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 相关文章推荐
学习ExtJS(二) Button常用方法
Oct 07 Javascript
THREE.JS入门教程(3)着色器-下
Jan 24 Javascript
JS实现下拉框的动态添加(附效果)
Apr 03 Javascript
JavaScript bold方法入门实例(把指定文字显示为粗体)
Oct 17 Javascript
jquery实现的美女拼图游戏实例
May 04 Javascript
AngularJS 实现弹性盒子布局的方法
Aug 30 Javascript
AngularJs基于角色的前端访问控制的实现
Nov 07 Javascript
原生JS实现图片无缝滚动方法(附带封装的运动框架)
Oct 01 Javascript
ES6知识点整理之模块化的应用详解
Apr 15 Javascript
如何写好一个vue组件,老夫的一年经验全在这了(推荐)
May 18 Javascript
微信小程序实现pdf、word等格式文件上传的方法
Sep 10 Javascript
关于vue表单提交防双/多击的例子
Oct 31 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
PHP define函数的使用说明
2008/08/27 PHP
9个PHP开发常用功能函数小结
2011/07/15 PHP
一个PHP针对数字的加密解密类
2014/03/20 PHP
Laravel使用memcached缓存对文章增删改查进行优化的方法
2016/10/08 PHP
CI框架(ajax分页,全选,反选,不选,批量删除)完整代码详解
2016/11/01 PHP
php连接mysql数据库最简单的实现方法
2019/09/24 PHP
jQuery ReferenceError: $ is not defined 错误的处理办法
2013/05/10 Javascript
Javascript 垃圾收集机制介绍理解
2013/05/14 Javascript
jquery操作下拉列表、文本框、复选框、单选框集合(收藏)
2014/01/08 Javascript
JavaScript中的Math 使用介绍
2014/04/21 Javascript
extjs每个组件要设置唯一的ID否则会出错
2014/06/15 Javascript
JavaScript定义变量和变量优先级问题探讨
2014/10/11 Javascript
JavaScript判断表单中多选框checkbox选中个数的方法
2015/08/17 Javascript
js实现常见的工具条效果
2017/03/02 Javascript
微信小程序 如何引入外部字体库iconfont的图标
2018/01/31 Javascript
vue动画之点击按钮往上渐渐显示出来的实例
2018/09/29 Javascript
快速解决layui弹窗按enter键不停弹窗的问题
2019/09/18 Javascript
LayUI switch 开关监听 获取属性值、更改状态的方法
2019/09/21 Javascript
Chrome插件开发系列一:弹窗终结者开发实战
2020/10/02 Javascript
Javascript实现关闭广告效果
2021/01/29 Javascript
python绘图库Matplotlib的安装
2014/07/03 Python
Python使用numpy模块实现矩阵和列表的连接操作方法
2019/06/26 Python
python做接口测试的必要性
2019/11/20 Python
TENSORFLOW变量作用域(VARIABLE SCOPE)
2020/01/10 Python
解决pip install psycopg2出错问题
2020/07/09 Python
全网最详细的PyCharm+Anaconda的安装过程图解
2021/01/25 Python
pycharm 的Structure界面设置操作
2021/02/05 Python
python实现b站直播自动发送弹幕功能
2021/02/20 Python
新秀丽拉杆箱美国官方网站:Samsonite美国
2016/07/25 全球购物
Electric官网:美国高级眼镜和配件品牌
2020/06/04 全球购物
自荐信怎么写呢?
2013/12/09 职场文书
安卓程序员求职信
2014/02/28 职场文书
《九寨沟》教学反思
2014/04/08 职场文书
水电站项目建议书
2014/05/12 职场文书
个人授权委托书格式
2014/08/30 职场文书
MySQL脏读,幻读和不可重复读
2022/05/11 MySQL