Vue中的this.$options.data()和this.$data用法说明


Posted in Javascript onJuly 26, 2020

问题

项目里遇到一个问题,用this.$options.data()重置组件data时,data()里用this获取的props或method都为undefined,代码简化如下:

export default {
  props: {
    P: Object
  },
  data () {
    return {
      A: {
        a: this.methodA
      },
      B: this.P
    };
  },
  methods: {
    resetData () { // 更新时调用
      Object.assign(this.$data, this.$options.data()); // 有问题!!!
    },
    methodA () {
      // do sth.
    },
    methodB () { // 通过用户操作调用
      this.A.a && this.A.a(); // this.A.a is undefined, this.B is undefined!!!
    }
  }
}

调用resetData()之后,再调用methodB()时,this.A.a和this.B是undefined。

解决

resetData里这样写:

resetData () { // 更新时调用
  Object.assign(this.$data, this.$options.data.call(this));
}

原因

和Vue实例的初始化相关。(源码version2.6.10)

1、new Vue的时候传了一个对象,把该对象记为options,Vue将options中自定义的属性和Vue构造函数中定义的属性合并为vm.$options,vm.$options.data()中的this指向vm.$options,而methodA和B并没有直接挂在vm.$options下,所以this.methodA和this.B为undefined。

// 创建一个vue实例
const options = {
  customOption: 'foo',
  data () {
    A: this.methodA
  },
  methods: {
    methodA () {}
  },
  created: function () {
    console.log(this.$options.customOption) // => 'foo'
  }
};
new Vue(options);
 
// src/core/instance/init.js
initMixin (Vue: Class<Component>) {
  const vm: Component = this
  // ...
  vm.$options = mergeOptions(
    resolveConstructorOptions(vm.constructor),
    options || {},
    vm
  )
  // ...
}

2、然后将vm.$options.data映射到vm._data,使得可以通过vm._data访问数据,在映射过程中,通过call将data()的this指向当前的实例vm,并将data()的执行结果返回,因为prop和methods的初始化在data之前,所以这时vm上已有_props和_methods,可以拿到this.methodA和this.B。(vm.key如何实现vm._props.key效果见3)。

// src/core/instance/state.js
initState (vm: Component) {
  // ...
  const opts = vm.$options
  if (opts.props) initProps(vm, opts.props)
  if (opts.methods) initMethods(vm, opts.methods)
  if (opts.data) {
    initData(vm) // 里面通过getData(data, vm)改变this
  }
  // ...
}
 
getData (data: Function, vm: Component): any {
  // ...
  try {
    return data.call(vm, vm) // this替换为vm
  }
  // ...
}

3、上面把属性映射到了vm._data里,可以通过vm._data.A访问数据,Vue再通过一个代理方法使得vm.A可以直接访问A。

// src/core/instance/state.js
proxy(vm, `_data`, key);
 
proxy (target: Object, sourceKey: string, key: string) {
  sharedPropertyDefinition.proxyget = function proxyGetter () {
    return this[sourceKey][key]
  }
  sharedPropertyDefinition.set = function proxySetter (val) {
    this[sourceKey][key] = val
  }
  Object.defineProperty(target, key, sharedPropertyDefinition)
}

总结

data()中若使用了this来访问props或methods,在重置$data时,注意this.$options.data()的this指向,最好使用this.$options.data.call(this)。

以上这篇Vue中的this.$options.data()和this.$data用法说明就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
最佳6款用于移动网站开发的jQuery 图片滑块插件小结
Jul 20 Javascript
JavaScript之Getters和Setters 平台支持等详细介绍
Dec 07 Javascript
js带按钮的提示框可供选择示例代码
Sep 17 Javascript
Bootstrap滚动监听(Scrollspy)插件详解
Apr 26 Javascript
javascript简单进制转换实现方法
Nov 24 Javascript
js定时器实例分享
Dec 20 Javascript
Vue 过渡(动画)transition组件案例详解
Jan 22 Javascript
JS实现JSON.stringify的实例代码讲解
Feb 07 Javascript
在Vue methods中调用filters里的过滤器实例
Aug 30 Javascript
详解Node.js中path模块的resolve()和join()方法的区别
Oct 29 Javascript
js利用拖放实现添加删除
Aug 27 Javascript
Javascript表单序列化原理及实现代码详解
Oct 30 Javascript
解决vue的router组件component在import时不能使用变量问题
Jul 26 #Javascript
Element Steps步骤条的使用方法
Jul 26 #Javascript
解决vue动态路由异步加载import组件,加载不到module的问题
Jul 26 #Javascript
vue 动态设置img的src地址无效,npm run build 后找不到文件的解决
Jul 26 #Javascript
VUE动态生成word的实现
Jul 26 #Javascript
Element Dialog对话框的使用示例
Jul 26 #Javascript
在vue中使用防抖函数组件操作
Jul 26 #Javascript
You might like
基于curl数据采集之正则处理函数get_matches的使用
2013/04/28 PHP
ThinkPHP之N方法实例详解
2014/06/20 PHP
学习php中的正则表达式
2014/08/17 PHP
php之readdir函数用法实例
2014/11/13 PHP
php获取字符串中各个字符出现次数的方法
2015/02/23 PHP
如何使用PHP给图片加水印
2016/10/12 PHP
JSON扫盲帖 JSON.as类教程
2009/02/16 Javascript
Jquery 快速构建可拖曳的购物车DragDrop
2009/11/30 Javascript
jQuery 获取URL参数的插件
2010/03/04 Javascript
JavaScript Memoization 让函数也有记忆功能
2011/10/27 Javascript
jQuery判断多个input file 都不能为空的例子
2015/06/23 Javascript
jquery实现的简单二级菜单效果代码
2015/09/22 Javascript
浅谈js script标签中的预解析
2016/12/30 Javascript
nodejs使用express创建一个简单web应用
2017/03/31 NodeJs
基于JavaScript 性能优化技巧心得(分享)
2017/12/11 Javascript
如何在JavaScript中创建具有多个空格的字符串?
2020/02/23 Javascript
微信小程序录音实现功能并上传(使用node解析接收)
2020/02/26 Javascript
vue 重塑数组之修改数组指定index的值操作
2020/08/09 Javascript
vue基于Echarts的拖拽数据可视化功能实现
2020/12/04 Vue.js
Vue看了就会的8个小技巧
2021/01/21 Vue.js
python解决字典中的值是列表问题的方法
2013/03/04 Python
python中查看变量内存地址的方法
2015/05/05 Python
Python使用PIL库实现验证码图片的方法
2016/03/11 Python
Python 多线程实例详解
2017/03/25 Python
讲解Python3中NumPy数组寻找特定元素下标的两种方法
2019/08/04 Python
tensorflow 模型权重导出实例
2020/01/24 Python
pycharm无法导入本地模块的解决方式
2020/02/12 Python
html5+svg学习指南之SVG基础知识
2014/12/17 HTML / CSS
html5视频媒体标签video的使用方法及完整参数说明详解
2019/09/27 HTML / CSS
英国在线购买马术服装:EQUUS
2019/07/12 全球购物
Swanson中国官网:美国斯旺森健康产品公司
2021/03/01 全球购物
Windows和Linux动态库应用异同
2016/07/28 面试题
大学生社团活动总结
2014/04/26 职场文书
学校教师读书活动总结
2014/07/08 职场文书
golang 比较浮点数的大小方式
2021/05/02 Golang
在python中实现导入一个需要传参的模块
2021/05/12 Python