日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

Vue2.x響應式簡單講解及示例

瀏覽:17日期:2023-12-12 14:22:31
一、回顧Vue響應式用法

​ vue響應式,我們都很熟悉了。當我們修改vue中data對象中的屬性時,頁面中引用該屬性的地方就會發生相應的改變。避免了我們再去操作dom,進行數據綁定。

二、Vue響應式實現分析

對于vue的響應式原理,官網上給了出文字描述 https://cn.vuejs.org/v2/guide/reactivity.html 。

vue內部主要是通過數據劫持和觀察者模式實現的

數據劫持:

vue2.x內部使用Object.defineProperty https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

vue3.x內部使用的Proxy https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy

觀察者模式:https://www.jb51.net/article/219790.htm

內部成員示意圖

Vue2.x響應式簡單講解及示例

各個成員的功能

Vue:

把data中的成員注入到Vue實例中,并把data中的成員轉換為getter和setter

Observer:

對data對象中的簡單類型數據及對象進行監聽,當數據發生變化時通知Dep

Compiler:

解析每個元素中的指令/差值表達式,并替換成相應的數據

Dep:

觀察者模式中的通知者,添加觀察者,當數據變化時通知觀察者

Watcher:

每個引用data中的屬性的地方都有一個watcher對象,負責更新視圖

附:data對象中的屬性充當被觀察者,引用data對象中屬性的地方充當觀察者

三、Vue響應式源碼實現

Vue對象實現

功能

負責接受初始化的參數 把data中的屬性注入到data實例,轉換成getter和setter 調用Observer監聽data中所有屬性的變化 調用compiler解析指令、差值表達式.

