Vue: 一个简单的Vue2.0 v-model双向数据绑定的实现,含源代码,小白也能看懂
首先说一下原理吧
View层(dom元素)的变动如何响应到Model层(Js变量)呢? 通过监听元素的input事件来动态的改变js变量的值,实际上不是改变的js变量的值,而是改变的js变量的getter的返回值
Model层(Js变量)的变动如何响应到View层(dom元素)呢?通过Object.defineProperty API的set回调方法可以劫持JS变量设置的新值newVal,然后将新值newVal设置给dom元素。
定义我们的view层
<input type="text" v-model="msg"><br>
<input type="text" v-model="msg"><br>
<input type="text" v-model="name">
定义我们的model代码
let data = {
msg: 'hello',
name: ''
}
定义我们的核心代码双向数据绑定
// 用户存放状态更改的新值
let reflect = {};
// 用于存放状态到dom元素的映射 也就是key是data里面的属性,value存的是数组domArr,domArr存放的是v-model等于key的元素
let deep = {};
// 查询到所有的含有v-modle属性的dom元素
document.querySelectorAll("[v-model]").forEach(item => {
// 获得dom元素的v-model的值
let model = item.getAttribute("v-model");
// 如果如果值所对应的映射数组为空的话 就初始化
deep[model] = deep[model] || [];
// 绑定状态和dom元素的映射关系
deep[model].push(item)
// 初始化dom元素的值 和 状态get的值
reflect[model] = item.value = data[model];
//监听dom元素的input事件
item.addEventListener('input', function(){
// 将dom元素的新值赋值给data中定义的状态
data[model] = item.value;
},false)
})
// 循环遍历所有状态
for(let [key, val] of Object.entries(data)){
// 通过Object.defineProperty来实现监听
Object.defineProperty(data, key, {
// 劫持状态更新的新值
set(newVal){
// 将更新的新值设置给get的返回值
reflect[key] = newVal;
// 循环将更新的新值设置给关联的的dom元素
deep[key] && deep[key].forEach(item => {
item.value = newVal;
})
return newVal;
},
// 返回状态的新值
get(){
return reflect[key];
}
})
}
此时,无论是改变input的值,还是改变data里面定义的状态,数据都会向另一端同步。
PS:这只是简单的实现了一下v-model,与Vue 2中的实现还是有一些差异的,原理都是相同的。
Vue: 一个简单的Vue2.0 v-model双向数据绑定的实现,含源代码,小白也能看懂的更多相关文章
- 小白也能看懂的Redis教学基础篇——做一个时间窗限流就是这么简单
不知道ZSet(有序集合)的看官们,可以翻阅我的上一篇文章: 小白也能看懂的REDIS教学基础篇--朋友面试被SKIPLIST跳跃表拦住了 书接上回,话说我朋友小A童鞋,终于面世通过加入了一家公司.这 ...
- vue3.0中的双向数据绑定方法
熟悉vue的人都知道在vue2.x之前都是使用object.defineProperty来实现双向数据绑定的 而在vue3.0中这个方法被取代了 1. 为什么要替换Object.definePrope ...
- 超简单的vue2.0分页组件
1.组件代码 <template> <div class="pagination_comment_style" style="width: 100%;o ...
- html一个页面链接携带参数跳转另一个页面基于vue2.0的element框架
来给生活比个耶! 1.按钮 <el-button @click="albumList(scope.row.id)" size="mini" type=&q ...
- 小白都能看懂的vue中各种通信传值方式,附带详细代码
1.路由通信传值 路由通信是通过路由跳转用query把参数带过去,也是vue常用的通信手段. 例子: 创建并在路由注册一个组件Head <template> <div id=&quo ...
- 【紧急】Log4j又发新版2.17.0,只有彻底搞懂漏洞原因,才能以不变应万变,小白也能看懂
1 事件背景 经过一周时间的Log4j2 RCE事件的发酵,事情也变也越来越复杂和有趣,就连 Log4j 官方紧急发布了 2.15.0 版本之后没有过多久,又发声明说 2.15.0 版本也没有完全解决 ...
- Angular2.0 基础:双向数据绑定 [(ngModel)]
在属性绑定中,值从模型到屏幕上的目标属性 (property). 通过把属性名括在方括号中来标记出目标属性,[]. 这是从模型到视图的单向数据绑定. 而在事件绑定中,值是从屏幕上的目标属性 到 mod ...
- centos7安装puppet详细教程(简单易懂,小白也可以看懂的教程)
简介: Puppet是一种linux.unix平台的集中配置管理系统,使用ruby语言,可配置文件.用户.cron任务.软件包.系统服务等.Puppet把这些系统实体称之为资源,它的设计目标是简化对这 ...
- 从壹开始前后端分离 [ Vue2.0+.NET Core2.1] 十五 ║Vue基础:JS面向对象&字面量& this字
缘起 书接上文<从壹开始前后端分离 [ Vue2.0+.NET Core2.1] 十四 ║ VUE 计划书 & 我的前后端开发简史>,昨天咱们说到了以我的经历说明的web开发经历的 ...
随机推荐
- 项目实战 Prometheus环境搭建
项目摘要: 本文是搭建一套prometheus环境的教程. 前期准备:准备三台虚拟机,本文以centos7为例. 项目具体实施:分别进入每台虚拟机设置hostname:# hostnamectl se ...
- Java爬虫系列四:使用selenium-java爬取js异步请求的数据
在之前的系列文章中介绍了如何使用httpclient抓取页面html以及如何用jsoup分析html源文件内容得到我们想要的数据,但是有时候通过这两种方式不能正常抓取到我们想要的数据,比如看如下例子. ...
- 【UE4 C++】学习笔记汇总
UE4 概念知识 基础概念--文件结构.类型.反射.编译.接口.垃圾回收.序列化[导图] GamePlay架构[导图] 类的继承层级关系[导图] 反射机制 垃圾回收机制/算法 序列化 Actor 的生 ...
- 离线状态迁移Anaconda虚拟环境
离线状态迁移Anaconda虚拟环境 同样是项目需求,需要布署的服务器上的Anaconda安装到了普通账户下 而后续所有的内容都需要通过root账户进行操作,而服务器已经布署,联网比较麻烦 本文提出, ...
- mybatis学习笔记(1)基本环境
1.pom引入 <dependencies> <dependency> <groupId>org.mybatis</groupId> <artif ...
- eureka服务端和客户端的简单搭建
本篇博客简单记录一下,eureka 服务端和 客户端的简单搭建. 目标: 1.完成单机 eureka server 和 eureka client 的搭建. 2.完成eureka server 的添加 ...
- Noip模拟49 2021.9.7
T1 reverse 又一道板子打假的挂分题,直接挂到倒二.. 考场上思路神奇,居然想到用$bfs$建边然后跑最短路, 其实当时也想到了直接$bfs$,但是不知道为啥觉得$dij$屌就没直接打$bfs ...
- 深入理解xLua基于IL代码注入的热更新原理
目前大部分手游都会采用热更新来解决应用商店审核周期长,无法满足快节奏迭代的问题.另外热更新能够有效降低版本升级所需的资源大小,节省玩家的时间和流量,这也使其成为移动游戏的主流更新方式之一. 热更新可以 ...
- DC综合与Tcl语法结构概述
转载:https://www.cnblogs.com/IClearner/p/6617207.html 1.逻辑综合的概述 synthesis = translation + logic optimi ...
- Oracle 19c 没有匹配的协议
Oracle12c连接问题ORA-28040:没有匹配的验证协议 造成改问题的原因是客户端版本太低.修改sqlnet.ora文件可以让服务器适配低版本的客户端 sqlnet.ora文件中加入 SQLN ...