Posted 濂囪垶绮鹃€?/a> 銆怴u

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了相关的知识,希望对你有一定的参考价值。

鎻愬埌鈥滃搷搴斿紡鈥濅笁涓瓧锛屽ぇ瀹剁珛鍒绘兂鍒板暐锛熷搷搴斿紡甯冨眬锛熷搷搴斿紡缂栫▼锛?/p>

銆怴uejs銆戞帰绱?Vue.js 鍝嶅簲寮忓師鐞?>浠庡瓧闈㈡剰鎬濆彲浠ョ湅鍑猴紝鍏锋湁鈥滃搷搴斿紡鈥濈壒寰佺殑浜嬬墿浼氭牴鎹潯浠跺彉鍖栵紝浣垮緱鐩爣鑷姩浣滃嚭瀵瑰簲鍙樺寲銆傛瘮濡傚湪鈥滃搷搴斿紡甯冨眬鈥濅腑锛岄〉闈㈡牴鎹笉鍚岃澶囧昂瀵歌嚜鍔ㄦ樉绀轰笉鍚屾牱寮忋€?/p> 
 <p data-tool=Vue.js 涓殑鍝嶅簲寮忎篃鏄竴鏍凤紝褰撴暟鎹彂鐢熷彉鍖栧悗锛屼娇鐢ㄥ埌璇ユ暟鎹殑瑙嗗浘鑰朵細鐩稿簲杩涜鑷姩鏇存柊銆?/p>

鎺ヤ笅鏉ユ垜鏍规嵁涓汉鐞嗚В锛屽拰澶у涓€璧锋帰绱笅 Vue.js 涓殑鍝嶅簲寮忓師鐞嗭紝濡傛湁閿欒锛屾杩庢寚鐐桂煒簙~

涓€銆乂ue.js 鍝嶅簲寮忕殑浣跨敤

鐜板湪鏈変釜寰堢畝鍗曠殑闇€姹傦紝鐐瑰嚮椤甸潰涓?鈥渓eo鈥?鏂囨湰鍚庯紝鏂囨湰鍐呭淇敼涓衡€滀綘濂斤紝鍓嶇鑷範璇锯€濄€?/p>

鎴戜滑鍙互鐩存帴鎿嶄綔 DOM锛屾潵瀹屾垚杩欎釜闇€姹傦細

<span id="name">leo</span>
const node = document.querySelector('#name')
node.innerText = '浣犲ソ锛屽墠绔嚜涔犺';

瀹炵幇璧锋潵姣旇緝绠€鍗曪紝褰撴垜浠渶瑕佷慨鏀圭殑鏁版嵁鏈夊緢澶氭椂锛堟瘮濡傜浉鍚屾暟鎹澶氬寮曠敤锛夛紝杩欐牱鐨勬搷浣滃皢鍙樺緱澶嶆潅銆?/p>

鏃㈢劧璇村埌 Vue.js锛屾垜浠氨鏉ョ湅鐪?Vue.js 鎬庝箞瀹炵幇涓婇潰闇€姹傦細

<template>
<div id="app">
<span @click="setName">{{ name }}</span>
</div>
</template>

<script>
export default {
name: "App",
data() {
return {
name: "leo",
};
},
methods: {
setName() {
this.name = "浣犲ソ锛屽墠绔嚜涔犺";
},
},
};
</script>

瑙傚療涓婇潰浠g爜锛屾垜浠?span class="mq-34">閫氳繃鏀瑰彉鏁版嵁锛屾潵鑷姩鏇存柊瑙嗗浘銆傚綋鎴戜滑鏈夊涓湴鏂瑰紩鐢ㄨ繖涓?name 鏃讹紝瑙嗗浘閮戒細鑷姩鏇存柊銆?/p>

<template>
<div id="app">
<span @click="setName">{{ name }}</span>
<span>{{ name }}</span>
<span>{{ name }}</span>
<span>{{ name }}</span>
</div>
</template>

褰撴垜浠娇鐢ㄧ洰鍓嶄富娴佺殑鍓嶇妗嗘灦 Vue.js 鍜?React 寮€鍙戜笟鍔℃椂锛?span class="mq-40">鍙渶鍏虫敞椤甸潰鏁版嵁濡備綍鍙樺寲锛屽洜涓烘暟鎹彉鍖栧悗锛岃鍥句篃浼氳嚜鍔ㄦ洿鏂?/strong>锛岃繖璁╂垜浠粠绻佹潅鐨?DOM 鎿嶄綔涓В鑴卞嚭鏉ワ紝鎻愰珮寮€鍙戞晥鐜囥€?/p>

浜屻€佸洖椤捐瀵熻€呮ā寮?/span>

鍓嶉潰鍙嶅鎻愬埌鈥?span class="mq-45">閫氳繃鏀瑰彉鏁版嵁锛屾潵鑷姩鏇存柊瑙嗗浘鈥濓紝鎹釜璇存硶灏辨槸鈥?span class="mq-46">鏁版嵁鏀瑰彉鍚庯紝浣跨敤璇ユ暟鎹殑鍦版柟琚姩鍙戠敓鍝嶅簲锛屾洿鏂拌鍥?/strong>鈥濄€?/p>

鏄笉鏄湁绉嶇啛鎮夌殑鎰熻锛熸暟鎹棤闇€鍏虫敞鑷韩琚灏戝璞″紩鐢紝鍙渶鍦ㄦ暟鎹彉鍖栨椂锛岄€氱煡鍒板紩鐢ㄧ殑瀵硅薄鍗冲彲锛屽紩鐢ㄧ殑瀵硅薄浣滃嚭鍝嶅簲銆傛仼锛屾湁绉嶈瀵熻€呮ā寮忕殑鍛抽亾锛?/p>

