最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue響應(yīng)式原理及雙向數(shù)據(jù)綁定示例分析

 更新時間:2022年07月19日 15:19:17   作者:一拳不是超人  
這篇文章主要為大家介紹了Vue響應(yīng)式原理及雙向數(shù)據(jù)綁定的示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前言

之前公司招人,面試了一些的前端同學(xué),因?yàn)楣臼褂玫那岸思夹g(shù)是Vue,所以免不了問到其響應(yīng)式原理和Vue的雙向數(shù)據(jù)綁定。但是這邊面試到的80%的同學(xué)會把兩者搞混,通常我要是先問響應(yīng)式原理再問雙向數(shù)據(jù)綁定原理,來面試的同學(xué)大都會認(rèn)為是一回事,那么這里我們就說一下二者的區(qū)別。

響應(yīng)式原理

是Vue的核心特性之一,數(shù)據(jù)驅(qū)動視圖,我們修改數(shù)據(jù)視圖隨之響應(yīng)更新,就很優(yōu)雅~

Vue2.x是借助Object.defineProperty()實(shí)現(xiàn)的,而Vue3.x是借助Proxy實(shí)現(xiàn)的,下面我們先來看一下2.x的實(shí)現(xiàn)。

Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    //攔截get,當(dāng)我們訪問data.key時會被這個方法攔截到
    get: function getter () {
        //我們在這里收集依賴
        return obj[key];
    },
    //攔截set,當(dāng)我們?yōu)閐ata.key賦值時會被這個方法攔截到
    set: function setter (newVal) {
        //當(dāng)數(shù)據(jù)變更時,通知依賴項(xiàng)變更UI
    } 
})

我們通過Object.defineProperty為對象obj添加屬性,可以設(shè)置對象屬性的gettersetter函數(shù)。之后我們每次通過點(diǎn)語法獲取屬性都會執(zhí)行這里的getter函數(shù),在這個函數(shù)中我們會把調(diào)用此屬性的依賴收集到一個集合中 ;而在我們給屬性賦值(修改屬性)時,會觸發(fā)這里定義的setter函數(shù),在次函數(shù)中會去通知集合中的依賴更新,做到數(shù)據(jù)變更驅(qū)動視圖變更。

3.x的與2.x的核心思想一致,只不過數(shù)據(jù)的劫持使用Proxy而不是Object.defineProperty,只不過Proxy相比Object.defineProperty在處理數(shù)組和新增屬性的響應(yīng)式處理上更加方便。

let nObj=new Proxy(obj,{
  //攔截get,當(dāng)我們訪問nObj.key時會被這個方法攔截到
  get: function (target, propKey, receiver) {
    console.log(`getting ${propKey}!`);
    return Reflect.get(target, propKey, receiver);
  },
  //攔截set,當(dāng)我們?yōu)閚Obj.key賦值時會被這個方法攔截到
  set: function (target, propKey, value, receiver) {
    console.log(`setting ${propKey}!`);
    return Reflect.set(target, propKey, value, receiver);
  }
})

Proxy的詳細(xì)使用方法參考ES6教程。

Vue的響應(yīng)式原理的實(shí)現(xiàn)細(xì)節(jié)相信大多數(shù)同學(xué)已經(jīng)很熟悉了,這里就不在展開細(xì)談了,如果還想更詳細(xì)的了解,或者想要做一個簡易的Vue實(shí)現(xiàn),可以參考這篇Vue原理,相信你會有不小收獲。

雙向數(shù)據(jù)綁定

雙向數(shù)據(jù)綁定通常是指我們使用的v-model指令的實(shí)現(xiàn),是Vue的一個特性,也可以說是一個input事件和value的語法糖。 Vue通過v-model指令為組件添加上input事件處理和value屬性的賦值。

<template>
   <input v-model='localValue'/>
</template>

上述的組件就相當(dāng)于如下代碼

<template>
   <!-- 這里添加了input時間的監(jiān)聽和value的屬性綁定 -->
   <input @input='onInput' :value='localValue' />
   <span>{{localValue}}</span>
