首先先要知道的是v-model的作用是实现数据的双向绑定,即:

数据在视图层的双向响应。

实现思路主要分为两步:

第一步:数据层到视图层的响应

将数据响应到视图层的方式,在vue2使用的是Object.defineProperty()来实现,需要劫持到数据的变化,在数据变化的时候将其渲染到视图上:

A,首先需要遍历data的数据,获取到每个data的属性

B,其次,获取到data的每个属性之后,对属性进行拦截。

C,在拦截时,需要将其值反映到对应的视图标签上。

第C步中又可以分为:

        a,获取到视图中每个节点的DOM对象, 

        b,遍历DOM对象,获取到每个DOM对象对应的node对象(节点对象)。

        c,遍历node对象,获取到node对象中含有v-model属性的节点

        d,将对应的data的属性值赋值给node节点的value值上

代码实现为:

<body>
<div id="app">
名字:<input type="text" v-model="name" value="12"><br>
年龄:<input type="text" v-model="age" value="2323">
<div class="sjkx">
<h1 class="name">模拟v-model</h1>
</div>
</div>
<script>
let data = {
name: '',
age: '',
}
let view = document.getElementById('app')
// 数据反映到视图方法
function getVmodelNode(view, data) {
// a,获取到视图中每个节点的DOM对象,
let allDom = view.getElementsByTagName("*")
let allDomArray = Array.from(allDom)//将伪数组转化成数组
let attributeArray = []
// b,遍历DOM对象,获取到每个DOM对象对应的node对象。
allDomArray.forEach(nodeItem => {
//c, 遍历node对象,过滤获取到node对象中含有v-model的节点
Array.from(nodeItem.attributes).forEach(item => {
if (item.nodeName === 'v-model') {
//d,将对应的data的属性值赋值给node节点的value值上
nodeItem.value = data[item.nodeValue]
}
})
})
}
// A,首先需要遍历data的数据,获取到每个data的属性
Object.keys(data).forEach(key => {
// B,其次,获取到data的每个属性之后,对属性进行拦截。
debugger
WebServer(data,key,data[key])
})
function WebServer(data, key, value) {
Object.defineProperty(data, key, {
get() {
return value
},
set(newValue) {
value= newValue
// C,在拦截时,需要将其值反映到对应的视图标签上。
getVmodelNode(view,data)
}
})
}
</script>
</body>

第二步:视图层到数据层的响应。

视图层响应到数据层的思路:当输入框的数据发生变化的时候,调用函数,将输入框的值赋值给data对应的属性上。

实际上就是在第一步的第C步多加了一步:为对应的node对象绑定一个input事件,并将node的value赋值给data对应的属性上。

<body>
<div id="app">
名字:<input type="text" v-model="name" value="12"><br>
年龄:<input type="text" v-model="age" value="2323">
<div class="sjkx">
<h1 class="name">模拟v-model</h1>
</div>
</div>
<script>
let data = {
name: '',
age: '',
}
let view = document.getElementById('app')
// 数据反映到视图方法
function getVmodelNode(view, data) {
// a,获取到视图中每个节点的DOM对象,
let allDom = view.getElementsByTagName("*")
let allDomArray = Array.from(allDom)//将伪数组转化成数组
let attributeArray = []
// b,遍历DOM对象,获取到每个DOM对象对应的node对象。
allDomArray.forEach(nodeItem => {
//c, 遍历node对象,过滤获取到node对象中含有v-model的节点
Array.from(nodeItem.attributes).forEach(item => {
if (item.nodeName === 'v-model') {
//d,将对应的data的属性值赋值给node节点的value值上
nodeItem.value = data[item.nodeValue]
//视图层反映到数据层上,
nodeItem.addEventListener('input',(e)=>{
data[item.nodeValue]=e.target.value
})
} }) })
}
// A,首先需要遍历data的数据,获取到每个data的属性
Object.keys(data).forEach(key => {
// B,其次,获取到data的每个属性之后,对属性进行拦截。 WebServer(data,key,data[key])
})
function WebServer(data, key, value) {
Object.defineProperty(data, key, {
get() {
return value
},
set(newValue) {
value= newValue
// C,在拦截时,需要将其值反映到对应的视图标签上。
getVmodelNode(view,data)
}
})
}
getVmodelNode(view, data)
</script>
</body>

这就是完整的模拟v-model的代码了。

关于优化,可移步到:

https://blog.csdn.net/qq_31539817/article/details/119992938

这边文章,通过定义发布者模式来实现精确更新。

顺着这个思路,vue中全部的指令源码都可以自己搞定,什么bind呀,什么v-text呀,甚至ref都可以自己搞定!!!!!!

