Vue.js中data的代理

主要背景

因为对Vue.js很感兴趣,而且工作中用到的技术栈也是它,所以停留在api调用工程师肯定不行,所以就去看了看源码,研究其中的实现内容。

如果有任何问题,还请各位大佬不吝赐教

从vue2项目说起

js 复制代码
export default {
    data(){
        return {
            a:1,
            b:2,
        }
    }
}

在我们的项目中,访问this.a或者this.data.a都可以,那么问题来了,a明明是data函数中的对象,为什么this.a可以访问到。为此去看了Vue.js的源码。

首先,Vue.js初始化即我们new Vue()时候,做了一件事情

js 复制代码
function Vue(options) {
  if (__DEV__ && !(this instanceof Vue)) {
    warn('Vue is a constructor and should be called with the `new` keyword')
  }
  this._init(options)
}

上面的options就是我们实例化的时候传入的对象,比如

js 复制代码
new Vue({
  router,
  store,
  render: (h) => h(App),
}).$mount("#app");

options = {
  router,
  store,
  render: (h) => h(App),
}

_init函数定义在src/core/instance/init.ts,做了很多事情,比如:初始化生命周期、事件、props、data等,

src/core/instance/state.ts就是初始化props、data的文件,方法名:initState,此处拿initData说明

js 复制代码
function initData(vm: Component) {
  let data: any = vm.$options.data
  data = vm._data = isFunction(data) ? getData(data, vm) : data || {}
  if (!isPlainObject(data)) {
    data = {}
    __DEV__ &&
      warn(
        'data functions should return an object:\n' +
          'https://v2.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 (__DEV__) {
      if (methods && hasOwn(methods, key)) {
        warn(`Method "${key}" has already been defined as a data property.`, vm)
      }
    }
    if (props && hasOwn(props, key)) {
      __DEV__ &&
        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
  const ob = observe(data)
  ob && ob.vmCount++
}

上述函数主要做了三件事情

  1. data中定义的key不能和props/methods中相同
  2. 进行代理,即proxy函数
  3. 对data进行数据绑定,即observe函数

proxy函数

代码如下

js 复制代码
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
  }
  Object.defineProperty(target, key, sharedPropertyDefinition)
}

target = Vue对象,sourceKey = data,key = data中各属性

通过Object.defineProperty(target, key, sharedPropertyDefinition)函数定义后续通过this.xx访问data中的属性时,代理到this[data][xx]中,即this.xx访问时底层还是通过this.data.xx来实现的。

最后

如此恍然大悟,以前是只知道用,结果出来就可以了,现在去看看源码,感受Vue源码的博大精深,也还是挺好的

相关推荐
子兮曰5 小时前
Bun v1.3.14 深度解析:Image API、HTTP/3、全局虚拟存储与五十项变革
前端·后端·bun
kyriewen6 小时前
今天,百年巨头一次砍了9200人,而一个离职科学家的实话让全网睡不着觉
前端·openai·ai编程
问心无愧05136 小时前
ctf show web 入门42
android·前端·android studio
kyriewen6 小时前
老板逼我上AI,我偷偷在浏览器里跑LLaMA,省下20万API费
前端·react.js·llm
Beginner x_u7 小时前
前端八股整理(手写 02)|数组转树、数组扁平化、随机打乱一个数组
前端·数组·数组转树·数组扁平化
KaMeidebaby7 小时前
卡梅德生物技术快报|禽类成纤维细胞 FISH 实验:鸟类性别染色体基因定位技术实现与数据验证
前端·数据库·其他·百度·新浪微博
天若有情6737 小时前
前端高阶性能优化:跳出传统懒加载与预加载,基于用户行为做轻量预判加载
前端·性能优化
小小小小宇7 小时前
前端转后端:SQL 是什么
前端
张元清8 小时前
React Observer Hooks:7 种监听 DOM 而不写样板代码的方式
前端·javascript·面试
广州华水科技8 小时前
单北斗GNSS变形监测是什么?主要有怎样的应用与优势?
前端