成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

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

itvincent / 2724人閱讀

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

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

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

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

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

{
  data: {
    name: "xxx"
  },
  mounted() {
    //調(diào)用方法,沒有使用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,都直接調(diào)用,這是因為一下vue初始化時做了下面兩點操作:

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

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

看下我的實現(xiàn)代碼,是對Vue源碼的精簡,如下:

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

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


//重新定義方法的引用,注意修改調(diào)用函數(shù)時的上下文環(huán)境,這里用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
}

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


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


let vm = new Vue(options);

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

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

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

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

//初始化,參數(shù)是vue實例
function initData (vm: Component) {
  //獲取options中的
  let data = vm.$options.data
  //設(shè)置vm._data,判斷data是obj還是函數(shù)
  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]
    //這是在開發(fā)環(huán)境打印的一些提示不用關(guān)心
    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
}

//代理函數(shù)
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設(shè)置對象的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) {
    //這些都是開發(fā)環(huán)境的提示信息,可以忽略
    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 $.`
        )
      }
    }
    //關(guān)鍵在這,重新定義了引用
    vm[key] = typeof methods[key] !== "function" ? noop : bind(methods[key], vm)
  }
}

有疑問可以給我留言,或發(fā)郵件至[email protected],歡迎大家來討論

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/100595.html

相關(guān)文章

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

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

    ckllj 評論0 收藏0
  • vue源碼閱讀之數(shù)據(jù)渲染過程

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

    AlphaGooo 評論0 收藏0
  • VUE

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

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

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

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

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

    Kross 評論0 收藏0

發(fā)表評論

0條評論

itvincent

|高級講師

TA的文章

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