国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Vue源碼解析(一) data屬性映射及methods函數引用的重定義

itvincent / 2714人閱讀

摘要:使用框架進行開發時,我們在的和中定義屬性和方法,在調用時直接使用或的形式,而不是用或的方式。項目的地址,后續會持續更新,分析的源碼,爭取實現一個精簡版的。中的所有方法都直接在實例重新定義了引用。

使用Vue框架進行開發時,我們在option的data和methods中定義屬性和方法,在調用時直接使用 vm.attr 或 vm.func()的形式,而不是用vm.data.attr或vm.methods.func()的方式。

項目的git地址: https://github.com/xubaodian/... ,后續會持續更新,分析Vue的源碼,爭取實現一個精簡版的Vue。
Vue解析系列文章如下:

Vue源碼解析(二)Vue的雙向綁定講解及實現

我們傳入Vue的options對象一般為以下這種形式,

{
  data: {
    name: "xxx"
  },
  mounted() {
    //調用方法,沒有使用this.methods.getInfo();
    this.getInfo();
  },
  methods: {
    getInfo() {
      //獲取屬性,沒有使用this.data.name
      this.name = "xxxx2314";
      //操作等等....
    }
  },
  computed: {
    getName() {
      return this.name;
    }
  },
  watch: {
    "name"(val, oldVal) {
      //這是操作
    }
  }
}

在vue實例中,我們無論data還是method,都直接調用,這是因為一下vue初始化時做了下面兩點操作:

1、給data中的屬性做了代理,所有訪問和設置vm[key]時,最終操作的是vm._data[key],而Vue在初始化時,會vm._data其實是options中data的引用。

2、methods中的所有方法都直接在vue實例重新定義了引用。

看下我的實現代碼,是對Vue源碼的精簡,如下:

//vue構造函數
class Vue {
  constructor(options) {
    //$options存儲構造選項
    this.$options = options || {};
    //data保存構造設置中的data,暫時忽略data為函數的情況
    let data = options.data;
    this._data = data;
    //初始化
    this._init();
  }

  _init() {
    //映射key
    mapKeys(this);
    //在vue實例上重新定義方法的引用
    initMethods(this, this.$options.methods)
  }
}


//重新定義方法的引用,注意修改調用函數時的上下文環境,這里用bind,當然也可以用apply和call
function initMethods (vm, methods) {
  for (const key in methods) {
    vm[key] = typeof methods[key] !== "function" ? noop : methods[key].bind(vm);
  }
}

//重新定義data的get和set
function mapKeys(vm) {
  let data = vm._data;
  if (null !== data && typeof data === "object") {
    const keys = Object.keys(data);
    let i = keys.length;
    while (i-- >= 0) {
      //所有屬性的操作就重新定向到了_data上
      proxy(vm, `_data`, keys[i]);
    }
  }
}

//使用defineProperty重新定義get和set
function proxy (target, sourceKey, key) {
  sharedPropertyDefinition.get = function proxyGetter () {
    return this[sourceKey][key]
  }
  sharedPropertyDefinition.set = function proxySetter (val) {
    this[sourceKey][key] = val
  }
  Object.defineProperty(target, key, sharedPropertyDefinition)
}

const sharedPropertyDefinition = {
  enumerable: true,
  configurable: true,
  get: noop,
  set: noop
}

//空函數,占位用
function noop () {}


//使用
let options = {
    data: {
        name: "xxx",
        age: 18
    },
    methods: {
        sayName() {
            console.log(this.name);
        }
    }
}


let vm = new Vue(options);

vm.sayName();//控制臺打印了xxx,可以把代碼直接復制出去試一下

上面代碼就完成了屬性的重新映射和方法的引用重新定義。

看下vue中源碼,,如下,我做了注釋,應該比較好懂:

簡單說明一下,源碼中使用了flow作為js代碼的靜態檢查工具,原理和typescript類似,所以代碼看起來會有些不同,不影響整體閱讀

//初始化,參數是vue實例
function initData (vm: Component) {
  //獲取options中的
  let data = vm.$options.data
  //設置vm._data,判斷data是obj還是函數
  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:
" +
      "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)) {
      //代理訪問,這就是為何操作vm[key]被定位到vm._data[key]的原因
      proxy(vm, `_data`, key)
    }
  }


  const sharedPropertyDefinition = {
  enumerable: true,
  configurable: true,
  get: noop,
  set: noop
}