使用JavaScript编写vue指令v-model,v-model原理实现的更多相关文章

  1. 深入浅出 JavaScript 变量、作用域和内存 v 0.5

    本文主要从原理入手分享变量和作用域的相关知识,最后结合本文所分享知识,再次深入了解下闭包的运行原理. 主要参考<JS高级程序设计> <JS权威指南> <高性能 JS> ...

  2. vue学习-day01(vue指令)

    目录: 1.什么是vue.js    2.为什么要学习前端的流行框架    3.框架和库的区别    4.后端MVC和前端的MVVM的区别    5.vue.js的基本代码--hollo world代 ...

  3. Vue 指令篇 案例(输入提交显示 提交数据_列表)

    一.文本操作指令 //1.v-text <p v-text="msg"></p> 等价于 <p>{{msg}}</p> //2.v- ...

  4. (尚016)Vue指令(11个自带指令+自定义指令)

    1.Vue常用指令 1)v:text:更新元素的 textContent 2)v-html:更新元素的 innerHTML 3)v-if:如果为true,当前标签才会输出到页面 4)v-else:如果 ...

  5. [Vue] : Vue指令

    Vue指令之 v-cloak v-cloak是解决解决插值表达式的闪烁问题 . 给插值表达式的元素加上v-cloak <p v-cloak>{{ msg }}</p> 为v-c ...

  6. Vue学习笔记【7】——Vue指令之v-model和双向数据绑定

    v-model是唯一可以实现双向数据绑定的vue指令 单向数据绑定:修改内存中的数据,页面上同步更改.v-bind <!-- v-bind 只能实现数据的单向绑定,从 M 自动绑定到 V, 无法 ...

  7. 第三篇:Vue指令

    Vue指令 1.文本指令相关 v-*是Vue指令,会被vue解析,v-text="num"中的num是变量(指令是有限的,不可以自定义) v-text是原样输出渲染内容,渲染控制的 ...

  8. 02 Vue指令

    Vue指令 1.文本相关指令 <div id="app"> <!-- 插值表达式 --> <p>{{ msg }}</p> < ...

  9. vue学习笔记(一) ---- vue指令(总体大纲)

    一.什么是Vue 官方文档:https://cn.vuejs.org/v2/guide/ 关键字: 渐进式框架 自底向上增量开发 视图层 单文件组件 复杂的单页应用 复杂的单页应用: 顾名思义,单页应 ...

  10. 【vuejs深入一】深入学习vue指令,自定义指令解决开发痛点

    写在前面  一个好的架构需要经过血与火的历练,一个好的工程师需要经过无数项目的摧残. 最近博主我沉淀了几个月,或者说懒了几个月.然而大佬的指点总是一针见血,能够让人看到方向.所以我现在有觉得,一个好的 ...

随机推荐

  1. 一键云部署:ROS的Terraform托管服务助你轻松上线2048经典游戏

    在现代云计算环境中,自动化部署已经成为一项重要的任务.Terraform,作为HashiCorp公司的一款开源工具,以其强大的基础设施即代码(IaC)能力,使得我们能够轻松管理和部署各种云资源. 阿里 ...

  2. 006. Gitlab组件介绍

    Gitlab组件 [root@master tools]# gitlab-ctl status #检查服务状态 run: gitaly: (pid 26704) 2201s; run: log: (p ...

  3. k8s——daemonset

    daemonset 为每一个匹配的node都部署一个守护进程 # daemonset node:type=logs daemonset 选择节点 - nadeSelector: 只调度到匹配指定的la ...

  4. react 过渡动画组件

    在项目中可能会有一些动画效果展示或是页面切换效果,css动画的方式,比较局限,涉及到一些js动画的时候没法处理了.react-transition-group是react的第三方模块,借住这个模块可以 ...

  5. IDEA 新建 MAVEN JAVA 控制台程序 Console

    IDEA 新建 MAVEN JAVA 控制台程序 Console File - New - Project-左侧选择 Maven,右侧勾选"Create from archetype&quo ...

  6. 流程控制之for循环结构

    1.for循环使用场景 1. 需要反复.重复执行的任务 2. 如创建100个用户,打印一百遍 chaoge666.插入数据库一万条数据等. 2.for语法 for 变量名 in 取值列表 do 每次循 ...

  7. MoneyPrinterPlus:AI自动短视频生成工具,赚钱从来没有这么容易过

    这是一个轻松赚钱的项目. 短视频时代,谁掌握了流量谁就掌握了Money! 所以给大家分享这个经过精心打造的MoneyPrinterPlus项目. 它可以:使用AI大模型技术,一键批量生成各类短视频. ...

  8. OAuth + Security - 错误收集

    Could not decode JSON for additional information: BaseClientDetails 完整的错误输出如下: 2019-12-03 22:18:37.2 ...

  9. 将链表以m长度为一组反转链表

    一群友分享的阿里面试题 1.将head链表以m为组反转链表(不足m则不反转): 例子:假设m=3. 链表 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> ...

  10. Ceph提供nfs服务

    目录 Ceph提供nfs服务 1. 前期准备 1.1 检查模块 1.2 检查是否有nfs-ganesha集群 2. 创建nfs服务 2.1 ceph提供的nfs的架构 3. nfs导出 3.1 创建c ...