class Vue{ constructor(options){// 1、通過屬性保存穿進來的屬性this.$options= options||{};this.$data= options.data||{};this.$el = typeof options.el ===’string’ ? document.querySelector(options.el) : options.el;// 2、把data參數中的數據轉換為getter和setter 掛載到Vue實例上this._proxyData(this.$data)// 3、調用observe對象監視data數據的變化new Observer(this.$data)// 4、調用compiler對象渲染頁面new Compiler(this) } _proxyData(data){if (data&&Object.keys(data).length>0){ for (const key in data) {Object.defineProperty(this,key,{ configurable:true, enumerable:true, get(){return data[key] }, set(value){if (data[key]===value) { return;}data[key]=value; }}) }} }}

Observer對象實現

功能

把data選項中的屬性進行數據劫持 data中的某個屬性也是對象的話,進行遞歸轉換成響應式對象 數據變化發送通知

//數據劫持 class Observer { constructor(data) {this.walk(data) } walk(data) { //1、判斷data是否是對象 if (!data || typeof data !== ’object’) { return}//2、循環調用defineReactive進行數據劫持Object.keys(data).forEach(key => { this.defineReactive(data, key, data[key])}) } defineReactive(obj, key, val) {//創建通知者const dep = new Dep()//使用walk把引用對象中的屬性變成響應式的this.walk(val)const that=this;Object.defineProperty(obj, key, { configurable: true, enumerable: true, get() {//通知者收集觀察者Dep.target && dep.addSub(Dep.target)return val; }, set(newVal) {if (newVal === val) { return;}val = newVal;that.walk(newVal)//被觀察者發生變化的時候,通知者對象給每個觀察者發送通知dep.notify() }}) }}

Compile對象實現

功能

負責編譯模板,解析指令、差值表達式 負責頁面首次渲染 當數據發生改變后,負責重新渲染視圖

//編譯器 class Compiler { constructor(vm) {this.el = vm.$el;this.vm = vm;this.compile(this.el) } //編譯模板 判斷節點是文本節點還是元素節點 compile(el) {let childNodes = el.childNodes;//處理第一層子節點Array.from(childNodes).forEach(node => { if (this.isTextNode(node)) {this.compileText(node) } else if (this.isElementNode(node)) {this.compileElement(node) } //如果當前節點還有子節點 遞歸調用編譯指令 if (node.childNodes && node.childNodes.length) {this.compile(node) }}) } //編譯元素節點,處理指令 compileElement(node) { //遍歷所有的指令Array.from(node.attributes).forEach(attr => { //判斷是不是指令節點 if (this.isDirective(attr.name)) {const nodeName = attr.name;const key = attr.nodeValue;const directive = nodeName.substr(2)this.updater(directive,node,key) }}) } updater(directive,node,key){const updaterFn = this[directive+'Updater']updaterFn && updaterFn.call(this,node,this.vm[key],key) } //v-text textUpdater(node,value,key){node.textContent=value//使用v-text表達式的地方就是一個觀察者new Watcher(this.vm,key,newValue => { node.textContent = newValue}) } //v-model modelUpdater(node,value,key){node.value =value//使用v-model表達式的地方就是一個觀察者new Watcher(this.vm,key,newValue => { node.value = newValue}) //實現雙向綁定node.addEventListener(’input’,()=>{ this.vm[key] = node.value}) } //v-html htmlUpdater(node,value,key){node.innerHTML = value//使用v-html表達式的地方就是一個觀察者new Watcher(this.vm,key,newValue => { node.innerHTML = newValue}) } //處理差值表達式 compileText(node) {//匹配差值表達式的正則let reg = /{{(.+?)}}///用正則匹配node的textContent,如果匹配到了 就替換if (reg.test(node.textContent)) { //獲取插值表達式的key let key = RegExp.$1; let value = node.textContent; node.textContent = value.replace(reg, this.vm[key]) //使用差值表達式的地方就是一個觀察者 new Watcher(this.vm,key,newValue => {node.textContent = newValue })} } //是否是指令 isDirective(attrName) {return attrName.startsWith(’v-’) } //是否是文本節點 isTextNode(node) {return node.nodeType === 3 } //是否是元素 isElementNode(node) {return node.nodeType === 1 }}

Dep對象實現

功能

收集依賴,添加觀察者 通知所有觀察者

//通知者類 class Dep { constructor() {//存儲觀察者this.subs = [] } /** * 收集觀察者 */ addSub(sub) {if (sub && sub.update) { this.subs.push(sub)} } /** * 通知觀察者改變狀態 */ notify() {this.subs.forEach(sub => { sub.update()}) }}

Watcher對象實現

功能

當數據變化時,Dep通知所有Watcher實例更新視圖 自身實例化的時候往Dep對象中添加自己

//觀察者類 class Watcher { constructor (vm,key,cb) {//Vue實例this.vm =vm;// data中的key對象this.key =key;// 更新視圖的回調函數this.cb = cb//把當前觀察者實例存放在Dep的target靜態屬性中Dep.target =this//觸發Observe的getter方法,把當前實例存放在Dep.subs中//data中key對應的舊值this.oldValue = this.vm[this.key]Dep.target = null } //每個觀察者都有一個update方法來改變狀態 update(){const newValue = this.vm[this.key]if ( this.newValue === this.oldValue ) { return}this.cb(newValue) }}

測試

<head> <meta charset='UTF-8'> <meta http-equiv='X-UA-Compatible' content='IE=edge'> <meta name='viewport' content='width=device-width, initial-scale=1.0'> <title>index</title> <script src='http://www.b3g6.com/bcjs/js/dep.js'></script> <script src='http://www.b3g6.com/bcjs/js/watcher.js'></script> <script src='http://www.b3g6.com/bcjs/js/compiler.js'></script> <script src='http://www.b3g6.com/bcjs/js/observer.js'></script> <script src='http://www.b3g6.com/bcjs/js/vue.js'></script></head><body> <p id='app'><h1>差值表達式</h1><h3>{{msg}}</h3><h3>{{count}}</h3><h1>v-text</h1><p v-text=’msg’></p><h1>v-model</h1><input type='text' v-model='msg' attr='msg'><input type='text' v-model='count'><h1>v-html</h1><p v-html='htmlText'></p> </p> <script>let vm = new Vue({ el:'#app', data:{msg:’信息’,count:’數量’, person:{name:’張三’},htmlText:'<p style=’color:red’>你好</p>' }}) </script></body>

到此這篇關于Vue2.x響應式簡單講解及示例的文章就介紹到這了,更多相關Vue2.x響應式內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Vue
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
精品美女久久| 蜜臀av国产精品久久久久 | 卡一卡二国产精品| 好吊一区二区三区| 国产精品久久久久av电视剧| 欧美视频二区| 蜜臀久久99精品久久久久宅男| 久久久精品国产**网站| 青青草国产成人99久久| 久久激五月天综合精品| 女人天堂亚洲aⅴ在线观看| 91欧美在线| 免费一级欧美片在线观看网站 | 日韩精品久久理论片| 999在线观看精品免费不卡网站| 日韩欧美少妇| 精品免费av| 国产精品hd| 国产精品久av福利在线观看| 日本a口亚洲| 日韩欧美另类中文字幕| 免费看久久久| 免费在线日韩av| 国产不卡av一区二区| 麻豆视频观看网址久久| 麻豆精品视频在线观看| 国产精品自拍区| 国产欧美日韩在线观看视频| 日韩av二区在线播放| 日本一不卡视频| 亚洲精品伦理| 午夜精品亚洲| 伊人久久成人| 久久99伊人| 日韩一区二区免费看| 亚洲一区二区免费看| 99pao成人国产永久免费视频 | 视频在线观看91| 视频在线在亚洲| 午夜电影一区| 婷婷综合电影| 久久亚洲精品伦理| 亚洲作爱视频| 亚洲我射av| 精品国产午夜肉伦伦影院| 欧美日韩国产观看视频| 亚洲www啪成人一区二区| 欧美日韩一区二区三区视频播放| 国产高清久久| 亚洲欧美日韩国产一区| 日韩欧美激情电影| 免费亚洲一区| 成人三级高清视频在线看| 91tv亚洲精品香蕉国产一区| 国产综合精品一区| 久久亚洲二区| 一本综合精品| 国产亚洲一卡2卡3卡4卡新区| 国产精品久久免费视频| 国产伊人久久| 色吊丝一区二区| 日韩电影二区| 国产精品腿扒开做爽爽爽挤奶网站| 丝袜诱惑制服诱惑色一区在线观看| 亚洲欧美网站| 欧美一区二区三区久久精品| 麻豆精品在线播放| 久久蜜桃精品| 美女国产一区| 国产精品v一区二区三区| 成人小电影网站| 久久久777| 免费在线观看视频一区| 国产情侣一区在线| av资源亚洲| 六月婷婷一区| 久久99精品久久久野外观看| 久久激情网站| 亚洲综合激情在线| 麻豆91精品视频| 免费观看久久av| 日韩有吗在线观看| 成人精品久久| 在线精品国产亚洲| 精品深夜福利视频| 中文国产一区| 91精品尤物| 日韩欧美二区| 亚洲精一区二区三区| 国产精品宾馆| 欧美亚洲激情| 国产一区二区三区视频在线| 噜噜噜久久亚洲精品国产品小说| 久久精品超碰| 亚洲激情中文| 国产精品1区| 黄色精品网站| 欧美极品一区二区三区| 亚洲黄色影院| 精品一区二区三区亚洲| 玖玖精品视频| 久久免费影院| 国产亚洲永久域名| 精品国产成人| 午夜精品影视国产一区在线麻豆| 免费在线小视频| 日韩精品一级| 久久天堂av| 国产精品成人**免费视频| 影院欧美亚洲| 国产欧美一区二区三区精品酒店 | 精品午夜久久| 亚洲精品免费观看| 欧美影院三区| 久久国产麻豆精品| 天堂资源在线亚洲| 美女久久久久久| 免费观看在线综合色| 国产v日韩v欧美v| 欧美一区二区三区久久精品| 欧美午夜不卡| 日韩电影免费网址| 日本aⅴ亚洲精品中文乱码 | 欧美国产日本| 亚洲精品欧洲| 天堂va蜜桃一区二区三区| 丝袜诱惑一区二区| 欧美一区精品| 蜜臀av一区二区三区| 日韩免费一区| 国产在线看片免费视频在线观看| 欧美精品国产白浆久久久久| 综合激情婷婷| 国产精品三上| 国产一区久久| 日韩美女一区二区三区在线观看| 国产精品调教| 青青国产精品| 亚洲资源网站| 免费美女久久99| 9色国产精品| 亚洲精品国产偷自在线观看| 日韩福利一区| sm捆绑调教国产免费网站在线观看 | 色综合视频一区二区三区日韩 | 免费看一区二区三区| 久久影院资源站| 欧美国产小视频| 99精品在线观看| 在线视频精品| 天堂精品久久久久| 欧美国产极品| 国产一区一一区高清不卡| 日韩欧美一区二区三区在线视频 | 日韩有码av| 国产精品男女| 国产一区不卡| 精品久久网站| 免费精品视频在线| 欧洲激情综合| 日韩一区二区在线免费| 美女黄网久久| 日韩精品中文字幕一区二区| 久久精品动漫| 国产高清一区| 日本欧美国产| 日韩区一区二| 国产伊人久久| 色8久久久久| 蜜桃tv一区二区三区| 伊人久久一区| 亚洲成人精品| 美女视频免费精品| 欧美a级一区| 成人在线免费观看网站| 日本伊人久久| 日本久久黄色| 欧美伊人久久| 一区二区三区四区日韩| 国产私拍福利精品视频二区| 激情婷婷欧美| 一区二区精品伦理...| 亚洲男女av一区二区| 97精品在线| 国产日产精品_国产精品毛片| 日韩在线免费| 国产一区二区三区黄网站| 婷婷成人av| 在线看片国产福利你懂的| 三级精品视频| 国产成人精品一区二区三区免费| 亚洲精品中文字幕乱码| 欧美亚洲二区| 亚洲综合婷婷| 九九综合在线| 国产无遮挡裸体免费久久| 蜜桃视频第一区免费观看| 日韩高清不卡在线| 在线视频观看日韩| 日韩国产一区二区|