我读了一篇关于Renderless Components的文章,它通过 $scopedSlots 属性将一个组件拆分为一个展示组件(视图部分)和一个无渲染组件(逻辑部分)。这是一个简单的标签组件。当您按 enter 时,您将添加一个新标签
<!DOCTYPE html>
<html>
<head>
<script src="http://vuejs.org/js/vue.js"></script>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<div id="app">
<custom-component v-model="tags">
<div slot-scope="{tags,addTag,newTag}">
<span v-for="tag in tags">
{{tag}}
</span>
<input type="text" @keydown.enter.prevent="addTag" v-model="newTag">
</div>
</custom-component>
</div>
<script>
Vue.component('custom-component',{
props:['value'],
data(){
return {
newTag:''
}
},
methods:{
addTag(){
this.$emit('input',[...this.value,this.newTag])
this.newTag = ''
}
},
render(h){
return this.$scopedSlots.default({
tags:this.value,
addTag:this.addTag,
newTag:this.newTag
})
}
})
new Vue({
el:'#app',
data:{
tags:[
'Test',
'Design'
]
}
})
</script>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
但是,它不起作用,似乎 newTag 总是 ''(空字符串),当我使用 SPA 方式时,模拟器说“'v-model' 指令无法更新迭代变量 'newTag' 本身”,这里是jsbin 上的演示
解决方案是,如文章中所述,使用 :value 属性绑定和 @input 事件绑定,而不是 v-model。jsbin 上的演示
<!DOCTYPE html>
<html>
<head>
<script src="http://vuejs.org/js/vue.js"></script>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<div id="app">
<custom-component v-model="tags">
<div slot-scope="{tags,addTag,inputAttrs,inputEvents}">
<span v-for="tag in tags">
{{tag}}
</span>
<input type="text" v-bind="inputAttrs" v-on="inputEvents">
</div>
</custom-component>
</div>
<script>
Vue.component('custom-component',{
props:['value'],
data(){
return {
newTag:''
}
},
methods:{
addTag(){
this.$emit('input',[...this.value,this.newTag])
this.newTag = ''
}
},
render(h){
return this.$scopedSlots.default({
tags:this.value,
addTag:this.addTag,
inputAttrs:{
value:this.newTag
},
inputEvents:{
input:(e) => {
this.newTag = e.target.value
},
keydown:(e) => {
if(e.keyCode === 13){
e.preventDefault()
this.addTag()
}
}
}
})
}
})
new Vue({
el:'#app',
data:{
tags:[
'Test',
'Design'
]
}
})
</script>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
我不知道为什么 v-model 不起作用。
编辑
上面的问题已经回答清楚了,而我在阅读参考链接后又遇到了另一个问题,但仍然 v-model 不起作用问题
<!DOCTYPE html>
<html>
<head>
<script src="http://vuejs.org/js/vue.js"></script>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<div id="app">
<base-test v-slot="sp">
<input type="text" v-model="sp.foo">
<div>{{ sp}}</div>
</base-test>
</div>
<script>
Vue.component('base-test', {
template: `
<div>
<slot :foo="foo"></slot>
</div>
`,
data(){
return{
foo: 'Bar',
}
}
});
// Mount
new Vue({
el: '#app',
});
</script>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
正如我们所见, sp 是一个对象。为什么这次 v-model 似乎不起作用?
ADM*_*-IT 52
我的解决方案非常简单(请参阅v-model="tags[index]"):
而不是这样做:
<template v-for="tag in tags">
<TagView :key="tag.key" v-model="tag" />
</template>
Run Code Online (Sandbox Code Playgroud)
你应该做这个:
<template v-for="(tag, index) in tags">
<TagView :key="tag.key" v-model="tags[index]" />
</template>
Run Code Online (Sandbox Code Playgroud)
原因是您无法将迭代对象传递tag给v-model修改。请查找有关此内容的更多信息:Iterateing a list ofobjects with foreach
ski*_*tle 14
考虑以下两个 JavaScript 示例:
for (let value of array) {
value = 10
}
Run Code Online (Sandbox Code Playgroud)
function (value) {
value = 10
}
Run Code Online (Sandbox Code Playgroud)
在这两种情况下,尝试分配10给value只会在本地产生影响,不会产生超出本地范围的任何影响。例如,调用者不会受到更改的影响。
现在考虑这两个使用对象的示例,其中对象的形式为{ value: 9 }:
for (let valueWrapper of array) {
valueWrapper.value = 10
}
Run Code Online (Sandbox Code Playgroud)
function (valueWrapper) {
valueWrapper.value = 10
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,更改不仅限于本地范围,因为我们正在更新对象。外部代码(例如函数的调用者)也会受到此value属性更改的影响,因为它可以看到相同的对象。
这些示例相当于尝试v-model在各种情况下使用更新值。前两个示例等效于:
<template v-for="value in array">
<input v-model="value">
</template>
Run Code Online (Sandbox Code Playgroud)
和:
<template v-slot="{ value }">
<input v-model="value">
</template>
Run Code Online (Sandbox Code Playgroud)
传递给的参数v-slot可以被认为类似于函数参数。循环和作用域槽都不会按预期工作,这与它们在纯 JavaScript 等效项中不工作的完全相同。
但是,我的四个示例中的后两个等效于:
<template v-for="valueWrapper in array">
<input v-model="valueWrapper.value">
</template>
Run Code Online (Sandbox Code Playgroud)
和:
<template v-slot="{ valueWrapper }">
<input v-model="valueWrapper.value">
</template>
Run Code Online (Sandbox Code Playgroud)
这些应该可以正常工作,因为它们正在更新对象上的属性。
然而,回到最初的问题,我们绑定适当的对象很重要。在这种情况下,我们需要绑定newTag组件的属性。将该属性复制到另一个对象也行不通,v-model就像更新不相关的对象一样。
| 归档时间: |
|
| 查看次数: |
13006 次 |
| 最近记录: |