'v-model'指令无法更新迭代变量本身 [英] 'v-model' directives cannot update the iteration variable itself

查看:215
本文介绍了'v-model'指令无法更新迭代变量本身的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我阅读了有关无渲染组件的文章,该文章将组件拆分为演示文稿组件(视图部分)和无渲染组件(逻辑部分),这是一个简单的Tag组件.当您按Enter时,您将添加一个新标签

I read an article about Renderless Components,it split a component into a presentational component (view part) and a renderless component(logical part) via $scopedSlots property.Here is a simple Tag component. when you press enter , you'll add a new tag

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

But,it doesn't work,it seems that the newTag always is ''(empty string), when I use SPA way, the emulator says "'v-model' directives cannot update the iteration variable 'newTag' itself" ,Here is demo on jsbin

解决方案是,如本文中所述,使用:value属性绑定和@input事件绑定,而不是v模型.jsbin上的演示

The solution is , as mentioned in the article ,use :value attribute binding, and an @input event binding ,instead of v-model. demo on 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模型不起作用.

I don't know why v-model doesn't work.

编辑

上面的问题已经清楚地回答了,虽然我在阅读参考链接后又遇到了另一个问题,但是v-model仍然无法正常工作

Questions above have been answered clearly, while I got another question after I read a reference link, and still 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模型似乎无法正常工作?

As we can see, sp is an object. why v-model seems to be not working this time?

推荐答案

请考虑以下两个JavaScript示例:

Consider the following two JavaScript examples:

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

function (value) {
  value = 10
}

在两种情况下,尝试将 10 分配给 value 只会在本地产生影响,而不会超出本地范围.例如,呼叫者将不受更改的影响.

In both cases trying to assign 10 to value will only have an effect locally, it won't have any impact beyond the local scope. The caller, for example, would not be affected by the change.

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

Now consider these two examples where an object is used instead, where the object is of the form { value: 9 }:

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

function (valueWrapper) {
  valueWrapper.value = 10
}

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

In this case the change is not limited to the local scope as we're updating objects. External code, such as the caller of the function, would also be impacted by this change to the value property as it can see the same object.

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

These examples are equivalent to trying to update a value using v-model in a variety of cases. The first two examples are equivalent to:

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

和:

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

传递给 v-slot 的参数非常类似于功能参数.循环和作用域范围的槽都无法按需工作,与纯JavaScript等效项完全不一样.

The arguments passed to v-slot can very much be thought of as analogous to function parameters. Neither the loop nor the scoped slot would work as desired, exactly the same as they don't for their pure JavaScript equivalents.

但是,我的四个示例中的后两个等同于:

However, the latter two of my four examples would be equivalent to:

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

和:

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

这些对象在更新对象的属性时应该可以正常工作.

These should work fine as they are updating a property on an object.

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

However, to go back to the original question, it's important that we're binding the appropriate object. In this case we would need to bind the newTag property of the component. Copying that property to another object wouldn't work either as v-model would just be updating an irrelevant object.

这篇关于'v-model'指令无法更新迭代变量本身的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