//代理函數
export function proxy (target: Object, sourceKey: string, key: string) {
  sharedPropertyDefinition.get = function proxyGetter () {
    return this[sourceKey][key]
  }
  sharedPropertyDefinition.set = function proxySetter (val) {
    this[sourceKey][key] = val
  }
  //利用defineProperty設置對象的get和set,操作屬性時,target[key]會映射到target[sourceKey][key]
  Object.defineProperty(target, key, sharedPropertyDefinition)
}

//方法映射
function initMethods (vm: Component, methods: Object) {
  const props = vm.$options.props
  for (const key in methods) {
    //這些都是開發環境的提示信息,可以忽略
    if (process.env.NODE_ENV !== "production") {
      if (typeof methods[key] !== "function") {
        warn(
          `Method "${key}" has type "${typeof methods[key]}" in the component definition. ` +
          `Did you reference the function correctly?`,
          vm
        )
      }
      if (props && hasOwn(props, key)) {
        warn(
          `Method "${key}" has already been defined as a prop.`,
          vm
        )
      }
      if ((key in vm) && isReserved(key)) {
        warn(
          `Method "${key}" conflicts with an existing Vue instance method. ` +
          `Avoid defining component methods that start with _ or $.`
        )
      }
    }
    //關鍵在這,重新定義了引用
    vm[key] = typeof methods[key] !== "function" ? noop : bind(methods[key], vm)
  }
}

有疑問可以給我留言,或發郵件至472784995@qq.com,歡迎大家來討論

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/100595.html

相關文章

  • Vue源碼解析(二)Vue的雙向綁定講解實現

    摘要:上篇文章,我們講解了的屬性映射和方法的重定義,鏈接地址如下源碼解析一屬性映射和函數引用的重定義這篇文章給大家帶來的是的雙向綁定講解。這就是的雙向綁定。使用定時器定時檢查的值,發生變化就通知訂閱者。這個方法不好,定時器不能實時反應變化。 文章中的代碼時階段,可以下載源碼測試一下。git項目地址:https://github.com/xubaodian/...項目使用webpack構建,下...

    ckllj 評論0 收藏0
  • vue源碼閱讀之數據渲染過程

    摘要:圖在中應用三數據渲染過程數據綁定實現邏輯本節正式分析從到數據渲染到頁面的過程,在中定義了一個的構造函數。一、概述 vue已是目前國內前端web端三分天下之一,也是工作中主要技術棧之一。在日常使用中知其然也好奇著所以然,因此嘗試閱讀vue源碼并進行總結。本文旨在梳理初始化頁面時data中的數據是如何渲染到頁面上的。本文將帶著這個疑問一點點追究vue的思路。總體來說vue模版渲染大致流程如圖1所...

    AlphaGooo 評論0 收藏0
  • VUE

    摘要:注意指令前面需要加,對指令傳遞數據賦值使用例如約定速成加上,表示自定義指令不要使用駝峰式命名。需要通過方法實現自定義指令注冊完成。 vue Vue.js 構建數據驅動的web界面庫。集中實現MVVM 的 VM層。容易與其他庫或項目整合 通過盡可能簡單的API實現相應的數據綁定和組合的視圖組件核心:相應的數據綁定系統, 數據與DOM保持同步數據驅動的視圖,普通的HTML模板中使用特殊的語...

    bergwhite 評論0 收藏0
  • Vue源碼解析:雙向綁定原理

    摘要:無論是還是都提倡單向數據流管理狀態,那我們今天要談的雙向綁定是否和單向數據流理念有所違背我覺得不是,從上篇文章語法樹轉函數了解到,雙向綁定,實質是的單向綁定和事件偵聽的語法糖。源碼解析今天涉及到的代碼全在文件夾下。 通過對 Vue2.0 源碼閱讀,想寫一寫自己的理解,能力有限故從尤大佬2016.4.11第一次提交開始讀,準備陸續寫: 模版字符串轉AST語法樹 AST語法樹轉rend...

    oliverhuang 評論0 收藏0
  • Vue源碼解析:雙向綁定原理

    摘要:無論是還是都提倡單向數據流管理狀態,那我們今天要談的雙向綁定是否和單向數據流理念有所違背我覺得不是,從上篇文章語法樹轉函數了解到,雙向綁定,實質是的單向綁定和事件偵聽的語法糖。源碼解析今天涉及到的代碼全在文件夾下。 通過對 Vue2.0 源碼閱讀,想寫一寫自己的理解,能力有限故從尤大佬2016.4.11第一次提交開始讀,準備陸續寫: 模版字符串轉AST語法樹 AST語法樹轉rend...

    Kross 評論0 收藏0

發表評論

0條評論

itvincent

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<