</template>
<script>
  export default{
    data(){
      return {
        localValue:'',
      }
    },
    methods:{
      onInput(v){
         //在input事件的處理函數(shù)中更新value的綁定值
         this.localValue=v.target.value;
         console.log(this.localValue)
      }
    }
  }
</script>
    <template>
      <div>
        <input @input='onInput' :value='localValue' />
        <span>{{localValue}}</span>
      </div>
    </template>
    <script>
    // import Vue from 'vue';
    export default{
      data(){
        return {
          localValue:'hello',
        }
      },
      methods:{
        onInput(v){
          this.localValue=v.target.value;
          console.log(this.localValue)
        }
      }
    }
    </script>
    <style>
    .count {
      color: red;
    }
    </style>

因此當(dāng)我們修改input輸入框中的值時,我們通過v-model綁定的值也會同步修改,基于上述原理,我們可以很容易的實(shí)現(xiàn)一個數(shù)據(jù)雙向綁定的組件。

v-model實(shí)踐

首先我們定義一個Vue組件,相信大家已經(jīng)很熟悉了。

<tempalte>
  <div class="count" @click="addCount">click me {{value}}</div>
</template>
<script>
export default{
      props:{
       //關(guān)鍵的第一步:設(shè)置一個value屬性
        value:{
          type:Number,
          default:0
        }
      },
      watch:{
        //監(jiān)聽value變化,更新組件localvalue狀態(tài)
        value(v){
          this.localvalue=v;
        }  
      },
      methods:{
        //關(guān)鍵的第二步:事件觸發(fā)localvalue變更,通過事件同步父組件狀態(tài)變更
        addCount(){
           this.localvalue++;
           this.$emit('input',this.localvalue);
        }
      },
      data(){
        return{
          //組件狀態(tài),遵守單項(xiàng)數(shù)據(jù)流原則,不直接修改props中的屬性
          localvalue:0
        }
      },
      created(){
        //初始化獲取value值
        this.localvalue=this.value;
      }
    }
</script>

上面的組件定了我們通過在props中添加value屬性,并且在值更新時觸發(fā)input事件。created鉤子和watch中為localvalue賦值是為了同步父組件狀態(tài)到子組件中。
通過上面??的組件定義,我們就可以在組件上使用v-model指令做雙向數(shù)據(jù)綁定了。

<template>
  <add-one v-model="count"></add-one>
  <span>父組件{{count}}</span>
</tempalte>
<script>
export default{
  data() {
    return {
       count: 0,
    };
  },
  methods: {
  },
  created(){   
  }
}
</script>

下面是實(shí)際效果

