Vue的实例、生命周期与Vue脚手架(vue-cli)实例详解


Posted in Javascript onDecember 27, 2017

一、Vue的实例

1.1、创建一个 Vue 的实例

每个 Vue 应用都是通过 Vue 函数创建一个新的 Vue 实例开始的:

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

虽然没有完全遵循 MVVM 模型,Vue 的设计无疑受到了它的启发。因此在文档中经常会使用 vm (ViewModel 的简称) 这个变量名表示 Vue 实例。

1、vue.js就是一个构造器,通过构造器Vue来实例化一个对象;例如:var vm = new Vue({});

2、实例化Vue时,需要传入一个参数(选项对象);

3、参数:选项对象可以包含,数据(data)、挂载元素(el)、方法(methods)、模版(template)、生命周期函数等等;

4、扩展构造器Vue,从而用预定义选项创建可复用的组件构造器,所有组件都是被扩展的Vue的实例,使用Vue.extend({})来扩展;

注意:尽管可以命令式地创建扩展实例,不过在多数情况下建议将组件构造器注册为一个自定义元素,然后声明式地用在模板中。

当创建一个 Vue 实例时,你可以传入一个选项对象。这篇教程主要描述的就是如何使用这些选项来创建你想要的行为。作为参考,你也可以在 API 文档 中浏览完整的选项列表。

一个 Vue 应用由一个通过 new Vue 创建的根 Vue 实例,以及可选的嵌套的、可复用的组件树组成。举个例子,一个 todo 应用的组件树可以是这样的:

Root Instance
└─ TodoList
├─ TodoItem
│ ├─ DeleteTodoButton
│ └─ EditTodoButton
└─ TodoListFooter
├─ ClearTodosButton
└─ TodoListStatistics

我们会在稍后的组件系统章节具体展开。不过现在,你只需要明白所有的 Vue 组件都是 Vue 实例,并且接受相同的选项对象即可 (一些根实例特有的选项除外)。

1.2、数据与方法

当一个 Vue 实例被创建时,它向 Vue 的响应式系统中加入了其 data 对象中能找到的所有的属性。当这些属性的值发生改变时,视图将会产生“响应”,即匹配更新为新的值。

// 我们的数据对象
var data = { a: 1 }
// 该对象被加入到一个 Vue 实例中
var vm = new Vue({
 data: data
})
// 他们引用相同的对象!
vm.a === data.a // => true
// 设置属性也会影响到原始数据
vm.a = 2
data.a // => 2
// ... 反之亦然
data.a = 3
vm.a // => 3

当这些数据改变时,视图会进行重渲染。 值得注意的是只有当实例被创建时 data 中存在的属性是响应式的 。也就是说如果你添加一个新的属性,像:

vm.b = 'hi'

那么对 b 的改动将不会触发任何视图的更新。

示例:

<!DOCTYPE html>
<html>
 <head>
 <meta charset="UTF-8">
 <title>vue2实例</title>
 </head>
 <body>
 <div id="app1">
  <input type="text" v-model="a"/>
 </div>
 <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
 <script type="text/javascript">
  var data={a:1}
  //实例
  var vm = new Vue({
  el: "#app1",
  data:data,
  updated:function(){
   console.log("实例被更新了!");
  }
  });
 </script>
 </body>
</html>

结果:

Vue的实例、生命周期与Vue脚手架(vue-cli)实例详解

如果你知道你会在晚些时候需要一个属性,但是一开始它为空或不存在,那么你仅需要设置一些初始值。比如:

data: {
newTodoText: '',
visitCount: 0,
hideCompletedTodos: false,
todos: [],
error: null
}

除了 data 属性,Vue 实例暴露了一些有用的实例属性与方法。它们都有前缀 $,以便与用户定义的属性区分开来。例如:

var data = { a: 1 }
var vm = new Vue({
el: '#example',
data: data
})
vm.$data === data // => true
vm.$el === document.getElementById('example') // => true
// $watch 是一个实例方法
vm.$watch('a', function (newValue, oldValue) {
// 这个回调将在 `vm.a` 改变后调用
})

在未来,你可以在 API 参考查阅到完整的实例属性和方法的列表 。

1.3、实例属性

Vue的实例、生命周期与Vue脚手架(vue-cli)实例详解

Vue的实例、生命周期与Vue脚手架(vue-cli)实例详解

解释