鍏充簬瑙傚療鑰呮ā寮忥紝鍙槄璇绘垜涔嬪墠鍐欑殑銆?/p>

1. 瑙傚療鑰呮ā寮忔祦绋?/span>

瑙傚療鑰呮ā寮忚〃绀轰竴绉嶁€?span class="mq-55">涓€瀵瑰鈥濈殑鍏崇郴锛宯 涓瀵熻€呭叧娉?1 涓瑙傚療鑰咃紝琚瀵熻€呭彲浠ヤ富鍔ㄩ€氱煡鎵€鏈夎瀵熻€呫€傛帴涓嬪浘锛?/p>

銆怴uejs銆戞帰绱?Vue.js 鍝嶅簲寮忓師鐞?>鍦ㄨ繖寮犲浘涓紝绮変笣鎯冲強鏃舵敹鍒扳€滃墠绔嚜涔犺鈥濇渶鏂版枃绔狅紝鍙渶鍏虫敞鍗冲彲锛屸€滃墠绔嚜涔犺鈥濇湁鏂版枃绔狅紝浼氫富鍔ㄦ帹閫佺粰姣忎釜绮変笣銆傝杩囩▼涓紝鈥滃墠绔嚜涔犺鈥濇槸琚瀵熻€咃紝姣忎綅鈥滅矇涓濃€濇槸瑙傚療鑰呫€?/p> 
 <h3 data-tool=2. 瑙傚療鑰呮ā寮忔牳蹇?/span>

瑙傚療鑰呮ā寮忔牳蹇冪粍鎴愬寘鎷細n 涓瀵熻€呭拰 1 涓瑙傚療鑰呫€傝繖閲屽疄鐜颁竴涓畝鍗曡瀵熻€呮ā寮忥細

2.1 瀹氫箟鎺ュ彛

// 瑙傚療鐩爣鎺ュ彛
interface ISubject {
    addObserver: (observer: Observer) => void// 娣诲姞瑙傚療鑰?/span>
    removeObserver: (observer: Observer) => void// 绉婚櫎瑙傚療鑰?/span>
    notify: () => void// 閫氱煡瑙傚療鑰?/span>
}

// 瑙傚療鑰呮帴鍙?/span>
interface IObserver {
    update: () => void;
}

2.2 瀹炵幇琚瀵熻€呯被

// 瀹炵幇琚瀵熻€呯被
class Subject implements ISubject {
    private observers: IObserver[] = [];

    public addObserver(observer: IObserver): void {
        this.observers.push(observer);
    }

    public removeObserver(observer: IObserver): void {
        const idx: number = this.observers.indexOf(observer);
        ~idx && this.observers.splice(idx, 1);
    }

    public notify(): void {
        this.observers.forEach(observer => {
            observer.update();
        });
    }
}

2.3 瀹炵幇瑙傚療鑰呯被

// 瀹炵幇瑙傚療鑰呯被
class Observer implements IObserver {
    constructor(private name: string) { }

    update(): void {
        console.log(`${this.name} has been notified.`);
    }
}

2.4 娴嬭瘯浠g爜

function useObserver(){
    const subject: ISubject = new Subject();
    const Leo = new Observer("Leo");
    const Robin = new Observer("Robin");
    const Pual = new Observer("Pual");

    subject.addObserver(Leo);
    subject.addObserver(Robin);
    subject.addObserver(Pual);
    subject.notify();

    subject.removeObserver(Pual);
    subject.notify();
}

useObserver();
// [LOG]: "Leo has been notified." 
// [LOG]: "Robin has been notified." 
// [LOG]: "Pual has been notified." 
// [LOG]: "Leo has been notified." 
// [LOG]: "Robin has been notified." 

涓夈€佸洖椤?Object.defineProperty()

Vue.js 鐨勬暟鎹搷搴斿紡鍘熺悊鏄熀浜?JS 鏍囧噯鍐呯疆瀵硅薄鏂规硶 Object.defineProperty() 鏂规硶鏉ュ疄鐜帮紝璇ユ柟娉曚笉鍏煎 IE8 鍜?FF22 鍙婁互涓嬬増鏈祻瑙堝櫒锛岃繖涔熸槸涓轰粈涔?Vue.js 鍙兘鍦ㄨ繖浜涚増鏈箣涓婄殑娴忚鍣ㄤ腑鎵嶈兘杩愯鐨勫師鍥犮€?/p>

鐞嗚В Object.defineProperty() 瀵规垜浠悊瑙?Vue.js 鍝嶅簲寮忓師鐞?span class="mq-164">闈炲父閲嶈銆?/p>

Vue.js 3 浣跨敤 proxy 鏂规硶瀹炵幇鍝嶅簲寮忥紝涓よ€呯被浼硷紝鎴戜滑鍙渶鎼炴噦Object.defineProperty() 锛?proxy 涔熷氨宸笉澶氱悊瑙d簡銆?/p>

1. 姒傚康浠嬬粛

Object.defineProperty() 鏂规硶浼氱洿鎺ュ湪涓€涓璞′笂瀹氫箟涓€涓柊灞炴€э紝鎴栬€呬慨鏀逛竴涓璞$殑鐜版湁灞炴€э紝骞惰繑鍥炴瀵硅薄銆?璇硶濡備笅锛?/p>

Object.defineProperty(obj, prop, descriptor)
  • 鍏ュ弬璇存槑锛?

