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 相关文章推荐
Jquery实现鼠标移上弹出提示框、移出消失思路及代码
May 19 Javascript
js页面跳转的常用方法整理
Oct 18 Javascript
一个html5播放视频的video控件只支持android的默认格式mp4和3gp
May 08 Javascript
禁用页面部分JavaScript不是全部而是部分
Sep 03 Javascript
jquery实现简单手风琴菜单效果实例
Jun 13 Javascript
jquery.mousewheel实现整屏翻屏效果
Aug 30 Javascript
快速掌握jQuery插件WebUploader文件上传
Nov 07 Javascript
easyui 中的datagrid跨页勾选问题的实现方法
Jan 18 Javascript
js实现旋转木马效果
Mar 17 Javascript
Vue单文件组件基础模板小结
Aug 10 Javascript
JavaScript 下载svg图片为png格式
Jun 21 Javascript
Vue.js组件props数据验证实现详解
Oct 19 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防止sql注入代码实例
2013/12/18 PHP
php事件驱动化设计详解
2016/11/10 PHP
Thinkphp3.2简单解决多文件上传只上传一张的问题
2017/09/26 PHP
jQuery实现的一个tab切换效果内部还嵌有切换
2014/08/10 Javascript
JS实现在页面随时自定义背景颜色的方法
2015/02/27 Javascript
深入理解JavaScript系列(45):代码复用模式(避免篇)详解
2015/03/04 Javascript
javascript实现无缝上下滚动特效
2015/12/16 Javascript
JavaScript学习笔记之数组求和方法
2016/03/23 Javascript
浅谈jQuery 中的事件冒泡和阻止默认行为
2016/05/28 Javascript
Bootstrap表单布局
2016/07/19 Javascript
jQuery验证表单格式的使用方法
2017/01/10 Javascript
基于Marquee.js插件实现的跑马灯效果示例
2017/01/25 Javascript
jQuery插件FusionCharts实现的Marimekko图效果示例【附demo源码】
2017/03/24 jQuery
javascript编写简易计算器
2017/05/06 Javascript
JavaScript表单验证实现代码
2017/05/22 Javascript
通过javascript实现段落的收缩与展开
2019/06/26 Javascript
[49:21]TNC vs VG 2019DOTA2国际邀请赛淘汰赛 胜者组赛BO3 第三场 8.20.mp4
2019/08/22 DOTA
Python IDLE 错误:IDLE''s subprocess didn''t make connection 的解决方案
2017/02/13 Python
Python使用PDFMiner解析PDF代码实例
2017/03/27 Python
pycharm修改file type方式
2019/11/19 Python
Python对wav文件的重采样实例
2020/02/25 Python
Django 设置admin后台表和App(应用)为中文名的操作方法
2020/05/10 Python
Python3.9 beta2版本发布了,看看这7个新的PEP都是什么
2020/06/10 Python
教你一分钟在win10终端成功安装Pytorch的方法步骤
2021/01/28 Python
可以随进度显示不同颜色的css3进度条分享
2014/04/11 HTML / CSS
canvas环形倒计时组件的示例代码
2018/06/14 HTML / CSS
GIVENCHY纪梵希官方旗舰店:高定彩妆与贵族护肤品
2018/04/16 全球购物
豪华床上用品、床单和浴室必需品:Peacock Alley
2019/09/04 全球购物
中专自荐信
2013/10/13 职场文书
学生就业推荐信
2013/11/13 职场文书
优秀员工表扬信
2014/01/17 职场文书
文体活动总结范文
2014/05/05 职场文书
学校领导班子四风问题整改意见
2014/10/02 职场文书
男方家长婚礼致辞
2015/07/27 职场文书
Vue.Draggable实现交换位置
2022/04/07 Vue.js
排查并解决MySQL生产库内存使用率高的报警
2022/04/11 MySQL