Vue.js中this如何取到data和method里的属性详解
目录
- 准备工作
- 调试源码
- initMethods
- initData
- 结束语
本篇文章介绍的是
Vue.js
如何取到data
和methods
里的属性?
准备工作
- 克隆源码到本地
git clone https://github.com/vuejs/vue.git
下载完毕后,用vscode
打开,目光移动到package.json
的scripts
属性,我们看到有dev
和build
,dev
会启动一个开发环境的服务,也就是说,我们在源码里做的改动,都会及时生效。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 (!isPlainObject(data)) { data = {}; warn$2('data functions should return an object:\n' + 'https://v2.vuejs.org/v2/guide/components.html#data-Must-Be-a-Function', vm); } // proxy data on instance var 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 data var ob = observe(data); ob && ob.vmCount++; }
逻辑和initMethods
类似,和props
、methods
做了比对,最后通过proxy
将data
,绑定到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.js
的this
如何取到data
和methods
的属性。
到此这篇关于Vue.js中this如何取到data和method里的属性的文章就介绍到这了,更多相关Vue.js this取data和method属性内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!