亲宝软件园·资讯

展开

Vue.js中this如何取到data和method里的属性详解

前端摸鱼儿 人气:0

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

准备工作

git clone https://github.com/vuejs/vue.git

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

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

<!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>

调试源码

我们这里使用谷歌浏览器调试,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);
      }
  }
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类似,和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的属性。

加载全部内容

相关教程
猜你喜欢
用户评论