vm._uid // 自增的id
vm._isVue // 标示是vue对象,避免被observe
vm._renderProxy // Proxy代理对象
vm._self // 当前vm实例
vm.$parent // 用于自定义子组件中,指向父组件的实例
vm.$root // 指向根vm实例
vm.$children // 当前组件的子组件实例数组
vm.$refs 
vm._watcher = null
vm._inactive = null
vm._directInactive = false
vm._isMounted = false // 标识是否已挂载
vm._isDestroyed = false // 标识是否已销毁
vm._isBeingDestroyed = false // 标识是否正在销毁
vm._events // 当前元素上绑定的自定义事件
vm._hasHookEvent // 标示是否有hook:开头的事件
vm.$vnode // 当前自定义组件在父组件中的vnode,等同于vm.$options._parentVnode
vm._vnode // 当前组件的vnode
vm._staticTrees // 当前组件模板内分析出的静态内容的render函数数组
vm.$el // 当前组件对应的根元素
vm.$slots // 定义在父组件中的slots,是个对象键为name,值为响应的数组
vm.$scopedSlots = emptyObject
// 内部render函数使用的创建vnode的方法
vm._c = (a, b, c, d) => createElement(vm, a, b, c, d, false)
// 用户自定义render方法时,传入的参数
vm.$createElement = (a, b, c, d) => createElement(vm, a, b, c, d, true)
vm._props // 被observe的存储props数据的对象
vm._data // 被observe的存储data数据的对象
vm._computedWatchers // 保存计算属性创建的watcher对象

1.4、实例方法

Vue的实例、生命周期与Vue脚手架(vue-cli)实例详解 

1.5、实例参数vm.$options

vm.$options其实也就是我们new Vue(options)options这个选项对象可传入的属性

declare type ComponentOptions = {
 // data
 data: Object | Function | void; // 传入的data数据
 props?: { [key: string]: PropOptions }; // props传入的数据
 propsData?: ?Object; // 对于自定义组件,父级通过`props`传过来的数据
 computed?: { // 传入的计算属性
 [key: string]: Function | {
 get?: Function;
 set?: Function;
 cache?: boolean
 }
 };
 methods?: { [key: string]: Function }; // 传入的方法
 watch?: { [key: string]: Function | string }; // 传入的watch
 // DOM
 el?: string | Element; // 传入的el字符串
 template?: string; // 传入的模板字符串
 render: (h: () => VNode) => VNode; // 传入的render函数
 renderError?: (h: () => VNode, err: Error) => VNode;
 staticRenderFns?: Array<() => VNode>;
 // 钩子函数
 beforeCreate?: Function;
 created?: Function;
 beforeMount?: Function;
 mounted?: Function;
 beforeUpdate?: Function;
 updated?: Function;
 activated?: Function;
 deactivated?: Function;
 beforeDestroy?: Function;
 destroyed?: Function;
 // assets
 directives?: { [key: string]: Object }; // 指令
 components?: { [key: string]: Class<Component> }; // 子组件的定义
 transitions?: { [key: string]: Object };
 filters?: { [key: string]: Function }; // 过滤器
 // context
 provide?: { [key: string | Symbol]: any } | () => { [key: string | Symbol]: any };
 inject?: { [key: string]: string | Symbol } | Array<string>;
 // component v-model customization
 model?: {
 prop?: string;
 event?: string;
 };
 // misc
 parent?: Component; // 父组件实例
 mixins?: Array<Object>; // mixins传入的数据
 name?: string; // 当前的组件名
 extends?: Class<Component> | Object; // extends传入的数据
 delimiters?: [string, string]; // 模板分隔符
 // 私有属性,均为内部创建自定义组件的对象时使用
 _isComponent?: true; // 是否是组件
 _propKeys?: Array<string>; // props传入对象的键数组
 _parentVnode?: VNode; // 当前组件,在父组件中的VNode对象
 _parentListeners?: ?Object; // 当前组件,在父组件上绑定的事件
 _renderChildren?: ?Array<VNode>; // 父组件中定义在当前元素内的子元素的VNode数组(slot)
 _componentTag: ?string; // 自定义标签名
 _scopeId: ?string;
 _base: Class<Component>; // Vue
 _parentElm: ?Node; // 当前自定义组件的父级dom结点
 _refElm: ?Node; // 当前元素的nextSlibing元素,即当前dom要插入到_parentElm结点下的_refElm前
}

1.5.1、computed计算属性

在模板中绑定表达式是非常便利的,但是它们实际上只用于简单的操作。在模板中放入太多的逻辑会让模板过重且难以维护。例如:

<span>{{msg.split('').reverse().join('')}}</span>

使用计算属性定义成一个方法可以复用且模板会更加简洁:

<!DOCTYPE html>
<html>
 <head>
 <meta charset="UTF-8">
 <title>vue2实例</title>
 </head>
 <body>
 <div id="app1">
  <p>
  <input type="text" v-model="msg" />
  <span>{{msg.split('').reverse().join('')}}</span>
  </p>
  <p>
  <input type="text" v-model="msg" />
  <span>{{revMsg}}</span>
  </p>
 </div>
 <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
 <script type="text/javascript">
  var app1 = new Vue({
  el: "#app1",
  data: {
   msg: "hello"
  },
  computed: {
   revMsg: function() {
   return this.msg.split('').reverse().join('');
   }
  }
  });
 </script>
 </body>
</html>

结果:

Vue的实例、生命周期与Vue脚手架(vue-cli)实例详解

注意:

1、computed中定义的方法只允许当着属性用,不能带参数,这限制它的复用性。

2、当方法中的属性发生变化时方法将重新调用

3、不应该使用箭头函数来定义计算属性函数

