写给自己看的Vue疑问

285 阅读2分钟

引言

由于Vue官方文档写的内容偏向于实战,但是不容易帮助消化

此博客是自己在学习vue时的一些畅想,我会记录我所思考的问题,以及一些总结。这里的想法不一定是对的,仅仅是思考而已。

这篇博客的内容会长期更新,伴随我学习完Vue的内容,最后我将带着我的疑问学习Vue的源码,看看能不能帮助我解释这些问题。


10月5日

实例

从官方文档中看到这个vm是Vue构造函数的实例,我需要在构造函数中传递一个对象,这个对象里面包含了各种选项

var vm = new Vue({
  // 选项
})

我怀着好奇心log了一下Vue的源码,结果发现是这样的

ƒ Vue (options) {
    if (!(this instanceof Vue)
    ) {
      warn('Vue is a constructor and should be called with the `new` keyword');
    }
    this._init(options);
  }

它把参数options传递给了一个_init函数,然后我又搜了一下vm._init

  function initMixin (Vue) {
    Vue.prototype._init = function (options) {
      var vm = this;
      // a uid
      vm._uid = uid$3++;
		...

发现这个_init是定义在Vue的prototype上的,也就是说在实例化之前就写好了,当实例化后就调用Vue构造函数上面的原型方法,当然我这堆解释没什么p用,反正源码太长了也看不懂。

通过官方文档的示例

<div id="app">
  {{ message }}
</div>
var vm = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!'
  }
})

然后页面变成了Hello Vue!

从效果上来看html上面的message变成了构造函数传递的options.data.message,这个options是实例化app时传递的参数。

上面这个el是什么鬼,貌似是获取的元素,通过这个元素,获取到dom。

还有就是{{message}},这个貌似是固定写法,我一定要写成跟data里面的message一致才有效。

我把代码修改成

        let obj = { message: 123 }
        let vm = new Vue({
            el: '#app', data: obj
        })
        console.log(vm.$data === obj);//true
        console.log(vm.message === obj.message);//true

发现实例对象中会有个$data属性跟obj是同一个数据,然后vm.message又跟obj.message是相同的

这引发了我的思考,我打印vm仔细看了一下 发现实例对象有个_data属性,保存着的是obj对象的地址,而_data内部的数据又被展开,变成vm的属性。

那么数据会不会是这样流转的:首先构造函数传入一个options参数,它的data会转变成实例的_data,然后再经过某种方法转化成vm自身的属性,然后通过某种方法将获取到的dom元素中的{{message}}替换掉?

引出疑问

通过上面的描述,给我造成很大的困惑,我总结一下疑问:

  • {{}}是什么 有什么用?
  • eldata是什么,有什么用
  • 实例对象跟Vue构造函数之间的内存是怎样的
  • options里面可以放多少参数
  • 如何把vm._data.message的转化成vm.message【涉及源码】
  • 似乎{{message}}vm.message存在某种关联,究竟怎样可以根据{{}}内部的字符串来替换成vm.message的属性值呢?【涉及源码】

解决疑问

1、el是什么

提供一个在页面上已存在的 DOM 元素作为 Vue 实例的挂载目标。可以是 CSS 选择器,也可以是一个 HTMLElement 实例。

在实例挂载之后,元素可以用 vm.$el 访问。

如果在实例化时存在这个选项,实例将立即进入编译过程,否则,需要显式调用 vm.$mount() 手动开启编译

也就是说,实际上el就是一个挂载点,也就是说,通过这个属性,我们所有的实例化操作都在这个dom内。大白话就是告诉Vue要操作这个dom元素。

Vue提供实例的属性可以访问到他们

<div id="vue_det">
    <h1>site : {{age}}</h1>
</div>
<script type="text/javascript">
// 我们的数据对象
var data = { age:123}
var vm = new Vue({
    el: '#vue_det',
    data: data
})
 
vm.$data === data // true
vm.$el === document.getElementById('vue_det')) // true
</script>

2、data是什么

data主要用于定义属性,根据vue官方文档的说法,推荐这里使用data函数返回一个对象的方式来使用。每次创建一个新的实例时,都会调用data函数,从而返回出一个数据副本。

  var vm = new Vue({
    data(){return {a:1}}
  })
  vm.a // => 1
  vm.$data === data // => true

3、{{}}是什么

{{ }}用于输出对象属性和函数返回值。可以用来做“Mustache”语法 (双大括号) 的文本插值

例如:

<span>Message: {{ msg }}</span>

data函数中返回的对象会影响{{}}里面的数据,当进行修改时,也可以发现页面重新渲染成了新的v.msg的值。这里面支持js语句,神奇!

4、内存图

假设现在有一个实例对象 const vm=new Vue({}),那么其内存图是怎样的呢?我开始画一下

vm.__proto__ === Vue.prototype //true
Vue.__proto__ ===Function.prototype //true
Vue.prototype.__proto__===Object.prototype //true
Function.prototype.__proto__===Object.prototype //true

5、options

从官方文档来看,选项内分上图内容,我将专门写一门博客来完善options。

还剩问题

  • 如何把vm._data.message的转化成vm.message【涉及源码】

  • 似乎{{message}}vm.message存在某种关联,究竟怎样可以让{{}}内部变成vm.message的属性值呢?【涉及源码】

    以上内容来自2020年10月5日