陌上寒

陌上寒个人博客

javascript原型(四)prototype在vue中的应用

温故

我们先简明扼要的回顾一下前几天所讨论的内容,总的来说就是一下几点

  • 原型对象prototype
  • 隐式原型__proto__
  • 构造函数constructor

原型对象prototype

还记得prototype是什么吗?
在构造函数new对象的时候,告诉构造函数新创建的对象的原型是谁。
我们将对象简单的分成了两类

  • 函数对象
  • 普通对象
    普通对象都是通过函数创建的,
    每一个函数对象都有一个prototype属性,但是普通对象是没有的。
    好了,不再展开讨论了,如果忘记了,可以翻看我们之前的讨论。

隐式原型__proto__

  • 为了确保浏览器兼容性问题,不要直接使用 __proto__ 属性
  • 普通对象的__proto__指向当前函数对象的原型prototyp,
  • 内置函数对象的__proto__指向的都是ƒ () { [native code] }
  • 所有对象(除了Object.prototype)都存在__proto__
  • Object的原型对象的__proto__为null
    注意:普通对象的__proto__指向(这里的“指向”可以理解为全等“===”)当前函数对象的原型prototype,这一结论使我们将__proto__和prototype关联了起来,原型链就是靠__proto__形成的

构造函数constructor

constructor是原型对象上的一个属性,默认指向这个原型的构造函数
我们把昨天的代码粘贴过来

function Foo(name) {
    this.name = name;
}
var foo = new Foo('陌上寒');
 console.log(Foo.prototype.constructor===Foo)//true
 console.log(foo.constructor===Foo);//true

Foo是foo的构造函数,foo是Foo的实例,
同样的
Foo.prototype是Foo的实例
所以
prototype下的constructor属性返回对创建此对象的函数的引用。
(构造函数constructor,这部分内容我们放在明天详细讨论)

 知新

如题,我们今天重点要说的就是prototype在vue中的应用
通过vue-cli3.x搭建了一个项目,项目地址已上传到github
毕竟vue不是js原生代码,我们得先通过代码了解一下vue
在main.js入口文件中

import Vue from 'vue'
//无关代码省略
console.log(Vue)
//无关代码省略

我们观察输出

//控制台输出如下
ƒ Vue (options) {
  if ( true &&
    !(this instanceof Vue)
  ) {
    warn('Vue is a constructor and should be called with the `new` keyword');
  }
  this._init(options);
}

提示我们Vue是一个构造函数,必须使用new关键字进行实例化,好吧我们再来一次

import Vue from 'vue'
//无关代码省略
var vm = new Vue()
console.log(vm)//输出一个对象(对象很大,就不贴了)
//无关代码省略

也就是Vue这个构造函数经过实例化后,得到一个对象(好像是废话),构造函数是有prototype的,对吧
我们看一下

var vm = new Vue()
//Vue 存在原型
console.log(Vue.prototype);
//普通对象的__proto__指向当前函数对象的原型
console.log(vm.__proto__===Vue.prototype)

js通过原型链可以实现继承那么我们可以对Vue.prototype进行操作,对Vue.prototype添加属性或者方法,所有通过new Vue创建的实例都可以继承这些属性或方法,例如我们在main.js 中添加如下代码

//无关代码省略
Vue.prototype.myName="陌上寒"
//无关代码省略

我们通过路由配置了两个页面(vue-cli默认自带的)Home和About,我们分别打印

//我们分别在两个页面中添加如下代码
  created() {
    console.log(this.myName);//陌上寒
  }

Home 页面和About页面分别打印出了 陌上寒,这个不意外,我们再做一下改动
Home.vue代码如下

//我们分别在两个页面中添加如下代码
created() {
    console.log(this.myName);//陌上寒
    this.myName="陌二哥"//重新赋值
    console.log(this.myName);//陌二哥
}

继续,About.vue代码如下

//我们分别在两个页面中添加如下代码
created() {
    console.log(this.myName);//陌上寒
}

我们看到了,在Home页面对myName进行了重新赋值,当页面从Home跳转到About后,myName并没有更新,这是怎么回事呢?

原型赋值与全局变量

原型赋值和全局变量不是一回事。要区别开来
因为每一次跳转到新的Vue页面,都是一个独立的Vue实例,实例中this.myName从Vue.prototype.myName而来,所以仍然是“陌上寒”。
也就是说Home.vue和About.vue都从Vue.prototype那继承一些属性和方法,继承后,各自想怎么玩怎么玩,但是不能相互影响,设想一些,如果可以随便改变继承源头的属性和方法,岂不是要乱套了?(类似于子组件不能修改父组件的值,他们是一个道理)
那么我就是想在vue中使用全局变量,怎么办呢?这个不是我们今天要讨论的主题,不过我们可以简单的说一下

vue中使用全局对象

如果你用过vue的bus,你就一定会添加全局变量了,当然,在vue中添加全局变量的方法不唯一,我们只介绍这一种
在main.js中

//省略无关代码
new Vue({
  router,
  store,
  data() {
    return {
      website: "https://www.qdtalk.com",
    }
  },
  render: h => h(App)
}).$mount('#app')

在其他页面中就可以使用this.$root.website进行读写操作了,

this.$root.website="陌上寒个人博客"
console.log(this.$root.website)

在实际开发过程中,不论是全局对象还是原型赋值,都会用到的,好了今天就到这里
明天我们重点讨论javascript中的构造函数,不见不散