4、 computed计算属性可以对属性进行缓存的,计算属性只有当该属性发生变化的时候才会重新计算值

5、如果一个属性不能完成需要的功能时可以考虑转成计算

1.5.2、watch计算属性

一个对象,键是需要观察的表达式,值是对应回调函数。值也可以是方法名,或者包含选项的对象。Vue 实例将会在实例化时调用 $watch(),遍历 watch 对象的每一个属性。

示例:

<!DOCTYPE html>
<html>
 <head>
 <meta charset="UTF-8">
 <title>vue2实例</title>
 </head>
 <body>
 <div id="app1">
  <p>
  a:
  <input type="text" v-model="a" />{{a}}<br/> b:
  <input type="text" v-model="b" />{{b}}<br/> c:
  <input type="text" v-model="c.x.y.z" />{{c.x.y.z}}<br/> d:
  <input type="text" v-model="d" />{{d}}<br/>
  </p>
  <p>
  n:<input type="text" v-model="c.x.y.n" />{{c.x.y.n}}
  </p>
 </div>
 <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
 <script type="text/javascript">
  var app1 = new Vue({
  el: "#app1",
  data: {
   a: 1,
   b: 2,
   c: {
   x: {
    y: {
    z: 3,
    n: 3
    }
   }
   },
   d: 4
  },
  watch: {
   a: function(val, oldVal) {
   console.log('a新: %5s, 原: %5s', val, oldVal);
   },
   // 方法名
   b: 'watchb',
   //对象,深度监视
   c: {
   handler: function(val, oldVal) {
    console.log('c新: %5s, 原: %5s', JSON.stringify(val),JSON.stringify(oldVal));
   },
   deep:true
   },
   //立即监视
   d: {
   handler: function(val, oldVal) {
    console.log('c新: %5s, 原: %5s', val,oldVal);
   },
   immediate:true //设置初始值时也将调用
   }
  },
  methods: {
   watchb: function(val, oldVal) {
   console.log('b新: %5s, 原: %5s', val, oldVal);
   }
  }
  });
  var watchb = function(val, oldVal) {
  console.log('b新: %5s, 原: %5s', val, oldVal);
  }
 </script>
 </body>
</html>

结果:

Vue的实例、生命周期与Vue脚手架(vue-cli)实例详解

注意:不应该使用箭头函数来定义 watcher 函数、对象类型时并非深拷贝的,只是引用。

1.5.3、方法methods

methods 将被混入到 Vue 实例中。可以直接通过 VM 实例访问这些方法,或者在指令表达式中使用。方法中的 this 自动绑定为 Vue 实例。

var vm = new Vue({
 data: { a: 1 },
 methods: {
 plus: function () {
 this.a++
 }
 }
})
vm.plus()
vm.a // 2

示例:

<!DOCTYPE html>
<html>
 <head>
 <meta charset="UTF-8">
 <title>vue2实例</title>
 </head>
 <body>
 <div id="app1">
  <button type="button" v-on:click="add(2)">{{msg}}</button>
 </div>
 <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
 <script type="text/javascript">
  var app1 = new Vue({
  el: "#app1",
  data:{
   msg:"vue"
  },
  methods:{
   add:function(str){
   return this.msg+=str;
   }
  }
  });
  console.log(app1.add(3));
 </script>
 </body>
</html>

结果:

Vue的实例、生命周期与Vue脚手架(vue-cli)实例详解

注意,不应该使用箭头函数来定义 method 函数 (例如 plus: () => this.a++)。理由是箭头函数绑定了父级作用域的上下文,所以 this 将不会按照期望指向 Vue 实例,this.a 将是 undefined。

1.5.4、小结

computed是计算属性的,methods是计算方法的,最主要的区别是 computed计算属性可以对

属性进行缓存的,计算属性只有当该属性发生变化的时候才会重新计算值,只要值没有改变,它是不会重新渲染的,但是methods方法不同,每次调用该方法的时候,都会重新执行的。

1、每个Vue的实例都会代理其data对象里的所有属性,被代理的属性是响应的;

2、如果实例创建之后添加新的属性到实例上,不会触发视图更新;

3、不要在实例属性或者回调函数中(如 vm.$watch('a', newVal => this.myMethod()))使用箭头函数。因为箭头函数绑定父上下文,所以 this 不会像预想的一样是 Vue 实例,而是 this.myMethod 未被定义。

4、Vue实例暴露了一些有用的实例属性和方法,带有前缀 $ 便于与代理的data区分

a、vm.$el:类型(HTMLElement)挂载元素,Vue实例的DOM根元素;

b、vm.$data:类型(Object),Vue实例观察的数据对象

c、vm.$props:类型(Object),属性

d、vm.$options:类型(Object),用于当前Vue实例的初始化选项,在选项中需要包含自定义属性的时候很有用。

e、vm.$parent:类型(Vue实例),父实例。

f、vm.$root:类型(Vue实例),当前组件树的根Vue实例,如果没有父实例,就是实例本身。

h、vm.$children:类型(Array(Vue实例)),当前实例的直接子组件