import Vue from 'https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.esm.browser.js'
    Vue.directive('mymodel', {
        bind(el, binding, vnode, oldVnode) {
            //組件和原生input標(biāo)簽需要分別處理,
            el.value = binding.value;
            if (vnode.tag == 'input') {
                //監(jiān)聽綁定的變量
                vnode.context.$watch(binding.expression, (v) => {
                    el.value = v;
                })
                //添加inout事件監(jiān)聽
                el.addEventListener('input', (e) => {
                    //context是input所在的父組件,這一步是同步數(shù)據(jù)
                    vnode.context[binding.expression] = e.target.value;
                })
            } else { //組件
                //vnode的結(jié)構(gòu)可以參見文檔。不過我覺得最直觀的方法就是直接在控制臺打印處理
                let {
                    componentInstance,
                    componentOptions,
                    context
                } = vnode;
                const {
                    _props
                } = componentInstance;
                //處理model選項(xiàng)
                if (!componentOptions.Ctor.extendOptions.model) {
                    componentOptions.Ctor.extendOptions.model = {
                        value: 'value',
                        event: 'input'
                    }
                }
                let modelValue = componentOptions.Ctor.extendOptions.model.value;
                let modelEvent = componentOptions.Ctor.extendOptions.model.event;
                //屬性綁定,這里直接修改了屬性,沒有想到更好的辦法,友好的意見希望可以提出
                console.log(binding)
                _props[modelValue] = binding.value;
                context.$watch(binding.expression, (v) => {
                    _props[modelValue] = v;
                })
                //添加事件處理函數(shù),做數(shù)據(jù)同步
                componentInstance.$on(modelEvent, (v) => {
                    context[binding.expression] = v;
                })
            }
        },
        inserted() {},
        update() {},
        componentUpdated() {},
        unbind() {},
    })
    Vue.component('add-one', {
        template: '<div class="count" @click="addCount">click me {{localvalue}}</div>',
        props: {
            value: {
                type: Number | String,
                default: -1
            }
        },
        //自定義value和事件
        // model: {
        //     value: 'count',
        //     event: 'change'
        // },
        watch: {
            //監(jiān)聽value變化,更新組件localvalue狀態(tài)
            value(v) {
                this.localvalue = v;
            }
        },
        methods: {
            //事件觸發(fā)localvalue變更,通過事件同步父組件狀態(tài)變更
            addCount() {
                this.localvalue++;
                this.$emit('input', this.localvalue);
            }
        },
        data() {
            return {
                localvalue: 0
            }
        },
        created() {
            //初始化獲取value值
            console.log(this.value)
            this.localvalue = this.value;
        }
    })
    new Vue({
        el: '#app',

        data() {
            return {
                count: 0,
            };
        },
        methods: {},
        created() {

        }
    })

當(dāng)然我們也可以不使用valueinput事件這樣的組合,為了更使得組件的定義更加符合語義,我們也可以自定義要實(shí)現(xiàn)雙向綁定的屬性和事件。 我們在組件的model選項(xiàng)中設(shè)置valueevent即可。如下:

export default{
      //這里做了一個value和event的映射
      model:{
        value:'count',
        event:'change'
      },
      props:{
       //關(guān)鍵的第一步:設(shè)置一個value屬性
        count:{
          type:Number,
          default:0
        }
      },
      methods:{
        //關(guān)鍵的第二步:事件觸發(fā)localvalue變更,通過事件同步父組件狀態(tài)變更
        addCount(){
           this.localvalue++;
           this.$emit('change',this.localvalue);
        }
      },
}

通過上面的組件定義

<add-one v-model="count"></add-one>

就相當(dāng)于

<template>
   <add-one @change='onChange' :count='count'></add-one>
   <span>{{count}}</span>
</template>
<script>
  export default{
    data(){
      return {
        count:0,
      }
    },
    methods:{
      onChange(v){
         this.count=v;
         console.log(this.count)
      }
    }
  }
</script>

只不過v-model指令幫我們做上面的事件添加,屬性綁定和狀態(tài)同步操作罷了。

