Vue.js的this如何取到data和method里的属性?

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

本篇文章介绍的是Vue.js如何取到datamethods里的属性

准备工作

  • 克隆源码到本地
git clone https://github.com/vuejs/vue.git 

下载完毕后用vscode打开目光移动到package.jsonscripts属性我们看到有devbuilddev会启动一个开发环境的服务也就是说我们在源码里做的改动都会及时生效。build就是打包。和我们平时开发Vue.js项目是一个道理。

我们首先安装一下Vue.js项目的依赖使用pnpm然后运行npm run dev。这样的好处就是我们能随时看到代码改动后的效果。

  • 接下来我们在examples目录下创建一个html文件引入打包后的vue.js
<!DOCTYPE html>
<html lang="en">
 <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title>
 </head>
 <body> <div id="app"> <h1 @click="changeMsg">hello {{msg}}</h1> </div> <script src="../dist/vue.js"></script> <script> const vm = new Vue({ el: '#app', data: { msg: 'world' }, methods: { changeMsg() { this.msg = 'me' } } }) </script>
 </body>
</html> 
  • 安装一个serve全局包启动, 在根目录运行一下serve就能看到页面展示出来了。

调试源码

我们这里使用谷歌浏览器调试F12找到sources面板如下图所示的位置打上断点接着刷新页面就进入了调试模式。

然后我们就通过step into按钮进入new Vue的函数内部。 接着进入_init的内部找到initState(vm),也就是当前文件代码的4714行这个函数的内部就是我们要研究的部分。

进入initState内部我们看到

 if (opts.methods)initMethods(vm, opts.methods);if (opts.data) {initData(vm);} 

initMethods

function initMethods(vm, methods) {var props = vm.$options.props;for (var key in methods) {{if (typeof methods[key] !== 'function') {warn$2("Method \"".concat(key, "\" has type \"").concat(typeof methods[key], "\" in the component definition. ") +"Did you reference the function correctly?", vm);}if (props && hasOwn(props, key)) {warn$2("Method \"".concat(key, "\" has already been defined as a prop."), vm);}if (key in vm && isReserved(key)) {warn$2("Method \"".concat(key, "\" conflicts with an existing Vue instance method. ") +"Avoid defining component methods that start with _ or $.");}}vm[key] = typeof methods[key] !== 'function' ? noop : bind$1(methods[key], vm);}} 
  • 首先判断组件内部是否声明了函数
  • 其次判断是否和props、保留键名的名字冲突了
  • 最后是处理逻辑如果对应值的类型是函数将传入的vm对应的属性赋值否则为noop赋值的函数这里做了一个强绑使用的bind, this指向vm。这个bind$来自原生的bind方法
var bind$1 = Function.prototype.bind ? nativeBind : polyfillBind; 

initData

调试完了initMehtods后就开始initData,我们使用step out按钮就跳出了当前函数接着进入initData内部。

function initData(vm) {var data = vm.$options.data;data = vm._data = isFunction(data) ? getData(data, vm) : data || {};if (<img src="https://v2.vuejs.org/v2/guide/components.html#data-Must-Be-a-Function', vm);}// proxy data on instancevar keys = Object.keys(data);var props = vm.$options.props;var methods = vm.$options.methods;var i = keys.length;while (i--) {var key = keys[i];{if (methods && hasOwn(methods, key)) {warn$2("Method \"".concat(key, "\" has already been defined as a data property."), vm);}}if (props && hasOwn(props, key)) {warn$2("The data property \"".concat(key, "\" is already declared as a prop. ") +"Use prop default value instead.", vm);}else if (!isReserved(key)) {proxy(vm, "_data", key);}}// observe datavar ob = observe(data);ob && ob.vmCount++;}" style="margin: auto" />

逻辑和initMethods类似和propsmethods做了比对最后通过proxydata,绑定到vm

function proxy(target, sourceKey, key) {sharedPropertyDefinition.get = function proxyGetter() {return this[sourceKey][key];};sharedPropertyDefinition.set = function proxySetter(val) {this[sourceKey][key] = val;};Object.defineProperty(target, key, sharedPropertyDefinition);} 

最终我们知道data的值是通过Object.defineProperty实现绑定的。

结束语

我们要研究一个源码首先要准备源码、serve、和调试工具谷歌浏览器然后进入代码的内部才能看的清楚明白我们就此知道了Vue.jsthis如何取到datamethods的属性。

最后

整理了一套《前端大厂面试宝典》包含了HTML、CSS、JavaScript、HTTP、TCP协议、浏览器、VUE、React、数据结构和算法一共201道面试题并对每个问题作出了回答和解析。

有需要的小伙伴可以点击文末卡片领取这份文档无偿分享

部分文档展示



文章篇幅有限后面的内容就不一一展示了

有需要的小伙伴可以点下方卡片免费领取

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: vue