需要注意 $children 并不保证顺序,也不是响应式的。如果你发现自己正在尝试使用 $children 来进行数据绑定,考虑使用一个数组配合 v-for 来生成子组件,并且使用 Array 作为真正的来源。

i、vm.$slots:类型({ [name: string]: ?Array<VNode> }),用来访问被 slot 分发的内容。每个具名 slot 有其相应的属性(例如:slot="foo" 中的内容将会在 vm.$slots.foo 中被找到)。default 属性包括了所有没有被包含在具名 slot 中的节点。

k、vm.$refs:类型(Object),一个对象,其中包含了所有拥有 ref 注册的子组件;

l、vm.$isServer:类型(boolean),当前Vue实例是否运行于服务器;

官网对应

1.5.5、箭头函数

箭头函数是ES6引入的一种语法糖,使得写函数更加简便,类似Lambda表达式,基本格式如下:

()=>{}

示例:

<!DOCTYPE html>
<html>
 <head>
 <meta charset="UTF-8">
 <title>vue2实例</title>
 </head>
 <body>
 <div id="app1">
 </div>
 <script type="text/javascript">
  var m1=a=>a+1;
  console.log(m1(100));
  //类似
  var m2=function(a){
  return a+1;
  }
  console.log(m2(100));
  
  var m3=(a,b)=>a+b;
  console.log(m3(100,200));
  
  var m4=(a,b)=>{a++; b++; return a+b;}; //如果方法体中有多个表达式,则需要大括号与return
  console.log(m4(100,200));
 </script>
 </body>
</html>

结果:

Vue的实例、生命周期与Vue脚手架(vue-cli)实例详解

二、生命周期 2.1、实例生命周期

每个 Vue 实例在被创建之前都要经过一系列的初始化过程。例如需要设置数据监听、编译模板、挂载实例到 DOM、在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,给予用户机会在一些特定的场景下添加他们自己的代码。

比如 created 钩子可以用来在一个实例被创建之后执行代码:

new Vue({
data: {
a: 1
},
created: function () {
// `this` 指向 vm 实例
console.log('a is: ' + this.a)
}
})
// => "a is: 1"

也有一些其它的钩子,在实例生命周期的不同场景下调用,如 mounted、updated、destroyed。钩子的 this 指向调用它的 Vue 实例。

不要在选项属性或回调上使用箭头函数,比如 created: () => console.log(this.a) 或 vm.$watch('a', newValue => this.myMethod())。因为箭头函数是和父级上下文绑定在一起的,this 不会是如你所预期的 Vue 实例,经常导致 Uncaught TypeError: Cannot read property of undefined 或 Uncaught TypeError: this.myMethod is not a function 之类的错误。

2.2、生命周期图示

下图说明了实例的生命周期。你不需要立马弄明白所有的东西,不过随着你的不断学习和使用,它的参考价值会越来越高。

Vue的实例、生命周期与Vue脚手架(vue-cli)实例详解

中文版:

Vue的实例、生命周期与Vue脚手架(vue-cli)实例详解

1. beforeCreate

在实例初始化之后,数据观测(data observer) 和 event/watcher 事件配置之前被调用。

2. created

实例已经创建完成之后被调用。在这一步,实例已完成以下的配置:数据观测(data observer),属性和方法的运算, watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。 可以在组件的这个期间请求数据,如果是keep-alive组件会被缓存起来,生命周期不会再次触发,如果需要更新数据可以watch当前router变化,如果router是当前组件所在的router则请求数据。

methods : {
getData : function(id){
...
this.content = 'test';
}
},
created : function(){
this.getData(this.id);
}
...
watch : {
$route : function(){
if(this.$route.name == 'xxx'){
this.getData(this.id);
}
}
}

3. beforeMount

在挂载开始之前被调用:相关的 render 函数首次被调用。

4. mounted

vm.$el已挂载在文档内,对已有dom节点的操作可以在这期间进行。

5. beforeUpdate

数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。

可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程。

6.updated

由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。

当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态,因为这可能会导致更新无限循环。

7.activated

keep-alive 组件激活时调用。

8.deactivated

keep-alive 组件停用时调用。

9.beforeDestroy

实例销毁之前调用。在这一步,实例仍然完全可用。

10.destroyed

Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。

2.3、生命周期示例一

示例1:

<!DOCTYPE html>
<html>
 <head>
 <meta charset="UTF-8">
 <title>vue2生命周期</title>
 </head>
 <body>
 <div id="app1">
  <input v-model="msg" /> {{msg}}
 </div>
 <button type="button" onclick="destroy()">销毁</button>
 <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
 <script type="text/javascript">
  //格式化输出
  console.log("示例:%c%s","background:red;color:#fff","vue2生命周期","开始了");
  
  var app1 = new Vue({
  el: "#app1",
  data:{
   msg:"vue"
  },
  beforeCreate:function(){
   console.log("创建前:"+this.msg);
  },
  created:function(){
   console.log("创建后:"+this.msg+","+this.$el);
  },
  beforeMount:function(){
   console.log("挂载前:");
   console.log(this.$el);
  },
  mounted:function(){
   console.log("挂载后:");
   console.log(this.$el);
  },
  beforeUpdate:function(){
   console.log("实例更新前:");
   console.log(this.msg);
   console.log(this.$el);
  },
  updated:function(){
   console.log("实例更新后:");
   console.log(this.msg);
   console.log(this.$el);
  },
  beforeDestroy:function(){
   console.log("实例销毁前:");
   console.log(this.msg);     
  },
  destroyed:function(){
   console.log("实例销毁后:");
   console.log(this.msg);
  }
  });
  
  function destroy(){
  app1.$destroy();
  }
 </script>
 </body>
