“v-model”指令无法更新迭代变量本身

新手上路,请多包涵

我读了一篇关于 Renderless Components 的文章,它通过 $scopedSlots 属性将一个组件拆分为一个展示组件( 视图 部分)和一个无渲染组件( 逻辑 部分)。这是一个简单的 Tag 组件。当您按下 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>

但是, 它不起作用,似乎 newTag 总是”(空字符串),当我使用 SPA 方式时,模拟器说“’v-model’指令无法更新迭代变量’newTag’本身”,这里是 jsbin上 的demo

如文章中所述,解决方案是使用 :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>

我不知道为什么 v-model 不起作用。

编辑

上面的问题已经回答清楚了,而我看了一个参考链接后又遇到了一个问题,仍然是 v-model doesn’t work question


<!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>

正如我们所见,sp 是一个对象。为什么 v-model 这次似乎不起作用?

原文由 Archsx 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1k
2 个回答

考虑以下两个 JavaScript 示例:

 for (let value of array) {
  value = 10
}

 function (value) {
  value = 10
}

在这两种情况下,尝试将 10 分配给 --- value 只会在本地产生影响,不会产生超出本地范围的任何影响。例如,调用者不会受到更改的影响。

现在考虑这两个使用对象代替的示例,其中对象的形式为 { value: 9 }

 for (let valueWrapper of array) {
  valueWrapper.value = 10
}

 function (valueWrapper) {
  valueWrapper.value = 10
}

在这种情况下,更改不限于本地范围,因为我们正在更新对象。外部代码(例如函数的调用者)也会受到 value 属性更改的影响,因为它可以看到相同的对象。

这些示例等同于在各种情况下尝试使用 v-model 更新值。前两个例子等同于:

 <template v-for="value in array">
  <input v-model="value">
</template>

和:

 <template v-slot="{ value }">
  <input v-model="value">
</template>

传递给 v-slot 的参数可以被认为类似于函数参数。循环和作用域插槽都不会按预期工作,这与它们在纯 JavaScript 等效项中的作用完全相同。

然而,我的四个例子中的后两个相当于:

 <template v-for="valueWrapper in array">
  <input v-model="valueWrapper.value">
</template>

和:

 <template v-slot="{ valueWrapper }">
  <input v-model="valueWrapper.value">
</template>

这些应该可以正常工作,因为它们正在更新对象的属性。

然而,回到最初的问题,重要的是我们要绑定适当的对象。在这种情况下,我们需要绑定组件的 newTag 属性。将该属性复制到另一个对象也不起作用,因为 v-model 只会更新不相关的对象。

原文由 skirtle 发布,翻译遵循 CC BY-SA 4.0 许可协议

我的解决方案非常简单(参见 v-model="tags[index]" ):

而不是这样做:

 <template v-for="tag in tags">
    <TagView :key="tag.key" v-model="tag" />
</template>

你应该做这个:

 <template v-for="(tag, index) in tags">
    <TagView :key="tag.key" v-model="tags[index]" />
</template>

原因是您不能将迭代对象 tag 传递到 v-model 进行修改。请找到有关此的更多信息: Iterating a list of objects with foreach

原文由 ADM-IT 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