使用JavaScript编写vue指令v-model,v-model原理实现
首先先要知道的是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原理实现的更多相关文章
- 深入浅出 JavaScript 变量、作用域和内存 v 0.5
本文主要从原理入手分享变量和作用域的相关知识,最后结合本文所分享知识,再次深入了解下闭包的运行原理. 主要参考<JS高级程序设计> <JS权威指南> <高性能 JS> ...
- vue学习-day01(vue指令)
目录: 1.什么是vue.js 2.为什么要学习前端的流行框架 3.框架和库的区别 4.后端MVC和前端的MVVM的区别 5.vue.js的基本代码--hollo world代 ...
- Vue 指令篇 案例(输入提交显示 提交数据_列表)
一.文本操作指令 //1.v-text <p v-text="msg"></p> 等价于 <p>{{msg}}</p> //2.v- ...
- (尚016)Vue指令(11个自带指令+自定义指令)
1.Vue常用指令 1)v:text:更新元素的 textContent 2)v-html:更新元素的 innerHTML 3)v-if:如果为true,当前标签才会输出到页面 4)v-else:如果 ...
- [Vue] : Vue指令
Vue指令之 v-cloak v-cloak是解决解决插值表达式的闪烁问题 . 给插值表达式的元素加上v-cloak <p v-cloak>{{ msg }}</p> 为v-c ...
- Vue学习笔记【7】——Vue指令之v-model和双向数据绑定
v-model是唯一可以实现双向数据绑定的vue指令 单向数据绑定:修改内存中的数据,页面上同步更改.v-bind <!-- v-bind 只能实现数据的单向绑定,从 M 自动绑定到 V, 无法 ...
- 第三篇:Vue指令
Vue指令 1.文本指令相关 v-*是Vue指令,会被vue解析,v-text="num"中的num是变量(指令是有限的,不可以自定义) v-text是原样输出渲染内容,渲染控制的 ...
- 02 Vue指令
Vue指令 1.文本相关指令 <div id="app"> <!-- 插值表达式 --> <p>{{ msg }}</p> < ...
- vue学习笔记(一) ---- vue指令(总体大纲)
一.什么是Vue 官方文档:https://cn.vuejs.org/v2/guide/ 关键字: 渐进式框架 自底向上增量开发 视图层 单文件组件 复杂的单页应用 复杂的单页应用: 顾名思义,单页应 ...
- 【vuejs深入一】深入学习vue指令,自定义指令解决开发痛点
写在前面 一个好的架构需要经过血与火的历练,一个好的工程师需要经过无数项目的摧残. 最近博主我沉淀了几个月,或者说懒了几个月.然而大佬的指点总是一针见血,能够让人看到方向.所以我现在有觉得,一个好的 ...
随机推荐
- Vue cli之项目打包
在项目根目录中执行如下命令: npm run build 注:Vue脚手架打包的项目必须在服务器上运行,不能直接双击运行: 在打包之后项目中出现 dist 目录,dist 目录就是 Vue脚手架项目的 ...
- CSS——鼠标样式
在浏览网页的过程中,当我们将鼠标移动到一些元素上时,鼠标的样式会发生相应的改变,例如当鼠标指向文本时,鼠标的样式会变成类似大写字母I的样子:当鼠标指向链接时,鼠标会变成一个小手的形状等. 除了这些默认 ...
- 使用 CompeletedFuture 实现异步调用
在我们平时写的项目中,异步调用是一个比较重要的优化手段,在 Java 中,提供了 CompletedFuture 供我们使用,具体实现如下: 例子 假如现在有一个需求,我需要去淘宝.天猫和京东去搜索某 ...
- 美团面试:说说Netty的零拷贝技术?
零拷贝技术(Zero-Copy)是一个大家耳熟能详的技术名词了,它主要用于提升 IO(Input & Output)的传输性能. 那么问题来了,为什么零拷贝技术能提升 IO 性能? 1.零拷贝 ...
- Django路由层、视图层及模板层
Django路由层 URL配置(URLconf)就像Django所支撑网站的目录.它的本质是URL与要为该URL调用的视图函数之间的映射表; 你就是以这种方式告诉Django,对于客户端发来的某个UR ...
- 在线Base64转文件、文件转Base64工具
在线Base64转换神器,一键实现Base64编码与文件互转!支持图片.文档等各类文件,快速准确,安全无服务器存储.拖拽上传,轻松编码解码,提升开发效率.跨平台兼容,移动端友好,让数据转换再无障碍. ...
- Java编码规范-字符串与Integer的比较,BigDecimal非空参数
Java编码规范-字符串与Integer的比较,BigDecimal非空参数 package com.example.core.mydemo; import java.math.BigDecimal; ...
- OpenCV + sklearnSVM 实现手写数字分割和识别
这学期机器学习考核方式以大作业的形式进行考核,而且只能使用一些传统的机器学习算法. 综合再三,选择了自己比较熟悉的MNIST数据集以及OpenCV来完成手写数字的分割和识别作为大作业. 1. 数据集准 ...
- 简单的css3头像旋转与3D旋转效果
Tips:当你看到这个提示的时候,说明当前的文章是由原emlog博客系统搬迁至此的,文章发布时间已过于久远,编排和内容不一定完整,还请谅解` 简单的css3头像旋转与3D旋转效果 日期:2017-7- ...
- JAVA日期当天0点0分0秒
LocalDateTime LocalDateTime ldt = LocalDateTime.now(); LocalDateTime todayZero = LocalDateTime.of(ld ...