</html>

初始化结果1:

Vue的实例、生命周期与Vue脚手架(vue-cli)实例详解

修改msg的值为vue2后的结果:

Vue的实例、生命周期与Vue脚手架(vue-cli)实例详解

执行销毁:

Vue的实例、生命周期与Vue脚手架(vue-cli)实例详解

2.4、生命周期示例二

示例2:

<!DOCTYPE html>
<html>
 <head>
 <title>Vue2生命周期</title>
 </head>
 <body>
 <div id="app">{{ message }}</div>
 <script type="text/javascript" src="https://cdn.jsdelivr.net/vue/2.1.3/vue.js"></script>
 <script type="text/javascript">
  var app = new Vue({
  el: '#app',
  data: {
   message: "South IT College!"
  },
  beforeCreate: function() {
   console.group('beforeCreate 创建前状态===============》');
   console.log("%c%s", "color:red", "el : " + this.$el); //undefined
   console.log("%c%s", "color:red", "data : " + this.$data); //undefined 
   console.log("%c%s", "color:red", "message: " + this.message)
  },
  created: function() {
   console.group('created 创建完毕状态===============》');
   console.log("%c%s", "color:red", "el : " + this.$el); //undefined
   console.log("%c%s", "color:red", "data : " + this.$data); //已被初始化 
   console.log("%c%s", "color:red", "message: " + this.message); //已被初始化
  },
  beforeMount: function() {
   console.group('beforeMount 挂载前状态===============》');
   console.log("%c%s", "color:red", "el : " + (this.$el)); //已被初始化
   console.log(this.$el);
   console.log("%c%s", "color:red", "data : " + this.$data); //已被初始化 
   console.log("%c%s", "color:red", "message: " + this.message); //已被初始化 
  },
  mounted: function() {
   console.group('mounted 挂载结束状态===============》');
   console.log("%c%s", "color:red", "el : " + this.$el); //已被初始化
   console.log(this.$el);
   console.log("%c%s", "color:red", "data : " + this.$data); //已被初始化
   console.log("%c%s", "color:red", "message: " + this.message); //已被初始化 
  },
  beforeUpdate: function() {
   console.group('beforeUpdate 更新前状态===============》');
   console.log("%c%s", "color:red", "el : " + this.$el);
   console.log(this.$el);
   console.log("%c%s", "color:red", "data : " + this.$data);
   console.log("%c%s", "color:red", "message: " + this.message);
  },
  updated: function() {
   console.group('updated 更新完成状态===============》');
   console.log("%c%s", "color:red", "el : " + this.$el);
   console.log(this.$el);
   console.log("%c%s", "color:red", "data : " + this.$data);
   console.log("%c%s", "color:red", "message: " + this.message);
  },
  beforeDestroy: function() {
   console.group('beforeDestroy 销毁前状态===============》');
   console.log("%c%s", "color:red", "el : " + this.$el);
   console.log(this.$el);
   console.log("%c%s", "color:red", "data : " + this.$data);
   console.log("%c%s", "color:red", "message: " + this.message);
  },
  destroyed: function() {
   console.group('destroyed 销毁完成状态===============》');
   console.log("%c%s", "color:red", "el : " + this.$el);
   console.log(this.$el);
   console.log("%c%s", "color:red", "data : " + this.$data);
   console.log("%c%s", "color:red", "message: " + this.message)
  }
  })
 </script>
 </body>
</html>

初始化结果:

Vue的实例、生命周期与Vue脚手架(vue-cli)实例详解

更新message的值:

Vue的实例、生命周期与Vue脚手架(vue-cli)实例详解

手动销毁实例:

Vue的实例、生命周期与Vue脚手架(vue-cli)实例详解

2.5、手动挂载与调用事件 2.5.1、手动挂载

vm.$mount( [elementOrSelector] ) 如果 Vue 实例在实例化时没有收到 el 选项,则它处于“未挂载”状态,没有关联的 DOM 元素。可以使用 vm.$mount() 手动地挂载一个未挂载的实例。

如果没有提供 elementOrSelector 参数,模板将被渲染为文档之外的的元素,并且你必须使用原生 DOM API 把它插入文档中。

这个方法返回实例自身,因而可以链式调用其它实例方法。

