浅谈 Vue v-model指令的实现原理

vue的v-model是一个十分强大的指令,它可以自动让原生表单组件的值自动和你选择的值绑定,

我们来看一下它的效果:

输入框的值和一个数据是绑定的,输入框的值变化,和他绑定的值也会发生变化

我们可以参照官方文档的例子    http://cn.vuejs.org/v2/guide/forms.html#文本

我们在手动输入 hello的过程中 下面和他绑定的p标签的值也是实时变化的

如此神奇的效果是如何实现的呢? 还是参照官方文档

http://cn.vuejs.org/v2/guide/components.html#使用自定义事件的表单输入组件

官方也说明了,v-model只不过是一个语法糖而已,真正的实现靠的还是

  1. v-bind:绑定响应式数据
  2. 触发 input 事件 并传递数据 (核心和重点)

现在我们也想设计自己的表单组件,也想通过 v-model暴露组件的值,怎么做呢?

例如我们要设计一个 自定义货币输入的组件, 通过 v-model暴露组件的值,我们可能使用如下的组件代码

<currency-input v-model="price"></currency-input>

然后再使用 这个我们自己定义的组件时, 组件内部会暴露出 组件的值到 v-model所绑定的值中去;那它是如何实现的呢?\

要搞明白v-model的实现,需要通过查看官方的自定义v-model组件示例的部分代码来进行说明

我们看上图中的代码,有行  $emit的代码,这行代码实际上会触发一个 input事件, 'input'后的参数就是传递给v-model绑定的属性的值,也就是说 v-model实现自定义的数据绑定的原理是这样的:

首先,大体的组件结构:

<custom-comp v-model="myattr">
  <input /> ??
  <select> ??
</custom-comp>

也就是自定义的组件内部一般包含原生的表单组件(当然非表单的组件也可以)

然后,给原生控件绑定事件,捕捉到原生组件的值,利用 $emit方法,触发input方法,组件监听到 input事件然后把值传入到myattr中.

这里有个疑问,为什么是 'input'呢??? 三个字,看文档!

这个就是 vue对 v-model实现的一个规则: 使用了v-model的组件会

自动监听 input 事件,并把这个input事件所携带的值 传递给v-model所绑定的属性!这样组件内部的值就给到了父组件了

通过以上讲解,我们总结一下如何利用v-model实现自定义的表单组件:

