简单理解Vue响应式原理
2020/3/1 11:14:46
本文主要是介绍简单理解Vue响应式原理,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
该文章简单模拟Vue响应式原理(MVVM),笔者还只是个大三的学生,文章有很多不到之处欢迎各位大佬指出错误,多多交流。
这是Vue官方文档的响应式原理图
官方文档的东西对于初学者来说都有点晦涩难懂,本文就将以一种简单的方式来聊聊Vue的响应式原理。
问题提出
Vuejs是数据驱动型,数据发生改变界面也会刷新改变。但这并不是理所当然,在其内部做了很多复杂的操作。
-
思路
-
首先要搞懂Vue内部是如何监听数据的改变?
通过Object.definePropety这个方法来监听数据的改变。
这个方法的第三个参数的 Setters 和 Getters是关键。详情
-
已经监听了数据的改变,Vue是如何知道要通知哪些元素界面发生刷新呢?
通过发布订阅者模式。
Observer会监听所有的data属性并且给他们创建一一对应的Dep对象.
Compile 会解析模板中指令(同时也会将界面初始化)。 一个指令就创建一个Watcher对象, 然后添加到相对应的Dep对象的订阅中绑定更新函数。如果一个属性的value发生改变Observer就会通知所对应的Dep对象调用notify()通知所有的订阅者 更新界面。
详情看下图
PS:画图技术渣渣,见谅。
-
具体实现
笔者只是简单模拟,还没有达到可以剖析源码的程度。
- 先用正则做下Mustache语法(双大括号)转化。
//render.js var render = function(template, data) { const reg = /\{\{(\w+)\}\}/; //不做贪婪匹配 if (reg.test(template)) { //退出条件 false //是否需要编译 // vue源码模板编译用的正则方法 const key = reg.exec(template)[1] // console.log(key) template = template.replace(reg, data[key]); return render(template, data) //递归渲染 } // template.replace(/{{(.)+/) return template } 复制代码
- 上代码(代码有挺详细的注释)。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="app"> </div> <script src="./render.js"></script> <script> const obj = { //模拟数据 name: '张三', age: '18', sex: '男' } // 发布订阅者模式 class Dep { constructor() { this.subs = [] } addSub(watch) { //添加订阅方法 this.subs.push(watch) } notify() { //通知订阅者更新 this.subs.forEach(item => { item.update(); }) } } class Watch { constructor(name) { this.name = name; } update() { console.log(this.name + 'update') //更新视图 document.getElementById('app').innerHTML = render(template,obj) } } Object.keys(obj).forEach(key => { //遍历obj对象 let dep = new Dep; //创建发布者对象 let value = obj[key]; Object.defineProperty(obj, key, {//监听数据 set: function(newValue) { //数据改变 console.log( '数据' + key + '改变了') // 更新数据 value = newValue dep.notify() //通知订阅者更新 }, get: function() { //获取数据 console.log('数据' + key + '加入了响应式系统') let w = new Watch(value) dep.addSub(w); return value } }) }) obj.message = "没用的" //待编译的模板 var template = '我是{{name}}, {{name}} 年龄 {{age}},性别 {{sex}} 。 {{message}} ' document.getElementById('app').innerHTML = render(template,obj); </script> </body> </html> 复制代码
- 效果图如下
obj.message = "没用的"
这个数据没在初始化中,所有没有打印。即不是响应式属性。
Vue 不允许动态添加根级响应式属性,所以你必须在初始化实例前声明所有根级响应式属性。详情看文档声明响应式属性。
页面成功的发生了刷新。看到这差不多就能初步了解了响应式原理吧!
再次证明下message不是响应式属性。我们在Vue开发中要时刻注意这点,可以避免很多坑。
最后
笔者是一个入门前端不久的小白,这篇文章挺浅显的,可能也有一些错误,希望大佬们多多给点建议。如果这篇文章对你有那么一点点小帮助的话,不妨点个赞吧。
这篇关于简单理解Vue响应式原理的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-10-04package.json 文件位置在哪?-icode9专业技术文章分享
- 2024-10-01Craco.js学习:从入门到实践指南
- 2024-10-01Create-React-App学习:入门与实践指南
- 2024-10-01CSS-in-JS学习:从入门到实践指南
- 2024-09-30JSX语法学习:从入门到初步掌握
- 2024-09-30Mock.js学习:入门教程与实战演练
- 2024-09-30React Hooks学习:从入门到实践
- 2024-09-30受控组件学习:React中的基础入门教程
- 2024-09-29JS定时器教程:初学者必看指南
- 2024-09-29JS对象教程:初学者的全面指南