关于 v-model

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

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

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


这个时候:

  • 我们在 input 文本框里修改 value 值,会影响 userName 这个 data 属性.
  • 我们在代码逻辑中,修改 this.userName = 'xxxx' 也会影响到 input 的 value 值.

原理也很简单.

  • data里的userName,被 Object.defineProperty() 定义后,具备了 set/get 的监听器.
  • input 元素本身就有 input 事件,能监听自己的 value 值修改.
  • 在对应的自己修改的时机里,修改对方的值即可.
image.png

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

  • 将对应的 data 属性 userName 绑定到 Dom.value 上.由于 data.userName 有 set,当值修改的时候,会同步更新 DOM.value
  • 被绑定的 DOM 元素会发布 @input 事件,当前组件根根据这个 input 来获取最新的 DOM.value 并同步被绑定的 data.userName

v-model 到底是怎么做的?

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

HTML 部分

 

JavaScript 部分

var app = new Vue({
    el: '#app',
    data: {
      userName: '李四'
    },
    methods: {
      // 我们在使用 v-model 时 会我们隐式添加这个事件响应方法.
      hanlderInputClick (e) {
        this.userName = e.target.value
        console.log(this.userName)
      }
    },
  })
  • 首先在 input 元素中,我们使用 :value='userName' 建立了 data -> dom 之间的单向数据流动关系.这样在 data 属性发生改变时(监听到 set),就可以同步的修改 input 的 value 值了.
  • 其次,我们在让 input 元素发布 input 事件,并让组件提供事件响应方法. 建立了 dom -> data 直接单向数据流动的关系. 这样,input 元素才发生 value 的 change 时,能同步的修改 data 里的值. dom -> data

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

  • 利用 :value="data" 建立 data -> dom 的流动关系.
  • 利用 @inutput 建立 dom -> data 的流动关系.

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

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

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


关于组件间的 v-model

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

  • 属性绑定到对应的 input
  • 对应的 input 像外发布 @input 事件.

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

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

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

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

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

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

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

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

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

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

组件是什么?

组件就是一个 js 对象.

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

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

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

查看下面这段代码

  • 首先 parentData 是 顶层 root 组件的一个 data 属性.
  • 接着在 child 组件标签上设置了 v-model='parentData'

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

但是问题是:

  • 在 input 元素,它有一个位置可以显示这个 parentData, 一般是 value 值.
  • 第二个,input 元素有 @input 事件,可以将自身 value 的改变,同步到 parentData 上.

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

首先,不管是什么鬼.

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

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

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

官方文档介绍说:

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

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

???

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

Vue.component('child',{
    props:['value']
    template: `

{{value}}

` })

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

一般v-model在常规的情况下,我们是用作于input表单元素的

当一个v-model作用与一个组件的时候,到底代表的是什么意思?

  let CompOne = {
    props:['value'], //v-model 等价于 :value='parentData' 所以这里写的是 value
    data () {
      return {
        msg: '我是compone组件'
      }
    },
    template: `
` }
image.png

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

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

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

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

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

 let CompOne = {
    props:['value'], //v-model 等价于 :value='parentData' 所以这里写的是 value
    data () {
      return {
        msg: '我是compone组件'
      }
    },
    template: `

一个可以发布 input 事件的元素:
一个普的 span 标签,没有 input 事件: {{value}}
`, methods: { // 让组件内的 input 元素,往外发布 input 事件. hanlderClick (e) { this.$emit('input',e.target.value) } }, }

查看结果:

image.png

结论

  • 在组件上使用 v-model ,会默认将这个值以 :value 的形式传递到组件的 props 上.
  • 我们在组件的内部,仍然需要自己拿到这个 props.value 在使用.
  • 一般使用到 input 元素上,可以在组件内部发布一个当前表单元素的 input 事件到外部.
  • 外部组件会默认的帮我们注册 input 事件的响应函数,并同步更新 v-model 传递过去的数据.

未完待续......

你可能感兴趣的:(关于 v-model)