作者:fdasfwgafaweg | 来源:互联网 | 2023-09-16 18:36
目录
Vue 实例
创建一个 Vue 实例
数据与方法
生命周期钩子
Vue 实例
创建一个 Vue 实例
每个 Vue 应用都是通过用 Vue
函数创建一个新的 Vue 实例开始的:
var vm = new Vue({// 选项
})
Vue 实例和 Vue 应用是什么关系呢?官方介绍:一个 Vue 应用由一个通过new Vue()
创建的根 Vue 实例,以及可选的嵌套的、可复用的组件树组成。所以 Vue 实例是属于 Vue 应用的一部分,与组件树组成了 Vue 应用:
// 一个Vue应用,由根实例+组件树组成
根实例
└─ 根组件 // 此行开始,为组件树├─ 组件1│ ├─ 组件1-1│ └─ 组件1-2└─ 组件2├─ 组件2-1└─ 组件2-2
数据与方法
当一个 Vue 实例被创建时,它将 data
对象中的所有的 property 加入到 Vue 的响应式系统中。当这些 property 的值发生改变时,视图将会产生“响应”,即匹配更新为新的值。
{{ msg }}
当这些数据改变时,视图会进行重渲染。值得注意的是只有当实例被创建时就已经存在于 data
中的 property 才是响应式的。也就是说如果你添加一个新的 property,比如:
vm.code = 0
那么对 code
的改动将不会触发任何视图的更新。如果你知道你会在晚些时候需要一个 property,但是一开始它为空或不存在,那么你仅需要设置一些初始值。比如:
var data = { msg: "hello vue", code: null }
这里唯一的例外是使用 Object.freeze()
,这会阻止修改现有的 property,也意味着响应系统无法再追踪变化。
// 我们的数据对象var data = { msg: "hello vue", code: null }// 阻止修改现有的 propertyObject.freeze(data)// 该对象被加入到一个 Vue 实例中var vm = new Vue({el: '#app',data: data})
Vue 实例提供了非常丰富的选项(new Vue()
时传入的选项),除了下面介绍的生命周期之外,最常见的大概是这几个了:
选项名 | 说明 | 类型 |
---|
el | 通过 CSS 选择器或者 HTMLElement 实例的方式,提供一个在页面上已存在的 DOM 元素作为 Vue 实例的挂载目标 | string /Element |
template | 字符串模板,将会替换挂载的元素 | string |
render | 字符串模板的代替方案,该渲染函数接收一个createElement 方法作为第一个参数用来创建 VNode | (createElement: () => VNode) => VNode |
data | Vue 实例的数据对象,用于数据绑定 | Object /Function 组件只支持Function |
props | 用于接收来自父组件的数据 | Array /Object |
methods | Vue 实例的事件,可用于事件绑定 | { [key: string]: Function } |
computed | 计算属性,用于简化模板的复杂数据计算 | { [key: string]: Function or { get: Function, set: Function } } |
watch | 观察 Vue 实例变化的一个表达式或计算属性函数 | { [key: string]: string or Function or Object or Array } |
directives | 自定义指令 | Object |
filters | 过滤器 | Object |
components | 组件 | Object |
除了数据 property,Vue 实例还暴露了一些有用的实例 property 与方法。它们都有前缀 $
,以便与用户定义的 property 区分开来。
vm.$data; // 获取 data
vm.$props; // 获取 props
vm.$el; // 获取挂载元素
vm.$options; // 获取 Vue 实例的初始选项
vm.$parent; // 获取父实例
vm.$root; // 获取根实例
vm.$children; // 获取当前实例的直接子组件
vm.$refs; // 获取持有注册过 ref 特性 的所有 DOM 元素和组件实例vm.$watch; // 观察 Vue 实例变化的一个表达式或计算属性函数
vm.$set; // 向响应式对象中添加一个属性,并确保这个新属性同样是响应式的,且触发视图更新
vm.$delete; // 删除对象的属性。如果对象是响应式的,确保删除能触发更新视图
更完整的选项内容和 API,大家可以去官网查询。
生命周期钩子
每个 Vue 实例在被创建时都要经过一系列的初始化过程。例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。
在 Vue 中要渲染一块页面内容的时候,会有这么几个过程:
(1) 解析语法生成 AST。
(2) 根据 AST 结果,完成 data 数据初始化。
(3) 根据 AST 结果和 data 数据绑定情况,生成虚拟 DOM。
(4) 将虚拟 DOM 生成真正的 DOM 插入到页面中,此时页面会被渲染。
当我们绑定的数据进行更新的时候,又会产生以下这些过程:
(5) 框架接收到数据变更的事件,根据数据生成新的虚拟 DOM 树。比较新旧两棵虚拟 DOM 树,得到差异。
(6) 把差异应用到真正的 DOM 树上,即根据差异来更新页面内容。
当我们清空页面内容时,还有:
(7) 注销实例,清空页面内容,移除绑定事件、监听器等。
Vue 生命周期说明
生命周期钩子 | 说明 | 对应上述步骤 |
---|
beforeCreate | 初始化实例前,data 、methods 等不可获取 | 1 之后,2 之前 |
created | 实例初始化完成,此时可获取data 里数据和methods 事件,无法获取 DOM | 2 之后,3 之前 |
beforeMount | 虚拟 DOM 创建完成,此时未挂载到页面中,vm.$el 可获取未挂载模板 | 3 之后,4 之前 |
mounted | 数据绑定完成,真实 DOM 已挂载到页面,vm.$el 可获取真实 DOM | 4 之后 |
beforeUpdate | 数据更新,DOM Diff 得到差异,未更新到页面 | 5 之后,6 之前 |
updated | 数据更新,页面也已更新 | 6 之后 |
beforeDestroy | 实例销毁前 | 7 之前 |
destroyed | 实例销毁完成 | 7 之后 |
官方的生命周期图如下:
官方生命周期图 ![](https://img.php1.cn/3cd4a/1eebe/cd5/a5d7215df572c386.webp?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzI3ODc1OTMz,size_16,color_FFFFFF,t_70)
生命周期钩子的使用方式也很简单,我们可以根据需要在特定的生命周期钩子里进行一些处理:
// 我们的数据对象var data = { msg: "hello vue", code: null }// Object.freeze(data)// 该对象被加入到一个 Vue 实例中var vm = new Vue({el: '#app',data: data,beforeCreate: function() {// 在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用console.log("beforeCreate", this.msg, this.$el);},created: function() {// 在实例创建完成后被立即调用// 在这一步,实例已完成以下的配置:数据观测 (data observer),属性和方法的运算,watch/event 事件回调// 挂载阶段还没开始,$el 属性目前不可见console.log("created", this.msg, this.$el);},beforeMount: function() {// 在挂载开始之前被调用:相关的 render 函数首次被调用console.log("beforeMount", this.msg, this.$el);},mounted: function() {// el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子// 如果 root 实例挂载了一个文档内元素,当 mounted 被调用时 vm.$el 也在文档内// mounted 不会承诺所有的子组件也都一起被挂载// 如果希望等到整个视图都渲染完毕,可以用 vm.$nextTick 替换掉 mountedconsole.log("mounted", this.msg, this.$el);this.$nextTick(function() {// 此处整个视图已渲染完毕});},beforeUpdate: function() {// 数据更新时调用,发生在虚拟 DOM 打补丁之前// 这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器},updated: function() {// 由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子// 当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作},beforeDestroy: function() {// 实例销毁之前调用。在这一步,实例仍然完全可用},destroyed: function() {// Vue 实例销毁后调用// 调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁}})
页面中我们可以看到输出结果,验证了几个生命周期的data
、DOM 挂载等情况:
![](https://img.php1.cn/3cd4a/1eebe/cd5/617c1173853af4b6.webp?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzI3ODc1OTMz,size_16,color_FFFFFF,t_70)