• 技术文章 >web前端 >Vue.js

    带你深入了解vue2中的 v-model,看看如何让组件支持该语法

    青灯夜游青灯夜游2022-01-04 19:12:20转载132
    本篇文章带大家了解一下vue2中的 v-model,看看v-model 是双向绑定还是单向数据流,如何让你开发的组件支持 v-model,希望对大家有所帮助。

    阅读本文

    你将:

    一、v-model 的本质是语法糖。

    v-model 本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。』 -- 官方文档。【相关推荐:vue.js教程

    什么是语法糖?

    语法糖,简单来说就是『便捷写法』。

    在大部分情况下, v-model="foo" 等价于 :value="foo" 加上 @input="foo = $event"

    <!-- 在大部分情况下,以下两种写法是等价的 -->
    <el-input v-model="foo" />
    
    <el-input :value="foo" @input="foo = $event" />

    没错,在大部分情况下如此。

    但也有例外:

    1.png

    2.png

    3.png

    4.png

    在编程思想上,这种帮助使用者『隐藏细节』的方式叫封装

    二、v-model 仅仅是语法糖吗?(冷知识)

    v-model 不仅仅是语法糖,它还有副作用。

    副作用如下:如果 v-model 绑定的是响应式对象上某个不存在的属性,那么 vue 会悄悄地增加这个属性,并让它响应式。

    举个例子,看下面的代码:

    // template中:
    <el-input v-model="user.tel"></el-input>
    // script中:
    export default {
      data() {
        return {
          user: {
            name: '公众号: 前端要摸鱼',
          }
        }
      }
    }

    响应式数据中没有定义 user.tel 属性,但是 template 里却用 v-model 绑定了 user.tel,猜一猜当你输入时会发生什么?

    看效果:

    5.gif

    揭晓答案吧:user 上会新增 tel 属性,并且 tel 这个属性还是响应式的。

    这就是『副作用』带来的效果,你学会了吗?

    三、 v-model 是双向绑定还是单向数据流?

    2.1 v-model 是双向绑定吗?

    是,官方说是。

    『你可以用 v-model 指令在表单 <input><textarea><select> 元素上创建双向数据绑定。』 —— vue2官方文档

    2.2 那 v-model 是单向数据流吗?

    是的,它甚至是单向数据流的典型范式。

    虽然官方没有明确表示这点,但我们可以捋一捋两者的关系。

    子组件不能改变父组件传递给它的 prop 属性,推荐的做法是它抛出事件,通知父组件自行改变绑定的值。

    v-model 做法完全符合单项数据流。甚至于,它给出了一种在命名和事件定义上的规范。

    众所周知 .sync 修饰符是单向数据流的另一个典型范式。

    6.png

    『单向数据流』总结起来其实也就8个字:『数据向下,事件向上』。

    四、如何让你开发的组件支持 v-model

    虽然不想说,但这确实是高频面试题。

    在定义 vue 组件时,你可以提供一个 model 属性,用来定义该组件以何种方式支持 v-model

    model 属性本身是有默认值的,如下:

    // 默认的 model 属性
    export default {
      model: {
        prop: 'value',
        event: 'input'
      }
    }

    也就是说,如果你不定义 model 属性,或者你按照当面方法定义属性,当其他人使用你的自定义组件时,v-model="foo" 就完全等价于 :value="foo" 加上 @input="foo = $event"

    如果把 model 属性进行一些改装,如下:

    // 默认的 model 属性
    export default {
      model: {
        prop: 'ame',
        event: 'zard'
      }
    }

    那么,v-model="foo" 就等价于 :ame="foo" 加上 @zard="foo = $event"

    没错,就是这么容易,让我们看个例子。

    先定义一个自定义组件:

    <template>
    <div>
      我们是TI{{ ame }}冠军
      <el-button @click="playDota2(1)">加</el-button>
      <el-button @click="playDota2(-1)">减</el-button>
    </div>
    </template>
    <script>
    export default {
      props: {
        ame: {
          type: Number,
          default: 8
        }
      },
      model: { // 自定义v-model的格式
        prop: 'ame', // 代表 v-model 绑定的prop名
        event: 'zard' // 代码 v-model 通知父组件更新属性的事件名
      },
      methods: {
        playDota2(step) {
          const newYear = this.ame + step
          this.$emit('zard', newYear)
        }
      }
    }
    </script>

    然后我们在父组件中使用该组件:

    // template中
    <dota v-model="ti"></dota>
    // script中
    export default {
      data() {
        return {
          ti: 8
        }
      }
    }

    看看效果:

    7.gif

    让你的组件支持 v-model 就这么容易。

    五、demo和源码

    获取源码请访问github

    https://github.com/zhangshichun/blog-vue2-demos/tree/master/src/views/about-v-model

    更多编程相关知识,请访问:编程视频!!

    以上就是带你深入了解vue2中的 v-model,看看如何让组件支持该语法的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:掘金社区,如有侵犯,请联系admin@php.cn删除
    专题推荐:vue2 v-model
    上一篇:详细介绍vue中vuex(详解及实例) 下一篇:推荐 20 个近期比较“火热”的Vue项目(值得收藏)

    相关文章推荐

    • 认识一下vue中的$attrs和$listeners属性,聊聊用法• 深入解析下vue3中的渲染系统• 尤雨溪解释vue3源码为啥不用?.可选链式操作符!• vue3项目keepAlive使用方法详解• 带你详解vue中实现全页面或局部刷新的方法• 一文你带快速认识Vue-Router路由

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网