以上就是Vue響應(yīng)式原理及雙向數(shù)據(jù)綁定示例分析的詳細(xì)內(nèi)容,更多關(guān)于Vue響應(yīng)式雙向數(shù)據(jù)綁定的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 如何使用vue開發(fā)公眾號網(wǎng)頁

    如何使用vue開發(fā)公眾號網(wǎng)頁

    因?yàn)轫?xiàng)目需要,近期做了一個公眾號網(wǎng)頁開發(fā)。在此期間也踩了一些坑,解決這些坑之后,準(zhǔn)備對這個項(xiàng)目進(jìn)行復(fù)盤。記錄下項(xiàng)目從開發(fā)到上線所解決的問題,并對使用vue進(jìn)行公眾號開發(fā)的步驟進(jìn)行一個總結(jié)。方便以后有問題進(jìn)行查閱。希望對你有所幫助
    2021-05-05
  • Vue實(shí)現(xiàn)移除數(shù)組中特定元素的方法小結(jié)

    Vue實(shí)現(xiàn)移除數(shù)組中特定元素的方法小結(jié)

    這篇文章主要介紹了Vue如何優(yōu)雅地移除數(shù)組中的特定元素,文中介紹了單個去除和批量去除的操作方法,并通過代碼示例講解的非常詳細(xì),具有一定的參考價值,需要的朋友可以參考下
    2024-03-03
  • Vue3中使用this的詳細(xì)教程

    Vue3中使用this的詳細(xì)教程

    在vue3中新的組合式API中沒有this,那我們?nèi)绻枰玫絫his怎么辦?下面這篇文章主要給大家介紹了關(guān)于Vue3中使用this的詳細(xì)教程,需要的朋友可以參考下
    2023-07-07
  • vue自定義橫向滾動條css導(dǎo)航兩行排列布局實(shí)現(xiàn)示例

    vue自定義橫向滾動條css導(dǎo)航兩行排列布局實(shí)現(xiàn)示例

    這篇文章主要為大家介紹了vue自定義橫向滾動條css導(dǎo)航兩行排列布局實(shí)現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • vue實(shí)現(xiàn)form表單與table表格的數(shù)據(jù)關(guān)聯(lián)功能示例

    vue實(shí)現(xiàn)form表單與table表格的數(shù)據(jù)關(guān)聯(lián)功能示例

    這篇文章主要介紹了vue實(shí)現(xiàn)form表單與table表格的數(shù)據(jù)關(guān)聯(lián)功能,涉及vue.js表單事件響應(yīng)及頁面元素屬性動態(tài)操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2019-01-01
  • vue中循環(huán)表格數(shù)據(jù)出現(xiàn)數(shù)據(jù)聯(lián)動現(xiàn)象(示例代碼)

    vue中循環(huán)表格數(shù)據(jù)出現(xiàn)數(shù)據(jù)聯(lián)動現(xiàn)象(示例代碼)

    在Vue中循環(huán)生成表格數(shù)據(jù)時,可能會遇到數(shù)據(jù)聯(lián)動的現(xiàn)象,即修改一個表格中的數(shù)據(jù)后,其他表格的數(shù)據(jù)也會跟著變化,這種現(xiàn)象通常是因?yàn)樗斜砀竦臄?shù)據(jù)引用了同一個對象或數(shù)組導(dǎo)致的,本文介紹vue中循環(huán)表格數(shù)據(jù)出現(xiàn)數(shù)據(jù)聯(lián)動現(xiàn)象,感興趣的朋友一起看看吧
    2024-11-11
  • vue開發(fā)中遇到的問題總結(jié)

    vue開發(fā)中遇到的問題總結(jié)

    在本篇文章里小編給大家分享的是關(guān)于vue開發(fā)中遇到的問題總結(jié),有興趣的朋友們可以學(xué)習(xí)參考下。
    2020-04-04
  • 一文詳解vue中偵聽器的使用

    一文詳解vue中偵聽器的使用

    這篇文章主要為大家詳細(xì)介紹了vue中偵聽器使用的相關(guān)知識,文中的示例代碼講解詳細(xì),具有一定的借鑒價值,有需要的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2007-02-02
  • vue+element-ui:使用el-dialog時彈框不出現(xiàn)的解決

    vue+element-ui:使用el-dialog時彈框不出現(xiàn)的解決

    這篇文章主要介紹了vue+element-ui:使用el-dialog時彈框不出現(xiàn)的解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-10-10
  • vue3中的組件間的傳值(props)

    vue3中的組件間的傳值(props)

    這篇文章主要介紹了vue3中的組件間的傳值(props)問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-04-04

最新評論

蓝田县| 唐山市| 卢氏县| 高邑县| 梨树县| 揭阳市| 泸州市| 石景山区| 丽水市| 南川市| 邵阳县| 同江市| 钟祥市| 民和| 营口市| 唐河县| 博罗县| 惠州市| 明溪县| 武威市| 桃园县| 西宁市| 措勤县| 吴旗县| 察雅县| 新昌县| 贵阳市| 兴文县| 苍南县| 苏尼特左旗| 广平县| 基隆市| 牟定县| 民权县| 南宁市| 彰武县| 桂林市| 安新县| 宜春市| 玛多县| 五原县|