<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Vue 中 data 的初始化主要過程

          共 4002字,需瀏覽 9分鐘

           ·

          2023-08-22 11:47


          在 Vue.js 中,props 和 data 是組件的兩個重要概念。props 是父組件向子組件傳遞數(shù)據(jù)的方式,而 data 是組件自身的狀態(tài)數(shù)據(jù)。這兩者都會被代理到 Vue 實例上,也就是說我們可以通過 this 訪問到它們。那么,這個代理是如何實現(xiàn)的呢?


          Vue.js 使用了 ES5 提供的 Object.defineProperty 方法來實現(xiàn)數(shù)據(jù)的響應式綁定。這個方法可以讓我們在讀取或者修改一個對象的屬性時,執(zhí)行一些額外的操作。Vue.js 利用這個方法在讀取或者修改 props 和 data 時,進行依賴收集和派發(fā)更新。


          當我們在組件中訪問 this.message 時,實際上是在訪問 this._data.message 或者 this._props.message。Vue.js 在初始化實例時,會遍歷 data 和 props 對象,使用 Object.defineProperty 為每一個屬性設置 getter 和 setter,然后將這些屬性代理到 Vue 實例上。


          當我們訪問 this.message 時,實際上觸發(fā)了 getter,返回了 this._data.message 或者 this._props.message 的值。當我們修改 this.message 時,實際上觸發(fā)了 setter,修改了 this._data.message 或者 this._props.message 的值,并且觸發(fā)視圖的更新。


          這就是 Vue.js 如何將 props 和 data 上的屬性代理到 vm 實例上的基本原理。


          在 Vue.js 的源碼中,props 和 data 的代理實現(xiàn)是在初始化實例時進行的。以下是一個簡化的示例,展示了如何使用 Object.defineProperty 來實現(xiàn)這個代理:


          function Vue (options) {  this._data = options.data;  this._props = options.props;
          var self = this;
          // 遍歷 data 對象 Object.keys(this._data).forEach(function(key) { self.proxyData(key); });
          // 遍歷 props 對象 Object.keys(this._props).forEach(function(key) { self.proxyProps(key); });}
          Vue.prototype.proxyData = function(key) { var self = this; Object.defineProperty(self, key, { enumerable: true, configurable: true, get: function proxyGetter() { return self._data[key]; }, set: function proxySetter(newVal) { self._data[key] = newVal; } });
          };
          Vue.prototype.proxyProps = function(key) { var self = this; Object.defineProperty(self, key, { enumerable: true, configurable: true, get: function proxyGetter() { return self._props[key]; }, set: function proxySetter(newVal) { console.warn('You are trying to modify a read only value'); } });};


          在這個示例中,我們在 Vue 的構(gòu)造函數(shù)中遍歷 data 和 props 對象,然后使用 Object.defineProperty 為每一個屬性設置 getter 和 setter。當我們訪問 this.message 時,實際上觸發(fā)了 getter,返回了 this._data.message 或者 this._props.message 的值。當我們修改 this.message 時,實際上觸發(fā)了 setter,修改了 this._data.message 的值,并且觸發(fā)視圖的更新。對于 props,由于它是只讀的,所以我們在 setter 中打印了一個警告消息。


          源碼中 Vue 的初始化階段,_init 方法執(zhí)行的時候,會執(zhí)行 initState(vm) 方法,方法主要是對 props、methods、data、computed 和 wathcer 等屬性做了初始化操作。


          data 的初始化主要過程也是做兩件事,一個是對定義 data 函數(shù)返回對象的遍歷,通過 proxy 把每一個值 vm._data.xxx 都代理到 vm.xxx 上;另一個是調(diào)用 observe 方法觀測整個 data 的變化。


          function initData (vm: Component) {  let data = vm.$options.data  data = vm._data = typeof data === 'function'    ? getData(data, vm)    : data || {}  if (!isPlainObject(data)) {    data = {}    process.env.NODE_ENV !== 'production' && warn(      'data functions should return an object:\n' +      'https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function',      vm    )  }  // proxy data on instance  const keys = Object.keys(data)  const props = vm.$options.props  const methods = vm.$options.methods  let i = keys.length  while (i--) {    const key = keys[i]    if (process.env.NODE_ENV !== 'production') {      if (methods && hasOwn(methods, key)) {        warn(          `Method "${key}" has already been defined as a data property.`,          vm        )      }    }    if (props && hasOwn(props, key)) {      process.env.NODE_ENV !== 'production' && warn(        `The data property "${key}" is already declared as a prop. ` +        `Use prop default value instead.`,        vm      )    } else if (!isReserved(key)) {      proxy(vm, `_data`, key)    }  }  // observe data  observe(data, true /* asRootData */)}


          瀏覽 139
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  天天综合网,7799精品视频天天看 | 日本操逼一区二区 | 国产女人18毛片水真多果冻 | 日逼黄色视频 | 欧美黄色影片在线观看 |