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 相关文章推荐
通过javascript获取iframe里的值示例代码
Jun 24 Javascript
JavaScript严格模式详解
Nov 18 Javascript
Angular 5.0 来了! 有这些大变化
Nov 15 Javascript
关于echarts在节点显示动态数据及添加提示文本所遇到的问题
Apr 20 Javascript
js调用设备摄像头的方法
Jul 19 Javascript
webpack打包非模块化js的方法
Oct 24 Javascript
jQuery实现购物车的总价计算和总价传值功能
Nov 28 jQuery
详解vue中的computed的this指向问题
Dec 05 Javascript
js实现倒计时秒杀效果
Mar 25 Javascript
微信小程序getLocation 需要在app.json中声明permission字段
Mar 03 Javascript
基于JavaScript实现猜数字游戏代码实例
Jul 30 Javascript
如何用vue实现网页截图你知道吗
Nov 17 Vue.js
解决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
PHP 程序授权验证开发思路
2009/07/09 PHP
ThinkPHP3.1新特性之内容解析输出详解
2014/06/19 PHP
php实现汉字验证码和算式验证码的方法
2015/03/07 PHP
PHP二进制与字符串之间的相互转换教程
2016/10/14 PHP
PHP实现唤起微信支付功能
2019/02/18 PHP
基于jQuery的可以控制左右滚动及自动滚动效果的代码
2010/07/25 Javascript
JSONP 跨域共享信息
2012/08/16 Javascript
jcrop基本参数一览
2013/07/16 Javascript
JavaScript检测弹出窗口是否已经关闭的方法
2015/03/24 Javascript
Grunt入门教程(自动任务运行器)
2015/08/06 Javascript
理解JS事件循环
2016/01/07 Javascript
JavaScript队列、优先队列与循环队列
2016/11/14 Javascript
《javascript少儿编程》location术语总结
2018/05/27 Javascript
详解如何从零开始搭建Express+Vue开发环境
2018/07/17 Javascript
深入理解react 组件类型及使用场景
2019/03/07 Javascript
JS实现“全选”和&quot;全不选&quot;功能代码实例
2020/02/06 Javascript
如何利用javascript接收json信息并进行处理
2020/08/06 Javascript
Python字典操作简明总结
2015/04/13 Python
Python Flask-web表单使用详解
2017/11/18 Python
Python多线程扫描端口代码示例
2018/02/09 Python
Django基于ORM操作数据库的方法详解
2018/03/27 Python
python实现函数极小值
2019/07/10 Python
python 修改本地网络配置的方法
2019/08/14 Python
python自动生成model文件过程详解
2019/11/02 Python
Python docutils文档编译过程方法解析
2020/06/23 Python
欧舒丹比利时官网:L’OCCITANE比利时
2017/04/25 全球购物
NFL墨西哥官方商店:Tienda NFL
2017/11/28 全球购物
水上运动奥特莱斯:Wasterports Outlet
2018/08/08 全球购物
创业计划书模版
2014/02/05 职场文书
商业房地产广告语
2014/03/13 职场文书
课前三分钟演讲稿
2014/04/24 职场文书
优秀教师事迹材料
2014/12/15 职场文书
化妆品促销活动总结
2015/05/07 职场文书
大学学生会辞职信
2015/05/13 职场文书
同学聚会开幕词
2019/04/02 职场文书
golang实现一个简单的websocket聊天室功能
2021/10/05 Golang