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 相关文章推荐
用jscript实现新建和保存一个word文档
Jun 15 Javascript
javascript window.opener的用法分析
Apr 07 Javascript
50款非常棒的 jQuery 插件分享
Mar 29 Javascript
鼠标移到导航当前位置的LI变色处于选中状态
Aug 23 Javascript
js如何实现淡入淡出效果
Nov 18 Javascript
JS封装cookie操作函数实例(设置、读取、删除)
Nov 17 Javascript
flexslider.js实现移动端轮播
Feb 05 Javascript
JavaScript模板引擎应用场景及实现原理详解
Dec 14 Javascript
微信小程序获取用户openid的实现
Dec 24 Javascript
vue源码中的检测方法的实现
Sep 26 Javascript
Javascript幻灯片播放功能实现过程解析
May 07 Javascript
javascript实现贪吃蛇小游戏
Jul 28 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的图形函数中显示汉字
2006/10/09 PHP
简单示例AJAX结合PHP代码实现登录效果代码
2008/07/25 PHP
简单实用的.net DataTable导出Execl
2013/10/28 PHP
php使浏览器直接下载pdf文件的方法
2013/11/15 PHP
PHP中isset()和unset()函数的用法小结
2014/03/11 PHP
PHP扩展程序实现守护进程
2015/04/16 PHP
PHP url的pathinfo模式加载不同控制器的简单实现
2016/08/12 PHP
Laravel 5.3 学习笔记之 安装
2016/08/28 PHP
利用php-cli和任务计划实现刷新token功能的方法
2017/05/03 PHP
thinkphp中的多表关联查询的实例详解
2017/10/12 PHP
jquery pagination插件实现无刷新分页代码
2009/10/13 Javascript
Js制作简单弹出层DIV在页面居中 中间显示遮罩的具体方法
2013/08/08 Javascript
javascript表单控件实例讲解
2016/09/13 Javascript
JavaScript实现窗口抖动效果
2016/10/19 Javascript
JavaScript实现的数字与字符串转换功能示例
2017/08/23 Javascript
利用JS测试目标网站的打开响应速度
2017/12/01 Javascript
vue中使用vue-cli接入融云实现即时通信
2019/04/19 Javascript
IE11下CKEditor在Bootstrap Modal中下拉问题的解决
2019/09/25 Javascript
ES5和ES6中类的区别总结
2020/12/21 Javascript
vue使用require.context实现动态注册路由
2020/12/25 Vue.js
kNN算法python实现和简单数字识别的方法
2014/11/18 Python
详细介绍Python中的偏函数
2015/04/27 Python
Python的装饰器模式与面向切面编程详解
2015/06/21 Python
解决csv.writer写入文件有多余的空行问题
2018/07/06 Python
Django之无名分组和有名分组的实现
2019/04/16 Python
Django静态资源部署404问题解决方案
2020/05/11 Python
pytorch查看模型weight与grad方式
2020/06/24 Python
咖啡为什么会有酸味?你喝到的咖啡為什麼是酸的?
2021/03/17 冲泡冲煮
2014年感恩母亲演讲稿
2014/05/27 职场文书
社区党建工作方案
2014/06/10 职场文书
毕业生面试求职信
2014/06/23 职场文书
二年级上册数学教学计划
2015/01/20 职场文书
乔布斯辞职信(中英文对照)
2015/05/12 职场文书
javascript的var与let,const之间的区别详解
2022/02/18 Javascript
Golang bufio详细讲解
2022/04/21 Golang
Docker安装MySql8并远程访问的实现
2022/07/07 Servers