关于 v-model

2019-07-17  本文已影响0人  人话博客

vue 开发开发中, v-model 是一个非常常用的属性.

常规模式下,我们给定当前组件的某个 data 属性值,并设置 v-model 到对应的 表单元素 的属性上.

这样就建立了 input 表单元素和 data 数据的双向绑定了.


<div id="app">
    <input type="text" v-model="userName" />
</div>

<script>
    new Vue({
        el: '#app',
        data: {
            userName: ''
        }
    })
</script>

这个时候:

原理也很简单.

image.png

也就是说,当我们使用 v-model 指令时,这个指令实质上帮我们做了两件事情:


v-model 到底是怎么做的?

现在不使用 v-model 指令,而是利用上述得出的规律,手动的完成 v-model 的特性.

HTML 部分

 <div id='app'>
    <!-- v-model 等价于下面这段HTML -->
    <input type="text" v-model="userName" />
    <!-- v-model做的事情. -->
    <input type="text" :value="userName" @input="hanlderInputClick" />
  </div>

JavaScript 部分

var app = new Vue({
    el: '#app',
    data: {
      userName: '李四'
    },
    methods: {
      // 我们在使用 v-model 时 会我们隐式添加这个事件响应方法.
      hanlderInputClick (e) {
        this.userName = e.target.value
        console.log(this.userName)
      }
    },
  })

所以, v-model 指令,就帮我们做了两件事情.

于是数据的双向流动关系就打通了.

所以 v-model="userName" 等价于 :value="userName" & @input="hanlderInputChange".(@input 事件监听以及 handlerInputChange 是 vue 在后帮我们自动提供的)

将数据绑定到 dom 上,并提供 dom 的@input 事件.


关于组件间的 v-model

根据上述内容,我们已经知道了 v-model 无非就是做了两件事情.

第一点什么好说的. 属性绑定任何元素可组件都可以非常方便的执行.

关键在于第二点,像外发布 @input 事件.

为什么 v-model 不能绑定在 DIV,p,<img /> .... 上 ?

常规情况下,这些元素都这是用于容器,或者展示静态文字和图片的 HTML 元素.

它基本不具备用户交互(这里的交互指的是编辑和修改)的功能(没有数据修改)

同时,它们也不具备类似 @input 事件. (即使有数据修改,也不能发布出来)

数据只能是单项的,从 data -> div,p, img.

所以我们现在知道了 v-model 一个非常重要的前提:

被绑定的元素必须包含可以变化自身数据 & 以及能将这种变化传递出去的能力.

那在组件上使用 v-model 是想表达什么意思呢?

组件是什么?

组件就是一个 js 对象.

里面包含一个数据,方法,以及最重要的 template 模板(render).

我们肉眼能看到的组件,就是 template 里的 HTML 模板外加一个数据展示.

那如果,我们在组件上使用 v-model ,对于这个组件来说,意味着什么呢?

查看下面这段代码

<div id='root'>
    <child v-model="parentData"></child>
</div>

在视觉上,就好像我们给一个 input 元素设置了 v-model 一样.

但是问题是:

在组件上写 v-model 是个什么鬼??

首先,不管是什么鬼.

我们在组件上写 v-model 并传递了数据 parentData.

主要的目的之一,肯定是希望在将 root 组件的 parentData 传递到 child 组件内部的.

child 组件内部如何去接受这个 parentData 这个值呢?

官方文档介绍说:

在组件上使用 v-model 会默认的设置到组件的 props 中名为 value 的属性值上.

根据上述说明,在组件上使用 v-model 可以等价于.

<div id='root'>
    <!--<child v-model='parentData'></child>-->
    <!--等价于-->
    <child :value='parentData'></child>
</div>

<child :value='parentData'></child>???

这不就是父组件向子组件传递数据的 props 语法么?

Vue.component('child',{
    props:['value']
    template: `<h1>{{value}}</h1>`
})

这样,在组件上使用 v-model 将数据从 root -> child 就已经打通了.

<div id='app'>
    <p>一般v-model在常规的情况下,我们是用作于input表单元素的</p>
    <input type="text" v-model="userName" />
    <!-- v-model到底做了什么事情? -->
    <!-- <input type="text" :value="userName" @input="hanlderInputClick">
    <button @click="hanlderClick">getUserName</button> -->
    <p>当一个v-model作用与一个组件的时候,到底代表的是什么意思?</p>
    <comp-one v-model="userName"></comp-one>
  </div>
  let CompOne = {
    props:['value'], //v-model 等价于 :value='parentData' 所以这里写的是 value
    data () {
      return {
        msg: '我是compone组件'
      }
    },
    template: `<div @click="hanlderClick">
        <label>{{msg}}</label>
        <input type='text' :value="value" />
      </div>`
  }
image.png

到目前为止,v-model 的数据从父组件传递到了子组件,且可以在子组件内部通过 props 在任意元素上去显示了.

但是数据流动只是单向的,从父组件传递到了子组件.

怎么才能在子组件中的数据修改之后,能够会传到父组件呢?

对于不可编辑修改以及没有往外发布变动实际的 span 来说,肯定是没戏了.

那如果我们利用组件内的那个 input 元素的事件呢?

 let CompOne = {
    props:['value'], //v-model 等价于 :value='parentData' 所以这里写的是 value
    data () {
      return {
        msg: '我是compone组件'
      }
    },
    template: `<div>
        <label>{{msg}}</label> <br />
        一个可以发布 input 事件的元素:<input type='text' :value="value" @input="hanlderClick" /> <br/>
        一个普的 span 标签,没有 input 事件: <span>{{value}}</span>
      </div>`,
    methods: {
    // 让组件内的 input 元素,往外发布 input 事件.
      hanlderClick (e) {
        this.$emit('input',e.target.value)
      }
    },
  }

查看结果:

image.png

结论

未完待续......

上一篇 下一篇

猜你喜欢

热点阅读