Vue源码分析-手写Vue(简易版)
1.Vue双向绑定/MVVM响应式原理/v-model的原理
vue.js通过数据劫持结合发布订阅者模式,通过Object.defineProperty来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
2.Vue的发布订阅者模式
data中每个数据都绑定一个Dep,这个Dep中都存有所有用到该数据的观察者,
当数据改变时,发布消息给Dep,去通知每一个观察者,做出相应的回调函数。
3.MVVM原理
Model:Vue中的data数据
View:页面视图
ViewModel: model和view之间的枢纽,Vue源码
MVVM作为绑定的入口,整合observer,compile,watcher三者,通过observe来监听model数据变化,通过compile来解析编译模板指令,最终利用watcher搭起observe,compile之间的通信桥路,达到数据变化->视图更新,视图交互变化->数据model变更的双向绑定效果。
index.html
<!DOCTYPE html>
<header><title></title>
</header>
<body><div id="app"><h1>{{str}}</h1>{{str}}{{yy}}<button @click='btn'>按钮</button><input type="" name="" v-model='str'></div><script type="text/javascript" src="vue.js"></script><script>//vue是一个构造函数new Vue({el:'#app',data:{str:'你好',yy:'yaya'},//生命周期beforeCreate() {console.log('beforeCreate',this.$data,this.$el)},created() {console.log('created',this.$data,this.$el)},beforeMount() {console.log('beforeMount',this.$data,this.$el)},mounted() {console.log('mounted',this.$data,this.$el)},methods: {btn(e) {alert(1)console.log(e)this.str='hahaha'}}})</script></body>
</html>
vue.js
class Vue{constructor(options){// 将options挂到全局上this.$options=optionsthis.$watchEvent={}this.observe()if(typeof options.beforeCreate=='function') {options.beforeCreate.call(this)}//$datathis.$data=options.data//数据劫持this.proxyData()if(typeof options.created=='function') {options.created.call(this)}if(typeof options.beforeMount=='function') {options.beforeMount.call(this)}//节点$elthis.$el=document.querySelector(options.el)//模板解析this.compile(this.$el)if(typeof options.mounted=='function') {options.mounted.call(this)}}//数据劫持//1.给vue本身对象赋属性,来自data中;// 2.vue本身对象中的属性和data中的属性保持一致proxyData() {for(let k in this.$data) {Object.defineProperty(this,k,{get() {return this.$data[k]},set(val) {this.$data[k]=val}}) // console.log(this)}}//监听数据变化//触发data中的数据变化后执行watch中的updataobserve() {for(let key in this.$data) {let that=thislet value=this.$data[key]Object.defineProperty(this.$data,key,{get() {return value},set(val) {console.log('改变了')value=valif(that.$watchEvent[key]) {that.$watchEvent[key].forEach((item,index)=> {item.update()})}}}) } }//渲染compile(node){node.childNodes.forEach((item,index)=> {//文本节点if(item.nodeType==3) {let reg=/\{\{(.*?)\}\}/glet text=item.textContent//给节点赋值item.textContent=text.replace(reg,(match,key)=> {key=key.trim()if(this.hasOwnProperty(key)) {let watch=new Watcher(this,key,item,'textContent')//属性,节点,内容if(this.$watchEvent[key]) {this.$watchEvent[key].push(watch)}else {this.$watchEvent[key]=[]this.$watchEvent[key].push(watch)}}return this.$data[key]})}//元素节点if(item.nodeType==1) {// 判断元素节点是否绑定了自定义属性@clickif(item.hasAttribute('@click')) {// 获取自定义属性的值let fn=item.getAttribute('@click').trim()item.addEventListener('click',(e)=> {console.log(this.$options)// 执行绑定了自定义属性的事件this.$options.methods[fn]// 事件对象this.$options.methods[fn](e)})}//判断元素节点是否添加了v-model指令if(item.hasAttribute('v-model')) {let key=item.getAttribute('v-model').trim()if(this.hasOwnProperty(key)){// console.log(this[key])item.value=this[key]}item.addEventListener('input',(e)=> {this[key]=item.value})}// 元素节点中的文本节点if(item.childNodes.length>0) {this.compile(item)} }})}
}
//更新视图DOM
class Watcher{constructor(o,key,node,attr) {//对象this.o=o//属性名称this.key=key//结点this.node=node//改变文本节点内容的字符串this.attr=attr}// 更新操作update() {console.log(this.key)this.node[this.attr]=this.o[this.key]}
}
Vue源码分析-手写Vue(简易版)相关推荐
- Vue 源码之手写Vue Router
Vue 源码之手写Vue Router 源码地址:https://github.com/CONOR007/Handwritten-routing 一.Vue Router的两种模式 hash模式实现原 ...
- 面试必会之ArrayList源码分析手写ArrayList
作者:Java知音-微笑面对生活 简介 ArrayList是我们开发中非常常用的数据存储容器之一,其底层是数组实现的,我们可以在集合中存储任意类型的数据,ArrayList是线程不安全的,非常适合用于 ...
- 源码分析 | 手写mybait-spring核心功能(干货好文一次学会工厂bean、类代理、bean注册的使用)
小傅哥 | https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获.专注于原创专题案例编写,目前已完成的专题有:Netty4.x实战专题案例.用Java实现JVM.基于Ja ...
- Vue源码分析——第三章
Vue源码分析--第一章 Vue源码分析--第二章 // only used in dev mode//检测 val必需是数字function checkDuration(val, name, vno ...
- [Vue源码分析] 模板的编译
最近小组有个关于vue源码分析的分享会,提前准备一下- 前言: Vue有两个版本:Runtime + Compiler . Runtime only ,前者是包含编译代码的版本,后者不包含编译代码,编 ...
- vue源码分析系列二:$mount()和new Watcher()的执行过程
续vue源码分析系列一:new Vue的初始化过程 在initMixin()里面调用了$mount() if (vm.$options.el) {vm.$mount(vm.$options.el);/ ...
- Vue源码分析--Vue.component
Vue源码分析–Vue.component 我将非 Vue.component 的部分去掉了 export function initAssetRegisters (Vue: GlobalAPI) { ...
- [Vue源码分析]自定义事件原理及事件总线的实现
最近小组有个关于vue源码分析的分享会,提前准备一下- 前言: 我们都知道Vue中父组件可以通过 props 向下传数据给子组件:子组件可以通过向$emit触发一个事件,在父组件中执行回调函数,从而实 ...
- [Vue源码分析] v-model实现原理
最近小组有个关于vue源码分析的分享会,提前准备一下- 前言: 我们都知道使用v-model可以实现数据的双向绑定,及实现数据的变化驱动dom的更新,dom的更新影响数据的变化.那么v-model是怎 ...
最新文章
- 计算Be原子基态能级
- C++类型转换: static_cast const_cast reinterpret_cast dynamic_cast
- linux pdf转换swf,CENTOS 5 PDF转换为SWF
- Mind Master Pro 8.0——安装教程
- 《终身成长》读书笔记(part3)--如果一个人能学会什么东西,那么世界上其他人也都可以学会
- 基本响应性的Web设计测试工具
- [2020-09-11 CQBZ/HSZX多校联测 T2] 泰拳警告(组合数+数学期望)
- 学习swing鼠标点击事件心得体会_西门子COMOS软件开发定制学习8-查询列表间的数据交互...
- 地铁售票系统设计思想及部分代码
- 深入理解HDFS:Hadoop分布式文件系统
- 小鹏汽车4月交付量5147台 同比增长285%
- 牛客网算法工程师能力评估
- Android实现计算器布局(表格布局)
- pcap文件格式及写pcap文件
- OverFeat学习
- 云服务器性能对照表,云服务器 性能对比
- 爬虫goodreads数据_精通技术的读者正在设计自己更好的goodreads版本
- becon帧 wifi_beacon帧
- 戏说数据仓库,商业智能BI中数据仓库的本质是什么?
- 【Java刷题】04_二叉树的左右视图