var MyComponent = Vue.extend({
template: '<div>Hello!</div>'
})
// 创建并挂载到 #app (会替换 #app)
new MyComponent().$mount('#app')
// 同上
new MyComponent({ el: '#app' })
// 或者,在文档之外渲染并且随后挂载
var component = new MyComponent().$mount()
document.getElementById('app').appendChild(component.$el)

示例:

<!DOCTYPE html>
<html>
 <head>
 <meta charset="UTF-8">
 <title>vue2生命周期</title>
 <style>
  #app1 {
  color: red;
  }
  #app2 {
  color: blue;
  }
 </style>
 </head>
 <body>
 <div id="app1">
 </div>
 <div id="app2">
 </div>
 <button type="button" onclick="loaddata1()">手动挂载1</button>
 <button type="button" onclick="loaddata2()">手动挂载2</button>
 <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
 <script type="text/javascript">
  var app1 = new Vue({
  template: "<h2>{{msg}}</h2>",
  data: {
   msg: "Hello Vue2!"
  }
  });
  function loaddata1() {
  app1.$mount("#app1");
  document.getElementById("app1").appendChild(app1.$el);
  }
  function loaddata2() {
  app1.$mount();
  document.getElementById("app2").appendChild(app1.$el);
  }
 </script>
 </body>
</html>

结果:

Vue的实例、生命周期与Vue脚手架(vue-cli)实例详解

2.5.2、销毁实例

vm.$destroy() 完全销毁一个实例。清理它与其它实例的连接,解绑它的全部指令及事件监听器。

2.5.3、强制更新

vm.$forceUpdate() 迫使 Vue 实例重新渲染。注意它仅仅影响实例本身和插入插槽内容的子组件,而不是所有子组件。

Vue的实例、生命周期与Vue脚手架(vue-cli)实例详解

三、Vue脚手架(vue-cli)

单页Web应用(single page web application,SPA),就是只有一张Web页面的应用,是加载单个HTML 页面并在用户与应用程序交互时动态更新该页面的Web应用程序。

提供一个官方命令行工具,可用于快速搭建大型单页应用(SPA)。该工具为现代化的前端开发工作流提供了开箱即用的构建配置。只需几分钟即可创建并启动一个带热重载、保存时静态检查以及可用于生产环境的构建配置的项目:

# 全局安装 vue-cli
$ npm install --global vue-cli
# 创建一个基于 webpack 模板的新项目
$ vue init webpack my-project
# 安装依赖,走你
$ cd my-project
$ npm install
$ npm run dev

注意:CLI 工具假定用户对 Node.js 和相关构建工具有一定程度的了解。如果你是新手,我们强烈建议先在不用构建工具的情况下通读指南,在熟悉 Vue 本身之后再使用 CLI。

3.1、环境搭建 3.1.1、安装node.js

从n ode.js官网 下载并安装node,安装过程很简单,一路“下一步”就可以了。安装完成之后,打开命令行工具(win+r,然后输入cmd),输入 node -v,如下图,如果出现相应的版本号,则说明安装成功。

Vue的实例、生命周期与Vue脚手架(vue-cli)实例详解

如果安装不成功,可以直接把安装包修改成压缩包,解压后配置环境变量也可以,就成了绿色版。

Vue的实例、生命周期与Vue脚手架(vue-cli)实例详解

这里需要说明下,因为在官网下载安装node.js后,就已经自带npm(包管理工具)了,另需要注意的是npm的版本最好是3.x.x以上,以免对后续产生影响。

注意版本不能太低,如果您已经安装了低版本的node可以使用npm直接更新。

3.1.2、修改npm为淘宝镜像

因为npm的仓库有许多在国外,访问的速度较慢,建议修改成cnpm,换成taobao的镜像。

打开命令行工具,复制如下配置:

npm install -g cnpm --registry=https://registry.npm.taobao.org

安装这里是因为我们用的npm的服务器是外国,有的时候我们安装“依赖”的时候很很慢很慢超级慢,所以就用这个cnpm来安装我们说需要的“依赖”。安装完成之后输入 cnpm -v,如下图,如果出现相应的版本号,则说明安装成功。

Vue的实例、生命周期与Vue脚手架(vue-cli)实例详解

版本号:

Vue的实例、生命周期与Vue脚手架(vue-cli)实例详解

3.1.3、安装webpack

安装webpack,打开命令行工具输入:

npm install webpack -g

Vue的实例、生命周期与Vue脚手架(vue-cli)实例详解

安装完成之后输入

webpack -v

如下图,如果出现相应的版本号,则说明安装成功。

Vue的实例、生命周期与Vue脚手架(vue-cli)实例详解

3.1.4、安装vue-cli脚手架构建工具

打开命令行工具输入:

cnpm install vue-cli -g

安装完成之后输入 vue -V(注意这里是大写的“V”),如下图,如果出现相应的版本号,则说明安装成功。

Vue的实例、生命周期与Vue脚手架(vue-cli)实例详解

3.2、构建项目

1)、在硬盘上找一个文件夹放工程用的。这里有两种方式指定到相关目录:

①cd 目录路径

②如果以安装git的,在相关目录右键选择Git Bash Here