obj 锛氳瀹氫箟灞炴€х殑婧愬璞?/strong>锛?code class="mq-185">prop 锛氳瀹氫箟鎴栦慨鏀圭殑灞炴€у悕绉?/strong>鎴?Symbol锛?code class="mq-188">descriptor 锛氳瀹氫箟鎴栦慨鏀圭殑灞炴€ф弿杩扮锛屽寘鎷?configurable銆?code class="mq-191">enumerable銆?code class="mq-192">value銆?code class="mq-193">writable銆?code class="mq-194">get銆?code class="mq-195">set锛屽叿浣撶殑鍙互鍘诲弬闃呮枃妗o紱

  • 鍑哄弬璇存槑锛?

淇敼鍚庣殑婧愬璞°€?/p>

涓句釜绠€鍗曫煂颁緥瀛愶細

const leo = {};
Object.defineProperty(leo, 'age', { 
    value18,
    writablefalse
})
console.log(leo.age); // 18
leo.age = 22;
console.log(leo.age); // 22

2. 瀹炵幇 getter/setter

鎴戜滑鐭ラ亾 Object.defineProperty() 鏂规硶绗笁涓弬鏁版槸灞炴€ф弿杩扮锛?code class="mq-221">descriptor锛夛紝鏀寔璁剧疆 get 鍜?set 鎻忚堪绗︼細

  • get 鎻忚堪绗︼細褰? 璁块棶璇ュ睘鎬?/strong>鏃讹紝浼氳皟鐢ㄦ鍑芥暟锛岄粯璁ゅ€间负 undefined 锛?
  • set 鎻忚堪绗︼細褰? 淇敼璇ュ睘鎬?/strong>鏃讹紝浼氳皟鐢ㄦ鍑芥暟锛岄粯璁ゅ€间负 undefined 銆?

涓€鏃﹀璞℃嫢鏈変簡 getter/setter 鏂规硶锛屾垜浠彲浠ョ畝鍗曞皢璇ュ璞$О涓哄搷搴斿紡瀵硅薄銆?/p>

杩欎袱涓搷浣滅涓烘垜浠彁渚涙嫤鎴暟鎹繘琛屾搷浣滅殑鍙兘鎬э紝淇敼鍓嶉潰绀轰緥锛屾坊鍔?getter/setter 鏂规硶锛?/p>

