Vue 实例
栏目: JavaScript · 发布时间: 5年前
内容简介:在刚接触Vue的时候,就知道Vue是一个优势的JavaScript框架,其主要是用来处理
在刚接触Vue的时候,就知道 实例 在Vue中是一个重要的概念,在学习之后也整理了一篇有关于 Vue实例和生命周期的学习笔记 。经过一段时间的学习之后,重新再温习了一遍有关于Vue的实例,整理一下,提供给有需要的同学作为参考资料。
Vue 的基本原理
Vue是一个优势的JavaScript框架,其主要是用来处理 视图层 (我的理解就是UI层)。当用户操作 View Model (即JavaScript,在Vue中指的是Vue实例,一个观察者)使其依照一定的逻辑取得需要改变的数据( Model ),配合在HTML中Vue提供的模板语法来改变配置,重新渲染后使画面产生相应的变化( View )。用一张图来描述这个过程:
比如我们在浏览器中渲染出来的页面有个 区域 和“删除”按钮,当用户点击“删除”按钮之后,会移除这个区域。用户交互之后反馈给用户的是,界面(视图)中的区域被移除。看上去非常的简单,其实在Vue中,主要经历了以下几个过程:
- (1) 用户在界面中点击“Remove”按钮进行交互
- (2) 通过模板中的绑定触发Vue实例中注册的
remove()
事件 - (3)
remove()
事件通过Ajax
向服务器请求数据 - (4) 服务器取得的数据后重新传给Vue实例
- (5) Vue实例修改绑定的ViewModel
- (6) ViewModel改变后触模板重新渲染
- (7) 改变后的视图反馈给用户(用户看到重新渲染后的视图)
咱们可以用下图来描述这个交互的整个过程:
事实上Vue的原理要比这复杂的多,只不过用上图来阐述对于初学者而言在概念上有一定的辅助作用。但其也遵循一个原则: 视图的状态由数据描述,并且通过数据来驱动视图变化 !
深入的概念还无法理解的情况之下,我们暂时只需要先记住,在Vue中视图和数据之间的关系是一个非常简单的关系,即 双向数据绑定 。
Vue采用发布者 —— 订阅者模式实现双向数据绑定,首先Vue将会获得需要监听的对象的所有属性,通过 Object.defineProperty
方法完成对象属性的劫持,将其转化为 getter
和 setter
,当属性被访问或修改时,立即将变化能知给订阅者,并由订阅者完成相应的逻辑操作。
我们可以用下图来描述双向数据绑定主要流程:
-
Observer
:主要处理属性监听逻辑,将监听属性转化为get
和set
属性,当属性被访问时,调用dep.depend()
方法,而属性被修改时,则调用了dep.notify()
方法 -
Dep
:担任发布者的角色,维护访问者列表,负责订阅者的添加和通知工作,上面所提到的depend()
和notify()
方法在这里实现 -
Watcher
:担任订阅者角色,即Dep.target
,可以订阅多个Dep
,在每次收到发布者消息通知时触发update()
方法执行更新逻辑
创建Vue实例
接下来,我们来创建一个Vue实例,就是前面提到的 ViewModel
部分。Vue实例是Vue中很重要的一部分,创建他很简单:
let app = new Vue({ })
创建Vue实例很简单,通过 new Vue({})
即可。事实上,Vue实例就是一个JavaScript对象,而且常常将这个对象赋值给一个 app
变量。
Vue的第一个参数是 options
,它会传给Vue实例这个对象。 options
这个参数主要包括:
-
el
:Vue实例需要挂载的一个DOM元素,一般是index.html
文件中的div#app
元素 -
data
:需要一个输出取得结果的数据 -
methods
:方法 - Vue实例生命周期的钩子函数
比如下面这个示例:
let app = new Vue({ el: '#app', data () { return { message: 'W3cplus.com' } }, methods: { getRemoteMessage () { Promise.resolve('获取远程数据:大漠') .then((res) => { this.message = res }) } } })
除了上面这种方式,Vue实例的挂载还有另外一种方式:
// main.js new Vue({ render: h => h(App), }).$mount('#app')
而给Vue实例传递参数,可以像下面这样的方式:
<!-- App.vue --> <script> export default { name: 'app', data () { return { message: 'W3cplus.com' } }, methods: { getRemoteMessage () { Promise.resolve('获取远程数据:大漠') .then((res) => { this.message = res }) } } } </script>
上面的示例主要做了三件事情:
- 将Vue实例挂载在页面中
id
为app
的一个div
元素上 - 在
data
中初始化了一个message
,并且在<template>
中以{{message}}
方式将data
中的message
显示在页面上 - 定义了一个
getRemoteMessage()
方法,该方法会以非同步的方式取得message
值 - 在
<template>
中的一个button
绑定了定义好的getRemoteMessage()
方法 - 当用户点击界面中的按钮,将会获取远程的一个数据,并且更改
<template>
中message
的值
效果如下:
创建一个Vue实例就是这么的简单。
最开始我们也提到了,Vue实例是Vue中重要的部分之一,甚至可以说, 任何一个Vue的应用程序都是从Vue实例开始的,大创建实例后,可以通过操作实例中的参数来改变页面的配置 。
以上示例代码可以查阅 app-vue-instance 项目的 step1
分支。
Vue实例的生命周期
Vue实例中还有另一个重要的内容,那就是Vue实例的生命周期,在Vue实例中会在各个生命周期中提供相应的钩子函数(Hooks事件),这些钩子函数让开发者可以在Vue实例阶段做相应的处理。Vue官方为Vue实例的生命周期提供了一张非常详细的图:
上图展示了Vue实例整个生命周期,其中红框白底就是生命周期中具备的钩子函数:
-
beforeCreate
:Vue实例初始化的时候会立即调用,其发生在未创立Vue实例之前,这个时候在Vue实例中的设置都还未配置完成,比如data
-
created
:Vue实例创建完成,此时Vue实例中的配置除了$el
外全部配置,而$el
只有在Vue实例挂载到相应的HTML元素时才会生效 -
beforeMount
:在Vue实例挂载到目标元素之前被调用,这时的$el
会是还未被Vue实例中的定义渲染的初始设定的模板 -
mounted
:Vue实例上的设置已经安装上模板,这里的$el
是已经由实例中的定义渲染成真成的页面 -
beforeUpdate
:当Vue实例中的data
发生变化后或是执行vm.$forceUpdate()
调用,这时的页面还未被重新沉浸而改变页面 -
updated
:在重新渲染页面后被调用,这时的页面已经被重新渲染成改变后的页面 -
beforeDestroy
:Vue实例被销毁前调用,这个时候Vue实例还是拥有完整的功能 -
destroyed
:Vue实例被销毁,这个时候Vue实例中的任何定义都已被解除绑定,此时对Vue实例做的任何操作都会失效
接下来看一个小示例,把分支切换到 step2
,来看看Vue实例中操作各个钩子函数,然后打印出 data
和 $el
,看看在各个钩子函数中它们是如何变化的。
<!-- App.vue --> <template> <div id="app"> <img alt="Vue logo" src="./assets/logo.png"> <h2>{{ message }}</h2> <div> <button @click="getRemoteMessage">获取远程数据</button> </div> </div> </template> <script> export default { name: 'app', data () { return { message: 'W3cplus.com' } }, methods: { getRemoteMessage () { Promise.resolve('获取远程数据:大漠') .then((res) => { this.message = res }) } } } </script>
根据上图,将Vue实例生命周期中的钩子函数分成四组:
-
beforeCreate
和created
:创建Vue实例 -
beforeMount
和mounted
:挂载目标元素 -
beforeUpdate
和updated
:改变后重新渲染 -
beforeDestroy
和destroyed
:销毁Vue实例
beforeCreate
和 created
先来看 beforeCreate
和 created
两个钩子函数,在Vue实例中添加这两个钩子函数,打印出相应的 data
和 $el
:
beforeCreate () { console.log(`>>> ==== 钩子函数 beforeCreate ==== >>>`) console.log(`this.message: ${this.message}`) console.log(`this.$el: ${this.$el}`) console.log(`>>> ==== End ==== >>>`) }, created () { console.log(`>>> ==== 钩子函数 created ==== >>>`) console.log(`this.message: ${this.message}`) console.log(`this.$el: ${this.$el}`) console.log(`>>> ==== End ==== >>>`) }
结果如下:
由于 beforeCreate
阶段,Vue实例还没有创建,所以 message
和 $el
都是 undefined
;而到了 created
阶段时,Vue实例已经创建了,所以 message
变成了 W3cplus.com
,但 $el
因为还没有挂载到目标元素,所以依旧是 unddefined
。
也就是说, 在 beforeCreate
钩子中是不能对Vue实例中的任何东西做操作 。
beforeMount
和 mounted
和前面的方式一样,在Vue实例中添加钩子函数 beforeMount
和 mounted
:
beforeMount () { console.log(`>>> |_==_| 钩子函数 beforeMount |_==_| >>>`) console.log(`this.message: ${this.message}`) console.log(`this.$el: ${this.$el}`) console.log(`>> |_==_| this.$el.outerHTML 开始 |_==_| >>`) console.log(this.$el.outerHTML) console.log(`>> |_==_| this.$el.outerHTML 结束 |_==_|`) console.log(`>>> |_==_| End |_==_| >>>`) }, mounted () { console.log(`>>> |_==_| 钩子函数 mounted |_==_| >>>`) console.log(`this.message: ${this.message}`) console.log(`this.$el: ${this.$el}`) console.log(`>> |_==_| this.$el.outerHTML 开始 |_==_| >>`) console.log(this.$el.outerHTML) console.log(`>> |_==_| this.$el.outerHTML 结束 |_==_| >>`) console.log(`>>> |_==_| End |_==_| >>>`) }
结果如下:
在Vue实例的流程图中提到,开始执行 beforeMount
钩子函数时,此时 $el
还没有生成HTML到页面上,因此在执行 this.$el.outerHTML
时会报警,如上图所示。而在执行 mounted
钩子函数时,Vue实例已经绑定到元素上,所以这里看到的是渲染后的结果。
也就是说, 在 beforeMount
前同样不能操作DOM元素 。
beforeUpdate
和 updated
同样的,把 beforeUpdate
和 updated
钩子函数加入到Vue实例中:
beforeUpdate () { console.log(`>>> (^_^) 钩子函数 beforeUpdate (^_^) >>>`) console.log(`this.message: ${this.message}`) console.log(`this.$el: ${this.$el}`) console.log(this.$el.outerHTML) console.log(`>>> (^_^) End (^_^) >>>`) }, updated () { console.log(`>>> (^_^) 钩子函数 updated (^_^) >>>`) console.log(`this.message: ${this.message}`) console.log(`this.$el: ${this.$el}`) console.log(this.$el.outerHTML) console.log(`>>> (^_^) End (^_^) >>>`) }
当你点击页面上的按钮时,打印出来的结果如下:
beforeDestroy
和 destroyed
beforeDestroy () { console.log(`(^_^) 钩子函数 beforeDestroy (^_^)`) console.log(`this.message: ${this.message}`) console.log(`this.$el:${this.$el}`) console.log(this.$el.outerHTML) console.log(`(^_^) End (^_^)`) }, destroyed () { console.log(`(^_^) 钩子函数 destroyed (^_^)`) console.log(`this.message: ${this.message}`) console.log(`this.$el:${this.$el}`) console.log(this.$el.outerHTML) console.log(`(^_^) End (^_^)`) }
第一次执行 app.__vue__.$destroy()
会打印出相应的信息,再执行一次将会报错,如下图所示:
正如上面所示,执行 beforeDestroy
后,即将执行销毁Vue实例,如果想要释放一些资源,可以在这里操作;当执行 destroyed
时,Vue实例将会销毁。比如上面的示例,执行 app.__vue__.$destroy()
后,再点击页面上的按钮,不会有任何的反应,这是因为我们的Vue实例已销毁。
小结
本文从Vue的基本原理着手,学习了Vue的一些基本原理以及相关的概念,然后学习Vue实例的创建以及Vue实例生命周期中的钩子函数,并通过简单的实例,演示了Vue实例中不同钩子函数时实例的状态。这样对于学习Vue实例以及生命周期就不仅仅是停在概念上的,而是知道每个不同周期中对应钩子函数中具体的行为。这样一来,在实际使用Vue的时候,更能清楚的什么事情该在什么样的钩子函数中执行,才能起到相应的效果。特别是对于DOM的操作,掌握这些尤其重要。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Pro JavaScript Techniques
John Resig / Apress / 2006-12-13 / USD 44.99
Pro JavaScript Techniques is the ultimate JavaScript book for the modern web developer. It provides everything you need to know about modern JavaScript, and shows what JavaScript can do for your web s......一起来看看 《Pro JavaScript Techniques》 这本书的介绍吧!