Vue 学习笔记
Vue 是什么呢?
Vue.js 是一套构建用户界面的渐进式框架,只关注视图层,采用自底向上增量的开发设计,实现双向数据绑定及组件化设计。vue 中响应双向绑定数据实现是建立在Object.defineProperty
方法上,通过访问器get
set
进行属性数据拦截。
Vue执行的流程:
(html -> AST -> )生成渲染函数(Render) -> vNode -> DOM
Vue.js 为了给开发者提供便利,提供了一系列的内置指令,来实现数据的响应式,更新DOM。同时,开发者可根据自己需求进行自定义指令。那什么是指令呢,又该如何使用呢?
指令与自定义指令
指令是带有 v- 前缀的特殊attribute。指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式的作用于DOM。常用的指令有:v-text、v-html、v-bind、v-model、v-on、v-for、v-if、v-show 等等。
指令的生命周期为:
- bind: 绑定元素
- inserted
- update
- componentUpdated
- unbind
v-text: 更新元素的innerText内容信息
v-html: 更新元素的innerHtml内容
v-bind:属性 :用于响应式的更新 Attribute(Html Attribute / 自定义Attribute),也可以简写成 :属性,如v-bind:id 可以写成:id 。绑定数据(表达式/对象/)到指定的属性上,如<div v-bind:参数="值/表达式"></div>
<div id="app">
<a v-bind:href="url">跳转</a>
<a :href="url">简写跳转</a>
<a v-bind:href="'url'">表达式跳转</a>
</div>
<script>
new Vue({
el: "#app",
data: {
url: "https://google.cn"
}
})
</script>
v-model: 表单元素上创建双向数据绑定,监听用户输入事件进行更新数据
<div id="app">
<input v-model="message" placeholder="请输入">
<p>Message is: {{ message }}</p>
</div>
v-on: 绑定事件,语法如:
,可简写为:<div @:click="click"><div id="app">
<div v-on:click="click"></div>
</div>
<script>
new Vue({
el: "#app",
methods: {
click: function(){
console.log('click,此处不能用箭头函数')
}
}
})
</script>
v-if、v-show,条件渲染指令
v-if: 根据表达式值的真假,销毁或重建元素,适用于状态切换不频繁的情况
v-show: 根据表达式值的真假,切换元素的display css 属性,适用于状态切换比较频繁的情况
自定义指令
当我们想对一些DOM元素进行低层操作时,这时候我们就可以用到自定义指令。
通过 Vue.directive 或者 在 配置项 中添加directives配置,进行全局/局部指令注册。
如:
Vue.directive('指令名称', {指令配置});
new Vue({
el: '#app',
directives: {
'指令名称': {指令配置}
}
});
使用:
<div id="app">
<input v-focus>
</div>
new Vue({
el: '#app',
directives: {
'focus': function(el){
el.focus()
}
}
});
Vue 中我们会使用不同的组件进行复用,比如头部,底部,侧边、dialog、modal 等组件,那么关于组件,我们又该了解什么呢?接下来我们来分析下Vue Componment 组件的使用。
Vue component 组件
Component 可以扩展HTML 元素,封装可重用的代码,一个组件系统可以用多个可复用的小组件来进行组合。
可以通过Vue.component 全局注册 或者 在Vue 根实例上加入components 属性进行局部注册。
如:
<div id="app">
<login></login>
</div>
<script>
Vue.component('login', {
template: '<h1>Login组件!</h1>'
})
new Vue({
el: '#app'
})
</script>
或者:
<script>
var Login = {
template: '<h1>Login组件!</h1>'
}
new Vue({
el: '#app',
components: {
'login': Login
}
})
</script>
而组件的生命周期跟Vue实例的生命周期是一样的:
-
创建(前/后)
- beforeCreate()
- 在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。初始化阶段,应用不多。
- created()
- 在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer),property 和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,
$el
property 目前尚不可用。 - 常用于异步数据的获取、初始化数据
- 在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer),property 和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,
- beforeCreate()
-
挂载(前/后)
- beforeMount()
- 在挂载开始之前被调用:相关的
render
函数首次被调用。
- 在挂载开始之前被调用:相关的
- mounted()
- 该阶段执行完了模板解析,以及挂载。同时组件根组件元素被赋给了
$el
属性,该阶段可以通过 DOM 操作来对组件内部元素进行处理了。 - 挂载元素dom节点的获取
- 该阶段执行完了模板解析,以及挂载。同时组件根组件元素被赋给了
- beforeMount()
-
更新(前/后)
- beforeUpdate()
- 数据更新时调用,但是还没有对视图进行重新渲染,这个时候,可以获取视图更新之前的状态。
- updated()
- 由于数据的变更导致的视图重新渲染,可以通过 DOM 操作来获取视图的最新状态。
- beforeUpdate()
-
卸载销毁(前/后)
- beforeDestroy()
- 实例销毁之前调用,移除一些不必要的冗余数据,比如定时器。
- destroyed()
- Vue 实例销毁后调用。
- beforeDestroy()
-
其他
- $nextTick()
-
将回调延迟到下次dom更新循环之后执行。
-
- $nextTick()
data 作为组件内部的私有属性,必须是函数。并且该函数必须返回一个对象。
很多时候,为了提供函数的复用性,我们的子组件需要接收外部的数据,那么我们可以通过Props 选项来接收(父组件到子组件的内部数据传递)。在使用中,我们在使用组件时候,通过标签属性的方式进行传参,用v-bind="key" 进行传值。
如
<div id="app">
<login v-bind:name="name" v-bind:length="passwordLen"></login>
</div>
<script>
Vue.component('login', {
template: '<h1>Login组件!</h1>',
props: ['name', 'length']
})
new Vue({
el: '#app',
data: {
"name": "Mark",
"passwordLen": "6"
}
})
</script>
同时,我们可以对props的属性值进行数据类型必要的验证及默认值设定。
如:
<div id="app">
<login v-bind:name="name" v-bind:length="passwordLen"></login>
</div>
<script>
Vue.component('login', {
template: '<h1>Login组件!</h1>',
props: {
name: {
type: String,
default: "测试"
},
length: {
type: Number,
default: 6
},
types: {
validator: function(value) {
return ['man', 'women'].indexOf(value) !== 1
}
}
}
})
new Vue({
el: '#app',
data: {
"name": "Mark",
"passwordLen": "6"
}
})
</script>
在很多时候,有些数据我们需要通过几个属性或者执行计算逻辑才能得出结果,这时,Computed 及 watch 就很有用了。
Computed
computed
中每个key对应一个data中的属性,该属性通过getter/setter的方式进行定义。
如:
<div id="app">
<p>fullName (computed):{{ fullName }}</p>
</div>
var vm = new Vue({
el: '#app',
data: {
firstName: 'Mark',
lastName: 'Yuan',
},
computed: {
fullName: {
get: function() {
return this.firstName + ' ' + this.lastName;
},
set: function(newValue) {
var name = newValue.split(' ');
this.firstName = name[0];
this.lastName = name[name.length - 1];
},
},
},
});
当我们更改fullName的值时,firstName 及 lastName 同时也会更改。
vm.fullName= 'Jay Zhou', 则 vm.firstName 就变成了 Jay 而 vm.lastName 则为Zhou
当然,method 也能实现 Computed 的效果,但是computed是根据关联数据监听改变时才进行计算,计算结果会被缓存起来,而method则不管有没有关联数据监听,都会进行重新计算。
所以,如果需要每次更新,则就用method,而只需要在某个数据更新时才要更新,则用computed
而同样,watch 也能实现跟computed同样的效果。
watch
watch
选项是对指定的响应式数据进行观察,进行处理一些逻辑事务。跟computed 实现有些类似。
<div id="app">
<p>fullName (computed):{{ fullName }}</p>
</div>
var vm = new Vue({
el: '#app',
data: {
firstName: 'Mark',
lastName: 'Yuan',
fullName: 'Mark Yuan'
},
watch: {
firstName: function(val){
this.fullName = this.firstName + ' ' + this.lastName
},
firstName: function(val){
this.fullName = this.firstName + ' ' + this.lastName
},
},
});
watch 更像是data数据的监听回调。当依赖data的数据变化后,执行回调,在方法中传入newVal 和 oldVal。Vue实例将会在实例化时调用$watch(),遍历watch对象中的每一个属性,当某个数据变化时,则就会触发watch。
但是computed跟watch看是乎很相似,那么各自的运用场景在哪比较合适呢?
watch:
- 当在data中某个数据发生变化时,我们需要做一些操作,或者当需要在数据变化时进行异步执行/开销比较大的操作时,可以使用watch来进行监听。
- 一对多的数据更新
computed:
- 使用于一些重复使用的数据或复杂及费时的运算,可以利用computed的缓存特性,下次就可以直接获取了。
- 依赖于其他的数据
以上是我个人见解,如有错误,请多指示。(部分概念从官网摘录)