首先先要知道的是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. ChatGPT-4o模型功能介绍

    1.概述 OpenAI 持续突破人工智能的边界,推出了其最新模型 ChatGPT-4o,作为 ChatGPT-4 的继承者,该模型有望带来显著的提升和创新功能.本文将深入解析 ChatGPT-4 与 ...

  2. QShop商城-快速开始-前端

    QShop商城-快速开始-前端 工具准备 NodeJs 前端环境为NodeJs,下载地址:http://nodejs.cn/download/current/ . 默认会用版本为Node 16,如找不 ...

  3. Android OpenMAX(一)漫谈

    在开始正式的学习前,我们先来聊一聊Android音视频开发中的一些问题.感受与想法.(有一点要事先说明,我的问题与答案.想法并不一定正确,请读者带着审慎的思考来阅读,后续的文章也是一样,希望读者边阅读 ...

  4. 8.19考试总结(NOIP模拟44)[Emotional Flutter·Medium Counting·Huge Counting·字符消除2 ]

    在自称善意的之时,即存恶意. 前言 几乎是大暑假的最后一次考试了. 我也迎来了我的第一次报零(雾 T1 Emotional Flutter 解题思路 比较考验思维能力,其实就是区间覆盖问题. 我考场上 ...

  5. C# .NET Unix 时间戳

    10 位时间戳: public static long GetTimeStampTen() { return (DateTime.Now.ToUniversalTime().Ticks - 62135 ...

  6. error pulling image configuration: Get https://eastasia.data.mcr.microsoft.com -- net/http: TLS handshake timeout

    error pulling image configuration: Get https://eastasia.data.mcr.microsoft.com/b29889755b1f4e46b6b44 ...

  7. java把时间戳转换成时间_(转)java时间与时间戳互转

    java中时间精确到毫秒级,所以需求时间需要 除以1000 //将时间转换为时间戳 public static String dateToStamp(String s) throws Exceptio ...

  8. FFmpeg开发笔记(三十)解析H.264码流中的SPS帧和PPS帧

    ​<FFmpeg开发实战:从零基础到短视频上线>一书的"2.1.1  音视频编码的发展历程"介绍了H.26x系列的视频编码标准,其中H.264至今仍在广泛使用,无论视频 ...

  9. 「C++」复杂模拟【壹】

    建议开启目录食用 阅读本文之前建议您先看这里,如果您已经看完了,那么就可以放心大胆的学习本文了. 我认为其实本文的难度还是比较大的,今天我们题是来自山东省省选,所以建议大家谨慎阅读,如果您是专业程序员 ...

  10. python重拾基础第四天

    本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1. 列表生成式,迭代器&生成器 列表生成式 我现在有个需求, ...