Vue的 v-model

今天被Vue的 v-model 给绕了一下,特在此记录一下;
https://cn.vuejs.org/v2/guide/components.html
下面是原文
定义事件也可以用于创建支持 v-model 的自定义输入组件。记住:

<input v-model="searchText">

等价于:(切记切记, searchText 是  input组件父组件的一个属性,因为我自己用 Ts 写组件时,总是很容易搞混)

<input
  v-bind:value="searchText"
  v-on:input="searchText = $event.target.value"
>

当用在组件上时,v-model 则会这样:
(切记切记, searchText 是custom-input组件父组件的一个属性,因为我自己用 Ts 写组件时,总是很容易搞混)

<custom-input
  v-bind:value="searchText"
  v-on:input="searchText = $event"
></custom-input>

这儿没有触发父组件任何的事件,而只是单纯的设置了 父组件的某一个属性;
并且,Vue对于原生的 Html Form元素和我们自己定义的 Vue - Componet  是进行了不同的处理的;
因为两处的 V-model 的代码是不一样的。。


这样,我们自己定义的组件,当绑定父组件的属性后,在input元素的值发生改变时,
必须能够接收一个内部 input 元素抛出的 input 事件,以便触发我们自己定义元素 (custom-input) 的 v-on:input 事件处理函数;
也就是Vue文档所说的:


为了让它正常工作,这个组件内的 <input> 必须:

  • 将其 value 特性绑定到一个名叫 value 的 prop 上
  • 在其 input 事件被触发时,将新的值通过自定义的 input 事件抛出

写成代码之后是这样的:

Vue.component('custom-input', {
  props: ['value'],
  template: `
    <input
      v-bind:value="value"
      v-on:input="$emit('input', $event.target.value)"
    >
  `
})

组件里面包含有原生的 input 元素的时候,很容易理解,
就是在 原生input元素触发 input 事件时,调用 $emit('input', $event.target.value) 
触发父元素的 input 事件,
而父元素的 v-model 类似于 , v-on:input="searchText = $event"  
//这儿的 $event 很明显已经不是 $event,  根据 input 元素的代码,  $emit('input', $event.target.value) , 而是 input 元素里面的 value; 
所以,searchText=value;  就获取到了元素的值了; 
而这个 searchText 是包含 custom-input 的 vue组件 里面的属性,所以啊,貌似工作的很好;
很好,但世界不是这么简单。。

还是上面的代码,

Vue.component('custom-input', { 
    props: ['value'], 
    template: 
        ` <input v-bind:value="value"   
          v-on:input="$emit('input', $event.target.value)"    > ` 
    }
)

Vue.component('wrap-custom-input', { 
    props: ['value'], 
    template: 
        ` <custom-input v-model="value">  ` 
    }
)

假如我把这个组件用到父组件里面,
也就是 :
<wrap-custom-input v-model='name'></wrap-custom-input>, 在输入框中输入了 abc 时,
使用 wrap-custom-input  的父组件里面的 name 的属性会是啥?
貌似也应该是 abc; 但是很可惜,不是;

为啥呢??
看看事件流程啊, 最里面的 input 元素输入了 abc 时,触发 input 元素的 v-on:inpu 事件,
也就是这一行代码:  v-on:input="$emit('input', $event.target.value)" 
然后触发了, customer-input 的 on:input 的事件处理, 
v-on:input="value= $event"  
这个没有疑问;   然后,就没有然后了。。
当然,不考虑警告的话,
(因为 vue 对于 Prop 不建议直接在子组件中直接修改(估计,以后会禁止直接修改)
customer-input 会设置父组件 wrap-custom-input 的 value,
而父组件 wrap-custom-input 的 value 又会去设置   wrap-custom-input 父组件的 name 属性,
这样,也能够间接修改 name 属性,

可惜,vue不喜欢警告,我也不喜欢;
咋样去除警告呢?
类似的,把 wrap-custom-input  的代码改成如下所示, 不就可以了。。

Vue.component('custom-input', { 
    props: ['value'], 
    template: 
        ` <input v-bind:value="value"   
          v-on:input="$emit('input', $event.target.value)"    > ` 
    }
)

Vue.component('wrap-custom-input', { 
    props: ['value'], 
    template: 
        ` <custom-input v-model="value"  v-on:input="$emit('input', $event)>  ` 
    }
)

以上只是猜想,实际验证一下呃。。
https://jsfiddle.net/hesi726/eywraw8t/418184/  
 

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>
<script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script>
</head>
<body>
<div id="app">
  <p>{{ message }}, Name: {{name}}, Abc: {{abc}}</p>
	V-model=Abc: <custom-input v-model='abc'></custom-input><br/>
	V-model=name: <wrap-custom-input v-model='name'></wrap-custom-input>
</div>

<script>
Vue.component('custom-input', { 
    props: ['value'], 
    template: 
       `<input v-bind:value="value" v-on:input="$emit('input', $event.target.value)"    >` 
    }
);
Vue.component('wrap-custom-input', { 
    props: ['value'], 
    template: 
       `<custom-input v-model="value"  v-on:input="$emit('input', $event)"></custom-input>` 
    }
);
new Vue({
  el: '#app',
  data: {
	  abc: '',
	name: '',  
    message: 'Hello Vue.js!'
  }
})
</script>
</body>
</html>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值