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 相关文章推荐
删除重复数据的算法
Nov 23 Javascript
select标签模拟/美化方法采用JS外挂式插件
Apr 01 Javascript
探讨在JQuery和Js中,如何让ajax执行完后再继续往下执行
Jul 09 Javascript
javascript变量声明实例分析
Apr 25 Javascript
浅谈javascript的分号的使用
May 12 Javascript
Vue.js组件tree实现无限级树形菜单
Dec 02 Javascript
微信小程序实现收藏与取消收藏切换图片功能
Aug 03 Javascript
微信小程序使用字体图标的方法
May 23 Javascript
在Vue mounted方法中使用data变量详解
Nov 05 Javascript
Javascript模块化机制实现原理详解
Apr 02 Javascript
openlayers4实现点动态扩散
Aug 17 Javascript
如何搭建一个完整的Vue3.0+ts的项目步骤
Oct 18 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
php5中date()得出的时间为什么不是当前时间的解决方法
2008/06/30 PHP
php+iframe实现隐藏无刷新上传文件
2012/02/10 PHP
phpstudy2018升级MySQL5.5为5.7教程(图文)
2018/10/24 PHP
Google排名中的10个最著名的 JavaScript库
2010/04/27 Javascript
JavaScript高级程序设计 阅读笔记(十七) js事件
2012/08/14 Javascript
7个JS基础知识总结
2014/03/05 Javascript
嵌入式iframe子页面与父页面js通信的方法
2015/01/20 Javascript
Jquery+Ajax+PHP+MySQL实现分类列表管理(上)
2015/10/28 Javascript
js检测iframe是否加载完成的方法
2015/11/26 Javascript
JavaScript中匿名函数的递归调用
2017/01/22 Javascript
详解Web使用webpack构建前端项目
2017/09/23 Javascript
javascript实现电脑和手机版样式切换
2017/11/10 Javascript
Vue2仿淘宝实现省市区三级联动
2020/04/15 Javascript
jQuery实现点击DIV同时点击CheckBox,并为DIV上背景色的实例
2017/12/18 jQuery
jq.ajax+php+mysql实现关键字模糊查询(示例讲解)
2018/01/02 Javascript
单页面vue引入百度统计的使用方法示例详解
2018/10/13 Javascript
微信小程序带动画弹窗组件使用方法详解
2018/11/27 Javascript
关于layui 弹出层一闪而过就消失的解决方法
2019/09/09 Javascript
Node.js API详解之 util模块用法实例分析
2020/05/09 Javascript
vue 点击其他区域关闭自定义div操作
2020/07/17 Javascript
解决Vue的文本编辑器 vue-quill-editor 小图标样式排布错乱问题
2020/08/03 Javascript
详解JavaScript类型判断的四种方法
2020/10/21 Javascript
python实现dict版图遍历示例
2014/02/19 Python
Python实现在Windows平台修改文件属性
2020/03/05 Python
Python爬虫自动化爬取b站实时弹幕实例方法
2021/01/26 Python
GLAMGLOW香港官网:明星出镜前的秘密武器
2017/03/16 全球购物
Java里面如何把一个Array数组转换成Collection, List
2013/07/26 面试题
硕士研究生自我鉴定范文
2013/12/27 职场文书
四风问题自查报告剖析材料
2014/02/08 职场文书
体育教师求职信
2014/06/30 职场文书
党校学习心得体会范文
2014/09/09 职场文书
技术股东合作协议书
2014/12/02 职场文书
2015年党员创先争优承诺书
2015/01/22 职场文书
教师年度考核个人总结
2015/02/12 职场文书
Vue + iView实现Excel上传功能的完整代码
2021/06/22 Vue.js
win11高清晰音频管理器在哪里?win11找不到高清晰音频管理器解决办法
2022/04/08 数码科技