首先先要知道的是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. 慢查询SQL优化

    记一次慢查询的SQL优化 测试表结构 MariaDB [shoppings]> desc login_userinfo; +------------+-------------+------+- ...

  2. Python OpenCV #1 - OpenCV介绍

    一.OpenCV介绍 1.1 OpenCV-Python教程简介 OpenCV由 Gary Bradsky 于1999年在英特尔创立,第一个版本于2000年发布. Vadim Pisarevsky 加 ...

  3. 开源一站式敏捷测试管理平台 itest(爱测试) 6.6.1 发布,安全升级及新增强

    (一)itest 简介及更新说明 itest 开源敏捷测试管理,testOps 践行者,极简的任务管理,测试管理,缺陷管理,测试环境管理,接口测试5合1,又有丰富的统计分析.可按测试包分配测试用例执行 ...

  4. vue 的directives一个坑

    大江东去,浪淘尽,千古风流人物.故垒西边,人道是,三国周郎赤壁.乱石穿空,惊涛拍岸,卷起千堆雪.江山如画,一时多少豪杰.遥想公瑾当年,小乔初嫁了,雄姿英发.羽扇纶巾,谈笑间,樯橹灰飞烟灭.故国神游,多 ...

  5. k8s——集群环境问题合集

    创建集群 k8s集群创建 集群环境问题合集 重置master节点 kubeadm reset -f # -f 强制重置 可选 重置node节点 # 当你的master节点重置后,node节点需要重新加 ...

  6. nodejs加jq来实现下载word文档

    先看效果 浏览器上: 下载的效果: 第一步是自己先搭建前端页面把自己写的结构数据全部传到后端 下面就是整个的结构 结构分析后端拿到数据后端解析: 第一层菜单层: { role: '分析报告', //顶 ...

  7. 红白机基本原理(二) CPU

    CPU 首发公号:Rand_cs NES 使用的 CPU 为 6502,但与标准的 6502 有些许不同,最大的不同在于 NES 使用的芯片拥有一个 pAPU(pseudo-Audio Process ...

  8. 闪迪SSD PLUS 128G CDM CrystalDiskMark

    闪迪SSD PLUS 128G CDM CrystalDiskMark 4k 读取才11,大号U盘水平. -- 对比三星SATA SSD. ..

  9. vm ware 安装 ubuntu server linux

    在:https://ubuntu.com/download/server 中下拉找到"Ubuntu Server 20.04 LTS",下载ISO. 在VM WARE 中,如果鼠标 ...

  10. C#.NET rabbit mq 持久化时报错 durable

    The AMQP operation was interrupted: AMQP close-reason, initiated by Peer, code=406, text='PRECONDITI ...