监听原生组件的事件,当获取到原生组件的值后把 值通过调用 $emit('input' ,data) 方法去触发 input事件

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • vue.js指令v-model使用方法

    vue.js的一大功能便是实现数据的双向绑定,本文就表单处理时运用v-model指令实现双向绑定做一个介绍: v-model这个指令只能用在<input>, <select>,<textarea>这些表单元素上,所谓双向绑定,指的就是我们在js中的vue实例中的data与其渲染的dom元素上的内容保持一致,两者无论谁被改变,另一方也会相应的更新为相同的数据.这是通过设置属性访问器实现的.例如: var data = { name: "erik", g

  • vue v-model表单控件绑定详解

    v-model 指令在表单控件元素上创建双向数据绑定,下面一一进行示例解释. 1.v-model 双向绑定文本 <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> <script type="text/javascript" src="vue.js&quo

  • vue.js指令v-model实现方法

    V-MODEL 是VUE 的一个指令,在input 控件上使用时,可以实现双向绑定. 通过看文档,发现他不过是一个语法糖. 实际是通过下面的代码来实现的: <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <!DOCTYPE html> <html lang="en">

  • vue 2.0组件与v-model详解

    前言 大家可能乍一看这个标题,可能会有疑问:v-model和组件也能扯到一起?在打算写这篇文章的时候,也是这么想的.咱们按简历的那一套STAR法则来梳理一下这篇文章: 情景[Situation]: 编写通用的输入组件时,子组件要绑定到父组件的某个变量上dataA,当父组件要拿到自组件的值时不能通过this.$children.xxx取值然后付给dataA, 而是父组件可以直接this.dataA就可以取到当前子组件最新值. 任务[Task]: 实现在父组件直接this.dataA就可以取到当前子

  • Vue2.0利用 v-model 实现组件props双向绑定的优美解决方案

    在项目中开始使用vue2来构建项目了,跟 vue1 很大的一处不同在于2 取消了props 的双向绑定,改成只能从父级传到子级的单向数据流,初衷当然是好的,为了避免双向绑定在项目中容易造成的数据混乱. 解决方案一 然后开始参考网上和github上的方案等等,发现很多解决方案是这样的 用data对象中创建一个props属性的副本 watch props属性 赋予data副本 来同步组件外对props的修改 watch data副本,emit一个函数 通知到组件外 这里以最常见的 modal为例子:

  • 利用Vue v-model实现一个自定义的表单组件

    功能描述: 通过点击按钮,可以增减购物数量 组件名称是 CouterBtn 最终效果如下 我们使用 vue-cli搭建基本的开发环境,这也是最快的进行 .vue组件开发的方式 对于入口组件  App.vue (可以暂时忽略其他细节,我们的重点是如何写组件) App.vue <template> <div id="app"> <h4>这是一个利用 v-model实现的自定义的表单组件</h4> <h6>CouterBtn组件的值

  • Vue 进阶教程之v-model详解

    Vue 官网教程上关于 v-model 的讲解不是十分的详细,写这篇文章的目的就是详细的剖析一下, 并介绍 Vue 2.2  v-model改进的地方,然后穿插的再说点 Vue 的小知识. 在 Vue 中,有许多方法和 Angular 相似,这主要是因为 Angular 是 Vue 早期开发的灵感来源.然而,Augular 中存在许多问题,在 Vue 中已经得到解决. v-model 用在 input 元素上时 v-model虽然很像使用了双向数据绑定的 Angular 的 ng-model,但

  • vue2 如何实现div contenteditable=“true”(类似于v-model)的效果

    发现问题 在 vue2 中对表单控件有着良好的双向数据绑定机制,但是对于要特定实现某些功能的输入时,我们就不得不使用到 contenteditable="true" 的 div ,而在这个 div 上是使用 v-model 是没有效果的.那么问题就来了,输入是非常需要双向绑定的,这里的双向数据绑定该如何实现? 解决思路一:自定义指令 当然,说在这一段的前面,这种解决方式在 vue2 中是不行的,为什么这么说,因为现在去搜索这个问题绝大多数的搜索结果是这个,所以放在前面. 实现的原理以及

  • Vue常用指令V-model用法

    v-model这个指令只能用在<input>, <select>,<textarea>这些表单元素上,所谓双向绑定,指的就是我们在js中的vue实例中的data与其渲染的dom元素上的内容保持一致,两者无论谁被改变,另一方也会相应的更新为相同的数据. <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title&

  • 浅谈vue 锚点指令v-anchor的使用

    如下所示: export default { inserted: function(el, binding) { el.onclick = function() { let total; if (binding.value == 0) { total = 0; } else { total = document.getElementById(`anchor-${binding.value}`).offsetTop; } let distance = document.documentElemen

  • 浅谈vue,angular,react数据双向绑定原理分析

    传统做法 前端维护状态,手动操作DOM更新视图.前端框架对服务器数据通过模版进行渲染.当用户产生了一个动作之后,我们通过document.getElementBy... 手动进行DOM更新. 框架帮忙分离数据和视图,后续状态更新需要手动操作DOM,因为框架只管首次渲染,不追踪状态监听变化. 双向数据绑定 当我们在前端开发中采用MV*的模式时,M - model,指的是模型,也就是数据,V - view,指的是视图,也就是页面展现的部分.通常,我们需要编写代码,将从服务器获取的数据进行"渲染&qu

  • 浅谈Vue的双向绑定和单向数据流冲突吗

    目录 前言 单向绑定 vs 双向绑定 单向数据流 vs 双向数据流 为什么说v-model只是语法糖 总结 参考资料 前言 众所周知,Vue中更加推荐单向数据流的状态管理模式(比如Vuex),但Vue同时支持通过v-model实现双向数据绑定.那么问题来了,单项数据流和双向数据绑定的概念,这两种不是相互冲突的吗?即然能用v-model双向数据绑定,不应该就是双向数据流了吗? 本文主要包括以下内容 单向绑定 vs 双向绑定 单向数据流 vs 双向数据流 为什么说v-model只是语法糖 单向绑定

  • 浅谈Vue.js

    vue.js的总体评价"简单却不失优雅,小巧而不乏大匠" Vue.js简介 Vue.js的作者为Evan You(尤雨溪),任职于Google Creative Lab,虽然Vue是一个个人项目,但在发展前景上个人认为绝不输于Google的AngularJs,下面我会将Vue与Angular(Angular 1.0+版本)做一些简单的比较. Vue的主要特点就和它官网(http://cn.vuejs.org/)所介绍的那样: (1) 简洁 (2) 轻量 (3)快速 (4) 数据驱动 (

  • 浅谈Vue.js 1.x 和 2.x 实例的生命周期

    在Vue.js中,在实例化Vue之前,它们都是以HTML的文本形式存在文本编辑器中.当实例化后将经历创建.编译.销毁三个主要阶段. 以下是Vue.js 1.x 实例的生命周期图示: Vue.js 1.x 的生命周期钩子 1. init 在实例开始初始化时同步调用.此时数据观测.事件和Watcher都尚未初始化. 2. created 在实例化创建之后同步调用.此时实例已经结束解析选项,已建立:数据绑定.计算属性.方法.Watcher/事件回调,但是还没有开始DOM编译,$el还不存在. 3. b

  • 浅谈Vue Element中Select下拉框选取值的问题

    之前写了.一个原生的select的,因为展示效果原因,给删除掉了,忘记保存代码了,现在大家展示使用elementUI的下拉框封装一个组件,供咱们项目中经常调用,减少代码量. html: <el-select v-model="ite" placeholder="请选择" value-key="mateGroup"> <el-option style="width: auto" :disabled="

  • 浅谈vue同一页面中拥有两个表单时,的验证问题

    问题:如果vue的同一个页面拥有两个表单.验证第一个表单时没有通过就切换到第二个,那么第二个表单会出现验证错误的信息 我们可以通过为两个表单添加ref属性 之后在通过调用resetFields()方法来解决问题 代码如下 <el-form :model="form" :rules="rules" ref="form" label-width="100px"> this.$refs["form"]

  • 浅谈vue权限管理实现及流程

    一.整体思路 后端返回用户权限,前端根据用户权限处理得到左侧菜单:所有路由在前端定义好,根据后端返回的用户权限筛选出需要挂载的路由,然后使用 addRoutes 动态挂载路由. 二.实现要点 (1)路由定义,分为初始路由和动态路由,一般来说初始路由只有 login,其他路由都挂载在 home 路由之下需要动态挂载. (2)用户登录,登录成功之后得到 token,保存在 sessionStorage,跳转到 home,此时会进入路由拦截根据 token 获取用户权限列表. (3)全局路由拦截,根据

  • 浅谈vue的第一个commit分析

    为什么写这篇vue的分析文章? 对于天资愚钝的前端(我)来说,阅读源码是件不容易的事情,毕竟有时候看源码分析的文章都看不懂.每次看到大佬们用了1-2年的vue就能掌握原理,甚至精通源码,再看看自己用了好几年都还在基本的使用阶段,心中总是羞愧不已.如果一直满足于基本的业务开发,怕是得在初级水平一直待下去了吧.所以希望在学习源码的同时记录知识点,可以让自己的理解和记忆更加深刻,也方便将来查阅. 目录结构 本文以vue的第一次 commit a879ec06 作为分析版本 ├── build │ └─

  • 浅谈vue中$bus的使用和涉及到的问题

    Hello大家周末好,最近项目比较忙所以没有及时的更新抱歉,今天给大家讲一vue.bus.使用过的都知道$bus是兄弟之间相互传值的项目中说实话用的地方不算多但是也会用到(每一个领域都是会有坑的呀). 1:创建$bus文件 创建一个文件内容如下: import Vue from 'vue' export default new Vue(); 2:引入$bus main.js: import Bus from './views/bus/bus'; Vue.prototype.$bus = Bus;

随机推荐