let leo = {}, age = 18;
Object.defineProperty(leo, 'age', { 
    get(){
        // to do something
       console.log('鐩戝惉鍒拌姹傛暟鎹?);
        return age;
    },
    set(newAge){
        // to do something
       console.log('鐩戝惉鍒颁慨鏀规暟鎹?);
        age = newAge > age ? age : newAge
    }
})
leo.age = 20;  // 鐩戝惉鍒颁慨鏀规暟鎹?/span>
console.log(leo.age); // 鐩戝惉鍒拌姹傛暟鎹?nbsp; // 18

leo.age = 10;  // 鐩戝惉鍒颁慨鏀规暟鎹?/span>
console.log(leo.age); // 鐩戝惉鍒拌姹傛暟鎹?nbsp; // 10

璁块棶 leo 瀵硅薄鐨?age 灞炴€э紝浼氶€氳繃 get 鎻忚堪绗﹀鐞嗭紝鑰屼慨鏀?age 灞炴€э紝鍒欎細閫氳繃 set 鎻忚堪绗﹀鐞嗐€?/p>

鍥涖€佸疄鐜扮畝鍗曠殑鏁版嵁鍝嶅簲寮?/span>

閫氳繃鍓嶉潰涓や釜灏忚妭锛屾垜浠涔犱簡鈥滆瀵熻€呮ā寮忊€濆拰鈥?code class="mq-270">Object.defineProperty()鈥?鏂规硶锛岃繖涓や釜鐭ヨ瘑鐐瑰湪 Vue.js 鍝嶅簲寮忓師鐞嗕腑闈炲父閲嶈銆?/p>

鎺ヤ笅鏉ユ垜浠潵瀹炵幇涓€涓緢绠€鍗曠殑鏁版嵁鍝嶅簲寮忓彉鍖栵紝闇€姹傚涓嬶細鐐瑰嚮鈥滄洿鏂版暟鎹€濇寜閽紝鏂囨湰鏇存柊銆?/p>

銆怴uejs銆戞帰绱?Vue.js 鍝嶅簲寮忓師鐞?> 
 </figure> 
 <p data-tool=鎺ヤ笅鏉ユ垜浠皢瀹炵幇涓変釜绫伙細

  • Dep 琚瀵熻€呯被锛岀敤鏉ョ敓鎴愯瑙傚療鑰咃紱
  • Watcher 瑙傚療鑰呯被锛岀敤鏉ョ敓鎴愯瀵熻€咃紱
  • Observer 绫伙紝 灏嗘櫘閫氭暟鎹浆鎹负鍝嶅簲寮忔暟鎹紝浠庤€屽疄鐜板搷搴斿紡瀵硅薄銆?

鐢ㄤ竴寮犲浘鏉ユ弿杩颁笁鑰呬箣闂村叧绯伙紝鐜板湪鐪嬩笉鎳傛病鍏崇郴锛岃繖灏忚妭鐪嬪畬鍙互鍐嶅洖椤捐繖寮犲浘锛?img data-ratio="0.822866344605475" src="https://image.cha138.com/20210506/b544f070a23c4ec0b07a02f5b1458505.jpg" data-type="png" data-w="1863" _width="100%" class="mq-284" alt="銆怴uejs銆戞帰绱?Vue.js 鍝嶅簲寮忓師鐞?>

1. 瀹炵幇绮剧畝瑙傚療鑰呮ā寮?/span>

杩欓噷鍙傜収鍓嶉潰澶嶄範鈥滆瀵熻€呮ā寮忊€濈殑绀轰緥锛屽仛涓嬬簿绠€锛?/p>

// 瀹炵幇琚瀵熻€呯被
class Dep {
    constructor() {
        this.subs = [];
    }
    addSub(watcher) {
        this.subs.push(watcher);
    }
    notify(data) {
        this.subs.forEach(sub => sub.update(data));
    }
}
// 瀹炵幇瑙傚療鑰呯被
class Watcher {
    constructor(cb) {
        this.cb = cb;
    }
    update(data) {
        this.cb(data);
    }
}

Vue.js 鍝嶅簲寮忓師鐞嗕腑锛?span class="mq-309">瑙傚療鑰呮ā寮忚捣鍒伴潪甯搁噸瑕佺殑浣滅敤銆傚叾涓細

  • Dep 琚瀵熻€呯被锛屾彁渚涚敤鏉ユ敹闆嗚瀵熻€咃紙 addSub 锛夋柟娉曞拰閫氱煡瑙傚療鑰咃紙 notify 锛夋柟娉曪紱
  • Watcher 瑙傚療鑰呯被锛屽疄渚嬪寲鏃舵敮鎸佷紶鍏ュ洖璋冿紙 cb 锛夋柟娉曪紝骞舵彁渚涙洿鏂帮紙 update 锛夋柟娉曪紱

2. 瀹炵幇鐢熸垚鍝嶅簲寮忕殑绫?/span>

杩欎竴姝ラ渶瑕佸疄鐜?Observer 绫伙紝鏍稿績鏄€氳繃 Object.defineProperty() 鏂规硶涓哄璞$殑姣忎釜灞炴€ц缃?getter/setter锛岀洰鐨勬槸灏嗘櫘閫氭暟鎹浆鎹负鍝嶅簲寮忔暟鎹紝浠庤€屽疄鐜板搷搴斿紡瀵硅薄銆?/p>

銆怴uejs銆戞帰绱?Vue.js 鍝嶅簲寮忓師鐞?> 
 </figure> 
 <p data-tool=杩欓噷浠ユ渶绠€鍗曠殑鍗曞眰瀵硅薄涓轰緥锛堜笅涓€鑺備細浠嬬粛娣卞眰瀵硅薄锛夛紝濡傦細

let initData = {
    text'浣犲ソ锛屽墠绔嚜涔犺',
    desc'姣忔棩娓呮櫒锛屼韩鍙椾竴绡囧墠绔紭绉€鏂囩珷銆?
};

鎺ヤ笅鏉ュ疄鐜?Observer 绫伙細

// 瀹炵幇鍝嶅簲寮忕被锛堟渶绠€鍗曞崟灞傜殑瀵硅薄锛屾殏涓嶈€冭檻娣卞眰瀵硅薄锛?/span>
class Observer {
    constructor (node, data) {
        this.defineReactive(node, data)
    }

    // 瀹炵幇鏁版嵁鍔寔锛堟牳蹇冩柟娉曪級
    // 閬嶅巻 data 涓墍鏈夌殑鏁版嵁锛岄兘娣诲姞涓?nbsp;getter 鍜?nbsp;setter 鏂规硶
    defineReactive(vm, obj) {
        //姣忎竴涓睘鎬ч兘閲嶆柊瀹氫箟get銆乻et
        for(let key in obj){
            let value = obj[key]锛?nbsp;dep = new Dep();
            Object.defineProperty(obj, key, {
                enumerabletrue,
                configurabletrue,
                get() {
                    // 鍒涘缓瑙傚療鑰?/span>
                    let watcher = new Watcher(v => vm.innerText = v);
                    dep.addSub(watcher);
                    return value;
                },
                set(newValue) {
                    value = newValue;
                    // 閫氱煡鎵€鏈夎瀵熻€?/span>
                    dep.notify(newValue);
                }
            })
        }
    }
}

涓婇潰浠g爜鐨勬牳蹇冩槸 defineReactive 鏂规硶锛屽畠閬嶅巻鍘熷瀵硅薄涓瘡涓睘鎬э紝涓烘瘡涓睘鎬у疄渚嬪寲涓€涓瑙傚療鑰咃紙Dep锛夛紝鐒跺悗鍒嗗埆璋冪敤 Object.defineProperty() 鏂规硶锛屼负姣忎釜灞炴€ф坊鍔?getter/setter銆?/p>

  • 璁块棶鏁版嵁鏃讹紝getter 鎵ц渚濊禆鏀堕泦锛堝嵆娣诲姞瑙傚療鑰咃級锛岄€氳繃瀹炰緥鍖? Watcher 鍒涘缓涓€涓瀵熻€咃紝骞舵墽琛岃瑙傚療鑰呯殑 addSub() 鏂规硶娣诲姞涓€涓瀵熻€咃紱
  • 淇敼鏁版嵁鏃讹紝setter 鎵ц娲惧彂鏇存柊锛堝嵆閫氱煡瑙傚療鑰咃級锛岄€氳繃璋冪敤琚瀵熻€呯殑 notify() 鏂规硶閫氱煡鎵€鏈夎瀵熻€咃紝鎵ц瑙傚療鑰? update() 鏂规硶銆?

3. 娴嬭瘯浠g爜

涓轰簡鏂逛究瑙傚療鏁版嵁鍙樺寲锛屾垜浠负鈥滄洿鏂版暟鎹€濇寜閽粦瀹氱偣鍑讳簨浠舵潵淇敼鏁版嵁锛?/p>

<div id="app"></div>
<button id="update">鏇存柊鏁版嵁</button>

娴嬭瘯浠g爜濡備笅锛?/p>

// 鍒濆鍖栨祴璇曟暟鎹?/span>
let initData = {
    text'浣犲ソ锛屽墠绔嚜涔犺',
    desc'姣忔棩娓呮櫒锛屼韩鍙椾竴绡囧墠绔紭绉€鏂囩珷銆?
};

const app = document.querySelector('#app');

// 姝ラ1锛氫负娴嬭瘯鏁版嵁杞崲涓哄搷搴斿紡瀵硅薄
new Observer(app, initData);

// 姝ラ2锛氬垵濮嬪寲椤甸潰鏂囨湰鍐呭
app.innerText = initData.text;

// 姝ラ3锛氱粦瀹氭寜閽簨浠讹紝鐐瑰嚮瑙﹀彂娴嬭瘯
document.querySelector('#update').addEventListener('click'function(){
    initData.text = `鎴戜滑蹇呴』缁忓父淇濇寔鏃х殑璁板繂鍜屾柊鐨勫笇鏈涖€俙;
    console.log(`褰撳墠鏃堕棿锛?span class="mq-430">${new Date().toLocaleString()}`
)
})

娴嬭瘯浠g爜涓紝鏍稿績鍦ㄤ簬閫氳繃瀹炰緥鍖?Observer锛屽皢娴嬭瘯鏁版嵁杞崲涓哄搷搴斿紡鏁版嵁锛岀劧鍚庢ā鎷熸暟鎹彉鍖栵紝鏉ヨ瀵熻鍥惧彉鍖栥€?姣忔鐐瑰嚮鈥滄洿鏂版暟鎹€濇寜閽紝鍦ㄦ帶鍒跺彴涓兘鑳界湅鍒扳€滄暟鎹彂鐢熷彉鍖栵紒鈥濈殑鎻愮ず锛岃鏄庢垜浠凡缁忚兘閫氳繃 setter 瑙傚療鍒版暟鎹殑鍙樺寲鎯呭喌銆?img data-ratio="0.6197916666666666" src="/img?url=https://mmbiz.qpic.cn/mmbiz_png/dy9CXeZLlCUenf0nfYZEiclLVFDmoFwpderUrONaQR16epBia74tibJFVYFogROwX3HbtAibvictGhCy8IM9aia8un1w/640?wx_fmt=png" data-type="png" data-w="1920" _width="100%" class="mq-435" alt="銆怴uejs銆戞帰绱?Vue.js 鍝嶅簲寮忓師鐞?>

褰撶劧锛屼綘杩樺彲浠ュ湪鎺у埗鍙版墜鍔ㄤ慨鏀?initData 瀵硅薄涓殑 text 灞炴€э紝鏉ヤ綋楠屽搷搴斿紡鍙樺寲~~銆怴uejs銆戞帰绱?Vue.js 鍝嶅簲寮忓師鐞?></p> 
 <p data-tool=鍒拌繖閲岋紝鎴戜滑瀹炵幇浜嗛潪甯哥畝鍗曠殑鏁版嵁鍝嶅簲寮忓彉鍖栵紝褰撶劧 Vue.js 鑲畾娌℃湁杩欎箞绠€鍗曪紝杩欎釜鍏堢悊瑙o紝涓嬩竴鑺傜湅 Vue.js 鍝嶅簲寮忓師鐞嗭紝鎬濊矾灏变細娓呮櫚寰堝銆?/p>

鍙互鍐嶅洖椤句笅杩欏紶鍥撅紝瀵规暣涓繃绋嬩細鏇存竻鏅帮細

銆怴uejs銆戞帰绱?Vue.js 鍝嶅簲寮忓師鐞?> 
 </figure> 
 <h2 data-tool=浜斻€乂ue.js 鍝嶅簲寮忓疄鐜?/span>

鏈妭浠g爜锛歨ttps://github.com/pingan8787/Leo-javascript/blob/master/Cute-Gist/Vue/leo-vue-reactive/

杩欓噷澶у鍙互鍐嶅洖椤句笅涓嬮潰杩欏紶瀹樼綉缁忓吀鐨勫浘锛屾€濊€冧笅鍓嶉潰璁茬殑绀轰緥銆?img data-ratio="0.625" src="/img?url=https://mmbiz.qpic.cn/mmbiz_png/dy9CXeZLlCUenf0nfYZEiclLVFDmoFwpd2vJRTR80IJ6Q33SH9vTiaXdM8GeaicB8PatGpib0jbYcWDhhXDDqR2Iww/640?wx_fmt=png" data-type="png" data-w="1200" _width="100%" class="mq-451" alt="銆怴uejs銆戞帰绱?Vue.js 鍝嶅簲寮忓師鐞?>

锛堝浘鐗囨潵鑷細https://cn.vuejs.org/v2/guide/reactivity.html锛?/p>

涓婁竴鑺傚疄鐜颁簡绠€鍗曠殑鏁版嵁鍝嶅簲寮忥紝鎺ヤ笅鏉ョ户缁€氳繃瀹屽杽璇ョず渚嬶紝瀹炵幇涓€涓畝鍗曠殑 Vue.js 鍝嶅簲寮忥紝娴嬭瘯浠g爜濡備笅锛?/p>

// index.js
const vm = new Vue({
    el'#app',
    data(){
        return {
            text'浣犲ソ锛屽墠绔嚜涔犺',
            desc'姣忔棩娓呮櫒锛屼韩鍙椾竴绡囧墠绔紭绉€鏂囩珷銆?
        }
    }
});

鏄笉鏄緢鏈夊唴鍛充簡锛屼笅闈㈡槸鎴戜滑鏈€缁堝疄鐜板悗椤圭洰鐩綍锛?/p>

- mini-reactive
 / index.html   // 鍏ュ彛 HTML 鏂囦欢
  / index.js     // 鍏ュ彛 JS 鏂囦欢
  / observer.js  // 瀹炵幇鍝嶅簲寮忥紝灏嗘暟鎹浆鎹负鍝嶅簲寮忓璞?br>  / watcher.js   // 瀹炵幇瑙傚療鑰呭拰琚瀵熻€咃紙渚濊禆鏀堕泦鑰咃級
  / vue.js       // 瀹炵幇 Vue 绫讳綔涓轰富鍏ュ彛绫?br>  / compile.js   // 瀹炵幇缂栬瘧妯$増鍔熻兘

鐭ラ亾姣忎竴涓枃浠跺姛鑳戒互鍚庯紝鎺ヤ笅鏉ュ皢姣忎竴姝ヤ覆鑱旇捣鏉ャ€?/p>

1. 瀹炵幇鍏ュ彛鏂囦欢

鎴戜滑棣栧厛瀹炵幇鍏ュ彛鏂囦欢锛屽寘鎷?index.html / index.js  2 涓畝鍗曟枃浠讹紝鐢ㄦ潵鏂逛究鎺ヤ笅鏉ョ殑娴嬭瘯銆?/p>

1.1 index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <script src="./vue.js"></script>
    <script src="./observer.js"></script>
    <script src="./compile.js"></script>
    <script src="./watcher.js"></script>
</head>
<body>
    <div id="app">{{text}}</div>
    <button id="update">鏇存柊鏁版嵁</button>
    <script src="./index.js"></script>
</body>
</html>

1.2 index.js

"use strict";
const vm = new Vue({
    el'#app',
    data(){
        return {
            text'浣犲ソ锛屽墠绔嚜涔犺',
            desc'姣忔棩娓呮櫒锛屼韩鍙椾竴绡囧墠绔紭绉€鏂囩珷銆?
        }
    }
});

console.log(vm.$data.text)
vm.$data.text = '椤甸潰鏁版嵁鏇存柊鎴愬姛锛?// 妯℃嫙鏁版嵁鍙樺寲
console.log(vm.$data.text)

2. 瀹炵幇鏍稿績鍏ュ彛 vue.js

vue.js 鏂囦欢鏄垜浠疄鐜扮殑鏁翠釜鍝嶅簲寮忕殑鍏ュ彛鏂囦欢锛屾毚闇蹭竴涓?Vue 绫伙紝骞舵寕杞藉叏灞€銆?/p>

class Vue {
    constructor (options = {}) {
        this.$el = options.el;
        this.$data = options.data();
        this.$methods = options.methods;

        // [鏍稿績娴佺▼]灏嗘櫘閫?nbsp;data 瀵硅薄杞崲涓哄搷搴斿紡瀵硅薄
        new Observer(this.$data);

        if (this.$el) {
            // [鏍稿績娴佺▼]灏嗚В鏋愭ā鏉跨殑鍐呭
            new Compile(this.$el, this)
        }
    }
}
window.Vue = Vue;

Vue 绫诲叆鍙備负涓€涓厤缃」 option 锛屼娇鐢ㄨ捣鏉ヨ窡 Vue.js 涓€鏍凤紝鍖呮嫭 $el 鎸傝浇鐐广€?$data 鏁版嵁瀵硅薄鍜?$methods 鏂规硶鍒楄〃锛堟湰鏂囦笉璇︾粏浠嬬粛锛夈€?/p>

閫氳繃瀹炰緥鍖?Oberser 绫伙紝灏嗘櫘閫?data 瀵硅薄杞崲涓哄搷搴斿紡瀵硅薄锛岀劧鍚庡垽鏂槸鍚︿紶鍏?el 鍙傛暟锛屽瓨鍦ㄦ椂锛屽垯瀹炰緥鍖?Compile 绫伙紝瑙f瀽妯$増鍐呭銆?/p>

鎬荤粨涓?Vue 杩欎釜绫诲伐浣滄祦绋?锛?img data-ratio="0.605475040257649" src="/img?url=https://mmbiz.qpic.cn/mmbiz_png/dy9CXeZLlCUenf0nfYZEiclLVFDmoFwpdsastoanIuPt6dHMZKdD5FxxsLQcXUnI8w0EoqianqpxEtYm6FFAywkQ/640?wx_fmt=png" data-type="png" data-w="1863" _width="100%" class="mq-602" alt="銆怴uejs銆戞帰绱?Vue.js 鍝嶅簲寮忓師鐞?>

3. 瀹炵幇 observer.js

observer.js 鏂囦欢瀹炵幇浜?Observer 绫伙紝鐢ㄦ潵灏嗘櫘閫氬璞¤浆鎹负鍝嶅簲寮忓璞★細

class Observer {
    constructor (data) {
        this.data = data;
        this.walk(data);
    }

    // [鏍稿績鏂规硶]灏?nbsp;data 瀵硅薄杞崲涓哄搷搴斿紡瀵硅薄锛屼负姣忎釜 data 灞炴€ц缃?nbsp;getter 鍜?nbsp;setter 鏂规硶
    walk (data) {
        if (typeof data !== 'object'return data;
        Object.keys(data).forEach( key => {
            this.defineReactive(data, key, data[key])
        })
    }

    // [鏍稿績鏂规硶]瀹炵幇鏁版嵁鍔寔
    defineReactive (obj, key, value) {
        this.walk(value);  // [鏍稿績杩囩▼]閬嶅巻 walk 鏂规硶锛屽鐞嗘繁灞傚璞°€?/span>
        const dep = new Dep();
        Object.defineProperty(obj, key, {
            enumerabletrue,
            configurabletrue,
            get () {
                console.log('[getter]鏂规硶鎵ц')
                Dep.target &&  dep.addSub(Dep.target);
                return value
            },
            set (newValue) {
                console.log('[setter]鏂规硶鎵ц')
                if (value === newValue) return;
                // [鏍稿績杩囩▼]褰撹缃殑鏂板€?nbsp;newValue 涓哄璞★紝鍒欑户缁€氳繃 walk 鏂规硶灏嗗叾杞崲涓哄搷搴斿紡瀵硅薄
                if (typeof newValue === 'object'this.walk(newValue);
                value = newValue;
                dep.notify(); // [鏍稿績杩囩▼]鎵ц琚瀵熻€呴€氱煡鏂规硶锛岄€氱煡鎵€鏈夎瀵熻€呮墽琛?nbsp;update 鏇存柊
            }
        })
    }
}

鐩告瘮杈冪鍥涜妭瀹炵幇鐨?Observer 绫伙紝杩欓噷鍋氫簡璋冩暣锛?/p>

  • 澧炲姞 walk 鏍稿績鏂规硶锛岀敤鏉ラ亶鍘嗗璞℃瘡涓睘鎬э紝鍒嗗埆璋冪敤鏁版嵁鍔寔鏂规硶锛? defineReactive() 锛夛紱
  • 鍦? defineReactive() 鐨?getter 涓紝鍒ゆ柇 Dep.target 瀛樺湪鎵嶆坊鍔犺瀵熻€咃紝涓嬩竴鑺備細璇︾粏浠嬬粛 Dep.target锛?
  • 鍦? defineReactive() 鐨?setter 涓紝鍒ゆ柇褰撳墠鏂板€硷紙 newValue 锛夋槸鍚︿负瀵硅薄锛屽鏋滄槸锛屽垯鐩存帴璋冪敤 this.walk() 鏂规硶灏嗗綋鍓嶅璞″啀娆¤浆涓哄搷搴斿紡瀵硅薄锛? 澶勭悊娣卞眰瀵硅薄銆?

閫氳繃鏀瑰杽鍚庣殑 Observer 绫伙紝鎴戜滑灏卞彲浠ュ疄鐜?span class="mq-669">灏嗗崟灞傛垨娣卞眰宓屽鐨勬櫘閫氬璞¤浆鎹负鍝嶅簲寮忓璞?/strong>銆?/p>

4. 瀹炵幇 watcher.js

杩欓噷瀹炵幇浜?Dep 琚瀵熻€呯被锛堜緷璧栨敹闆嗚€咃級鍜?Watcher 瑙傚療鑰呯被銆?/p>

class Dep {
    constructor() {
        this.subs = [];
    }
    addSub(watcher) {
        this.subs.push(watcher);
    }
    notify(data) {
        this.subs.forEach(sub => sub.update(data));
    }
}

class Watcher {
    constructor (vm, key, cb) {
        this.vm = vm;   // vm锛氳〃绀哄綋鍓嶅疄渚?/span>
        this.key = key; // key锛氳〃绀哄綋鍓嶆搷浣滅殑鏁版嵁鍚嶇О
        this.cb = cb;   // cb锛氳〃绀烘暟鎹彂鐢熸敼鍙樹箣鍚庣殑鍥炶皟

        Dep.target = this// 鍏ㄥ眬鍞竴
        this.oldValue = this.vm.$data[key]; // 淇濆瓨鍙樺寲鐨勬暟鎹綔涓烘棫鍊硷紝鍚庣画鍋氬垽鏂槸鍚︽洿鏂?/span>
        Dep.target = null;
    }
    
    update () {
        console.log(`鏁版嵁鍙戠敓鍙樺寲锛乣);
        let oldValue = this.oldValue;
        let newValue = this.vm.$data[this.key];
        if (oldValue != newValue) {  // 姣旇緝鏂版棫鍊硷紝鍙戠敓鍙樺寲鎵嶆墽琛屽洖璋?/span>
            this.cb(newValue, oldValue);
        };
    }
}

鐩告瘮杈冪鍥涜妭瀹炵幇鐨?Watcher  绫伙紝杩欓噷鍋氫簡璋冩暣锛?/p>

  • 鍦ㄦ瀯閫犲嚱鏁颁腑锛屽鍔? Dep.target 鍊兼搷浣滐紱
  • 鍦ㄦ瀯閫犲嚱鏁颁腑锛屽鍔? oldValue 鍙橀噺锛屼繚瀛樺彉鍖栫殑鏁版嵁浣滀负鏃у€硷紝鍚庣画鍋氫负鍒ゆ柇鏄惁鏇存柊鐨勪緷鎹紱
  • 鍦? update() 鏂规硶涓紝澧炲姞褰撳墠鎿嶄綔瀵硅薄 key 瀵瑰簲鍊肩殑鏂版棫鍊兼瘮杈冿紝濡傛灉涓嶅悓锛屾墠鎵ц鍥炶皟銆?

Dep.target 鏄?span class="mq-727">褰撳墠鍏ㄥ眬鍞竴鐨勮闃呰€?/strong>锛屽洜涓哄悓涓€鏃堕棿鍙厑璁镐竴涓闃呰€呰澶勭悊銆?code class="mq-728">target 鎸?span class="mq-729">褰撳墠姝e湪澶勭悊鐨勭洰鏍囪闃呰€?/strong>锛屽綋鍓嶈闃呰€呭鐞嗗畬灏辫祴鍊间负 null 銆傝繖閲?Dep.target 浼氬湪 defineReactive() 鐨?getter 涓娇鐢ㄥ埌銆?/p>

閫氳繃鏀瑰杽鍚庣殑 Watcher 绫伙紝鎴戜滑鎿嶄綔褰撳墠鎿嶄綔瀵硅薄 key 瀵瑰簲鍊肩殑鏃跺€欙紝鍙互鍦ㄦ暟鎹湁鍙樺寲鐨勬儏鍐垫墠鎵ц鍥炶皟锛屽噺灏戣祫婧愭氮璐广€?/p>

4. 瀹炵幇 compile.js

compile.js 瀹炵幇浜?Vue.js 鐨勬ā鐗堢紪璇戯紝濡傚皢 HTML 涓殑 {{text}} 妯$増杞崲涓哄叿浣撳彉閲忕殑鍊笺€?/p>

5. 娴嬭瘯浠g爜

鍒拌繖閲岋紝鎴戜滑宸茬粡灏嗙鍥涜妭鐨?demo 鏀归€犳垚绠€鏄撶増 Vue.js 鍝嶅簲寮忥紝鎺ヤ笅鏉ユ墦寮€ index.html 鐪嬬湅鏁堟灉锛?/p>

褰?index.js 涓墽琛屽埌锛?/p>

vm.$data.text = '鎴戜滑蹇呴』缁忓父淇濇寔鏃х殑璁板繂鍜屾柊鐨勫笇鏈涖€?;

椤甸潰渚垮彂鐢熸洿鏂帮紝椤甸潰鏄剧ず鐨勬枃鏈唴瀹逛粠鈥?span class="mq-753">浣犲ソ锛屽墠绔嚜涔犺鈥濇洿鏂版垚鈥?span class="mq-754">鎴戜滑蹇呴』缁忓父淇濇寔鏃х殑璁板繂鍜屾柊鐨勫笇鏈涖€?/strong>鈥濄€?/p>

鍒拌繖閲岋紝鎴戜滑鐨勭畝鏄撶増 Vue.js 鍝嶅簲寮忓師鐞嗗疄鐜板ソ浜嗭紝鑳借窡鐫€鏂囩珷鐪嬪埌杩欓噷鐨勬湅鍙嬶紝缁欎綘鐐逛釜澶уぇ鐨勮禐馃憤

鍏€佹€荤粨

鏈枃棣栧厛閫氳繃鍥為【瑙傚療鑰呮ā寮忓拰 Object.defineProperty() 鏂规硶锛屼粙缁?Vue.js 鍝嶅簲寮忓師鐞嗙殑鏍稿績鐭ヨ瘑鐐癸紝鐒跺悗甯﹀ぇ瀹堕€氳繃涓€涓畝鍗曠ず渚嬪疄鐜扮畝鍗曞搷搴斿紡锛屾渶鍚庨€氳繃鏀归€犺繖涓畝鍗曞搷搴斿紡鐨勭ず渚嬶紝瀹炵幇涓€涓畝鍗?Vue.js 鍝嶅簲寮忓師鐞嗙殑绀轰緥銆?/p>

鐩镐俊鐪嬪畬鏈枃鐨勬湅鍙嬶紝瀵?Vue.js 鐨勫搷搴斿紡鍘熺悊鐨勭悊瑙d細鏇存繁鍒伙紝甯屾湜澶у鐞嗘竻鎬濊矾锛屽啀濂藉ソ鍥炲懗涓媬

鍙傝€冭祫鏂?/span>

  1. 瀹樻柟鏂囨。 - 娣卞叆鍝嶅簲寮忓師鐞?
  2. 銆婃祬璋圴ue鍝嶅簲寮忓師鐞嗐€?
  3. 銆奦ue鐨勬暟鎹搷搴斿紡鍘熺悊銆?

鍏充簬濂囪垶绮鹃€?/h2>

濂囪垶鍥㈡槸360闆嗗洟鏈€澶х殑澶у墠绔洟闃燂紝浠h〃闆嗗洟鍙備笌W3C鍜孍cma浼氬憳锛圱C39锛夊伐浣溿€傚鑸炲洟闈炲父閲嶈浜烘墠鍩瑰吇锛屾湁宸ョ▼甯堛€佽甯堛€佺炕璇戝畼銆佷笟鍔℃帴鍙d汉銆佸洟闃烲eader绛夊绉嶅彂灞曟柟鍚戜緵鍛樺伐閫夋嫨锛屽苟杈呬互鎻愪緵鐩稿簲鐨勬妧鏈姏銆佷笓涓氬姏銆侀€氱敤鍔涖€侀瀵煎姏绛夊煿璁绋嬨€傚鑸炲洟浠ュ紑鏀惧拰姹傝搐鐨勫績鎬佹杩庡悇绉嶄紭绉€浜烘墠鍏虫敞鍜屽姞鍏ュ鑸炲洟銆?/p>


以上是关于的主要内容,如果未能解决你的问题,请参考以下文章

谷歌浏览器调试jsp 引入代码片段,如何调试代码片段中的js

片段和活动之间的核心区别是啥?哪些代码可以写成片段?

VSCode自定义代码片段——.vue文件的模板

VSCode自定义代码片段6——CSS选择器

VSCode自定义代码片段——声明函数

VSCode自定义代码片段8——声明函数