2)、安装vue脚手架输入:vue init webpack projectName,注意这里的“projectName” 是项目的名称可以说是随便的起名,但是“ 不能用中文 ”。

提示选择项:

$ vue init webpack exprice --------------------- 这个是那个安装vue脚手架的命令
This will install Vue 2.x version of the template. ---------------------这里说明将要创建一个vue 2.x版本的项目
For Vue 1.x use: vue init webpack#1.0 exprice
? Project name (exprice) ---------------------项目名称
? Project name exprice
? Project description (A Vue.js project) ---------------------项目描述
? Project description A Vue.js project
? Author Datura --------------------- 项目创建者
? Author Datura
? Vue build (Use arrow keys)
? Vue build standalone
? Install vue-router? (Y/n) --------------------- 是否安装Vue路由,也就是以后是spa(但页面应用需要的模块)
? Install vue-router? Yes
? Use ESLint to lint your code? (Y/n) n ---------------------是否启用eslint检测规则,这里个人建议选no
? Use ESLint to lint your code? No
? Setup unit tests with Karma + Mocha? (Y/n)
? Setup unit tests with Karma + Mocha? Yes
? Setup e2e tests with Nightwatch? (Y/n)
? Setup e2e tests with Nightwatch? Yes
vue-cli · Generated "exprice".
To get started: --------------------- 这里说明如何启动这个服务
cd exprice
npm install
npm run dev

Vue的实例、生命周期与Vue脚手架(vue-cli)实例详解

3)、cd 命令进入创建的工程目录,首先cd projectName;

4)、安装项目依赖:npm install,因为自动构建过程中已存在package.json文件,所以这里直接安装依赖就行。不要从国内镜像cnpm安装(会导致后面缺了很多依赖库),但是但是如果真的安装“个把”小时也没成功那就用:cnpm install 吧

5)、安装 vue 路由模块 vue-router 和网络请求模块 vue-resource,输入:cnpm install vue-router vue-resource --save。

Vue的实例、生命周期与Vue脚手架(vue-cli)实例详解

目录:

|-- build       // 项目构建(webpack)相关代码
| |-- build.js      // 生产环境构建代码
| |-- check-version.js    // 检查node、npm等版本
| |-- dev-client.js    // 热重载相关
| |-- dev-server.js    // 构建本地服务器
| |-- utils.js      // 构建工具相关
| |-- webpack.base.conf.js   // webpack基础配置
| |-- webpack.dev.conf.js   // webpack开发环境配置
| |-- webpack.prod.conf.js   // webpack生产环境配置
|-- config       // 项目开发环境配置
| |-- dev.env.js     // 开发环境变量
| |-- index.js      // 项目一些配置变量
| |-- prod.env.js     // 生产环境变量
| |-- test.env.js     // 测试环境变量
|-- src        // 源码目录
| |-- components      // vue公共组件
| |-- store       // vuex的状态管理
| |-- App.vue      // 页面入口文件
| |-- main.js      // 程序入口文件,加载各种公共组件
|-- static       // 静态文件,比如一些图片,json数据等
| |-- data       // 群聊分析得到的数据用于数据可视化
|-- .babelrc       // ES6语法编译配置
|-- .editorconfig     // 定义代码格式
|-- .gitignore      // git上传需要忽略的文件格式
|-- README.md      // 项目说明
|-- favicon.ico 
|-- index.html      // 入口页面
|-- package.json      // 项目基本信息

3.3、运行项目

6)、启动项目,输入:npm run dev。服务启动成功后浏览器会默认打开一个“欢迎页面”,如下图:

Vue的实例、生命周期与Vue脚手架(vue-cli)实例详解

编译成功后可以直接在浏览器中查看项目:

Vue的实例、生命周期与Vue脚手架(vue-cli)实例详解

3.4、Vue-cli HelloWorld

了解了默认的模板内容,我们可以开始定义自己的vue程序了,这里写一个简单的HelloWorld,在src目录下创建一个Hi.vue文件,内容如下:

<template>
 <div id="app1">
  <input v-model="msg" v-on:click="sayhi"/>
  <p>
   <h2>{{msg}}</h2>
  </p>
 </div>
</template>

<script>
 export default {
  name: 'Hi',
  data() {
   return {
    msg: 'My First vue-cli app!'
   }
  },
  methods:{
   sayhi:function(){
    alert(this.msg);
   }
  }
 }
</script>
<style>
 #app1 {
  font-family: "microsoft yahei";
  color: dodgerblue;
  font-size: 20px;
 }
</style>

修改main.js

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './Hi'

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
 el: '#app',
 template: '<App/>',
 components: { App }
})

运行结果:

Vue的实例、生命周期与Vue脚手架(vue-cli)实例详解

四、示例下载

https://git.coding.net/zhangguo5/vue2.git

五、视频

https://www.bilibili.com/video/av17503637/

六、作业

1、请定义任意一个Vue实例,触发Vue实例中的8个事件,将结果输出到控制台,要求可以观察到数据初始化与挂载情况。

2、请使用vue2+bootstrap完成如下功能:

要求如下:

a)、实现添加功能

b)、实现删除功能

c)、实现编辑功能,增加按钮

d)、实现隔行换色

e)、实现按年龄排序

Vue的实例、生命周期与Vue脚手架(vue-cli)实例详解

参考 :

Vue的实例、生命周期与Vue脚手架(vue-cli)实例详解

Vue的实例、生命周期与Vue脚手架(vue-cli)实例详解

Vue的实例、生命周期与Vue脚手架(vue-cli)实例详解Vue的实例、生命周期与Vue脚手架(vue-cli)实例详解

总结

以上所述是小编给大家介绍的Vue的实例、生命周期与Vue脚手架(vue-cli)实例详解,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
解密效果
Jun 23 Javascript
Mootools 1.2教程 输入过滤第二部分(字符串)
Sep 15 Javascript
JavaScript写的一个自定义弹出式对话框代码
Jan 17 Javascript
JavaScript限定复选框的选择个数示例代码
Aug 25 Javascript
使用js显示当前时间示例
Mar 02 Javascript
PHP中使用微秒计算脚本执行时间例子
Nov 19 Javascript
jQuery对指定元素中指定字符串进行替换的方法
Mar 17 Javascript
js实现点击获取验证码倒计时效果
Jan 28 Javascript
Angular 4依赖注入学习教程之组件服务注入(二)
Jun 04 Javascript
使用Vue-Awesome-Swiper实现旋转叠加轮播效果&amp;平移轮播效果
Aug 16 Javascript
如何手写简易的 Vue Router
Oct 10 Javascript
el-table-column 内容不自动换行的解决方法
Aug 14 Vue.js
Angular实现的简单查询天气预报功能示例
Dec 27 #Javascript
Angular实现点击按钮后在上方显示输入内容的方法
Dec 27 #Javascript
Angular实现的日程表功能【可添加及隐藏显示内容】
Dec 27 #Javascript
Vue+SpringBoot开发V部落博客管理平台
Dec 27 #Javascript
简单的Vue异步组件实例Demo
Dec 27 #Javascript
Vue.js组件间的循环引用方法示例
Dec 27 #Javascript
全面介绍vue 全家桶和项目实例
Dec 27 #Javascript
You might like
曾在DC漫画界反派角色扮演的演员,谁才是你心目中的小丑之王?
2020/04/09 欧美动漫
ubuntu 编译安装php 5.3.3+memcache的方法
2010/08/05 PHP
PHP调用Linux命令权限不足问题解决方法
2015/02/07 PHP
微信 开发生成带参数的二维码的实例
2016/11/23 PHP
Yii2框架数据验证操作实例详解
2018/05/02 PHP
ThinkPHP中图片按比例切割的代码实例
2019/03/08 PHP
PHP获取当前时间不准确问题解决方案
2020/08/14 PHP
关于使用runtimeStyle属性问题讨论文章
2007/03/08 Javascript
Javascript和Ajax中文乱码吐血版解决方案
2009/12/21 Javascript
jQuery选择头像并实时显示的代码
2010/06/27 Javascript
JavaScript/Js脚本处理html元素的自定义属性解析(亲测兼容Firefox与IE)
2013/11/25 Javascript
解决extjs grid 不随窗口大小自适应的改变问题
2014/01/26 Javascript
淘宝网提供的国内NPM镜像简介和使用方法
2014/04/17 Javascript
JavaScript数值数组排序示例分享
2014/05/27 Javascript
实例解析jQuery插件EasyUI最常用的表单验证规则
2015/11/29 Javascript
Nodejs爬虫进阶教程之异步并发控制
2016/02/15 NodeJs
jQuery快速实现商品数量加减的方法
2017/02/06 Javascript
使用jQuery实现鼠标点击左右按钮滑动切换
2017/08/04 jQuery
安装多版本Vue-CLI的实现方法
2020/03/24 Javascript
浅谈React中组件逻辑复用的那些事儿
2020/05/21 Javascript
nodejs+express最简易的连接数据库的方法
2020/12/23 NodeJs
详解阿里Node.js技术文档之process模块学习指南
2021/01/04 Javascript
vue 中this.$set 动态绑定数据的案例讲解
2021/01/29 Vue.js
pycharm安装图文教程
2017/05/02 Python
基于python OpenCV实现动态人脸检测
2018/05/25 Python
Django restframework 框架认证、权限、限流用法示例
2019/12/21 Python
浅谈selenium如何应对网页内容需要鼠标滚动加载的问题
2020/03/14 Python
Python urllib2运行过程原理解析
2020/06/04 Python
意大利灯具购物网站:Lampade.it
2018/10/18 全球购物
企业统计员岗位职责
2013/12/13 职场文书
周年庆促销方案
2014/03/15 职场文书
中秋晚会策划方案
2014/06/12 职场文书
党员自我剖析材料范文
2014/10/06 职场文书
北大自主招生自荐信
2015/03/04 职场文书
社会实践活动总结格式
2015/05/11 职场文书
vue首次渲染全过程
2021/04/21 Vue.js