vue--知识点总结:
目录
1. v-if与v-show的区别
相同点:v-if与v-show都可以动态控制dom元素显示隐藏
不同点:v-if显示隐藏是将dom元素整个添加或删除,而v-show隐藏则是为该元素添加css--display:none,dom元素还在。
注意:
- 手段:v-if是动态的向DOM树内添加或者删除DOM元素;v-show是通过设置DOM元素的display样式属性控制显隐;
- 编译过程:v-if切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子组件;v-show只是简单的基于css切换;
- 编译条件:v-if是惰性的,如果初始条件为假,则什么也不做;只有在条件第一次变为真时才开始局部编译(编译被缓存?编译被缓存后,然后再切换的时候进行局部卸载); v-show是在任何条件下(首次条件是否为真)都被编译,然后被缓存,而且DOM元素保留;
- 性能消耗:v-if有更高的切换消耗;v-show有更高的初始渲染消耗;
- 使用场景:v-if适合运营条件不大可能改变;v-show适合频繁切换。
2. Vue的双向数据绑定原理
答:vue.js 是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。 具体步骤:
- 第一步:需要observe的数据对象进行递归遍历,包括子属性对象的属性,都加上 setter和getter 这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化
- 第二步:compile解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图
- 第三步:Watcher订阅者是Observer和Compile之间通信的桥梁,主要做的事情是:
- 在自身实例化时往属性订阅器(dep)里面添加自己
- 自身必须有一个update()方法
- 待属性变动dep.notice()通知时,能调用自身的update()方法,并触发Compile中绑定的回调,则功成身退。
- 第四步:MVVM作为数据绑定的入口,整合Observer、Compile和Watcher三者,通过Observer来监听自己的model数据变化,通过Compile来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据model变更的双向绑定效果。
3. Vue的生命周期
答:总共分为8个阶段创建前/后,载入前/后,更新前/后,销毁前/后。
- 创建前/后: 在beforeCreated阶段,vue实例的挂载元素$el和数据对象data都为undefined,还未初始化。在created阶段,vue实例的数据对象data有了,$el还没有。
- 载入前/后:在beforeMount阶段,vue实例的$el和data都初始化了,但还是挂载之前为虚拟的dom节点,data.message还未替换。在mounted阶段,vue实例挂载完成,data.message成功渲染。
- 更新前/后:当data变化时,会触发beforeUpdate和updated方法。
- 销毁前/后:在执行destroy方法后,对data的改变不会再触发周期函数,说明此时vue实例已经解除了事件监听以及和dom的绑定,但是dom结构依然存在
(上图是网上找的,忘了出处啦,侵删)
4. 封装 vue 组件的过程
答:首先,组件可以提升整个项目的开发效率。能够把页面抽象成多个相对独立的模块,解决了我们传统项目开发:效率低、难维护、复用性等问题。
然后,使用Vue.extend方法创建一个组件,然后使用Vue.component方法注册组件。子组件需要数据,可以在props中接受定义。而子组件修改好数据后,想把数据传递给父组件。可以采用emit方法。
5. 理解vuex
vuex的核心是:state,getter,actions,mutations
- state就是根据你项目的需求,自己定义的一个数据结构,里面可以放些通用的状态。建议使用mutations来改变state里面的值,因为不通过mutations改变state,状态不会被同步。至于mutations下面会讲到。
- getter怎么理解呢?通俗的理解可以认为是getter里的函数就是vuex里的计算属性,类似于computed函数。 getter函数怎么用呢?如果vuex里定义了一个getter函数addNum。我们可以在vue文件里的computed计算属性里引用,如下。先引入vuex的文件,然后在当前文件的computed中引入你在vuex的getter中定义的函数addNum。
- 更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutations 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数:(需要注意:Mutations必须是同步函数。如果我们需要异步操作,Mutations就不能满足我们需求了,这时候我们就需要Actions了。)
- Action 类似于 mutation,不同在于:Action 提交的是 mutation,而不是直接变更状态。Action 可以包含任意异步操作。(如果我在vue页面里想用action,我们可以分发 Action,Action 通过 store.dispatch 方法触发:)
- mutations由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:
总结:mutation 只管存,你给我(dispatch)我就存;action只管中间处理,处理完我就给你,你怎么存我不管(所有的改变state状态的都是mutation 来操作);Getter 我只管取,我不改的(类似计算属性)。
6.vue页面间传值
一、父组件向子组件传递数据通过props
父组件:使用v-bind传值
子组件:使用props接收
父组件:
<header-box v-bind="message"></header-box>
子组件:
props: {
message: String
},
二、子组件向父组件传值 (参考的vue组件之间的通信来完成,侵删)
子组件向父组件传递分为两种类型:
- 子组件改变父组件传递的props(你会发现通过props中的Object类型参数传输数据,可以通过子组件改变数据内容。这种方式是可行的,但是不推荐使用,因为官方定义prop是单向绑定)
- 通过$on和$emit
**父组件代码**
<template>
<div id="counter-event-example">
<p>{{ total }}</p>
<button-counter v-on:increment="incrementTotal"></button-counter>
</div>
</template>
<script>
import ButtonCounter from './buttonCounter'
export default {
name: 'index',
components: {
'button-conuter': ButtonCounter
},
data () {
return {
total: 0
}
},
methods: {
incrementTotal () {
this.total++
}
}
}
</script>
**子组件代码**
<template>
<button @click="incrementCounter">{{counter}}</button>
</template>
<script>
export default {
name: 'button-counter',
data () {
return {
counter: 0
}
},
metheds: {
incrementCounter () {
this.$emit('increment')
this.counter++
}
}
}
</script>
三、同级传参的两种方式:
- query传参,或者params传参
使用
this.$router.push({ path:'路径值' , query: { 参数名: '参数值' }})
this.$router.push({name: '路由名',params: {参数名: '参数值'}})
注意1:使用params时不能使用path
接收:
var a = this.$route.query.参数名
var b = this.$route.params.参数名
注意:接收传来的值时,最好把接收值的方法放在钩子函数中触发,或者在路由守卫beforeRouteEnter、beforeRouteLeave, 并且使用watch来监听(可以自己搜一下,在钩子函数和路由守卫中触发的区别)
代码示例:
watch: {
// 监测路由变化,只要变化了就调用获取路由参数方法将数据存储本组件即可
'$route': 'getParams'
},
beforeRouteEnter (to, from, next) {
next(vm =>{
vm.getParams();
})
},
beforeRouteLeave(to, from, next) {
next(vm =>{
vm.getParams();
});
},
methods: {
getParams:function(){
var pid = this.$route.query.pid;
},
}
注意2:实用params去传值的时候,在页面刷新时,参数会消失,用query则不会有这个问题。
四、vue组件之间使用bus(总线/观察者模式)传值
- 创建Bus.js
import Vue from 'vue'
const Bus = new Vue();
export default Bus
- 在需要通信的两个组件中引入Bus
import Bus from '@/components/utils/Bus.js';
- 发送消息
Bus.$emit('消息名', 消息值);
- 接收消息
接受组件的事件:写在钩子函数内:例如:mounted created都可以
Bus.$on('msg', (e) => {
this.num = e;
})
五、通过设置Session Storage缓存的形式进行传递
- 两个组件A和B,在A组件中设置缓存orderData
const orderData = { 'orderId': 123, 'price': 88 }
sessionStorage.setItem('缓存名称', JSON.stringify(orderData))
- B组件就可以获取在A中设置的缓存了
const dataB = JSON.parse(sessionStorage.getItem('缓存名称'))
注意:了解一下 Session Storage(程序退出销毁) 和 Local Storage(长期保存) 的区别。
四、vuex
7. vue样式的切换及vue动态样式的使用
- vue中style与class绑定API
<div id="wrap" class="box">
<div v-for="(list,index) in navLists" class="nav"
:class="{ red:changeRed == index}"
@click="reds(index)"
>
{{list.text}}
</div>
</div>
css和js:
*{
padding: 0;margin: 0;
}
.box{
height: 40px;
background: cyan;
}
.nav{
line-height: 40px;
display: inline-block;
margin-left: 100px;
cursor: pointer;
}
.red{
color: red;
}
//前提是必须引入vuejs哦!
var vm = new Vue({
el:"#wrap",
data:{
navLists:[
{
"text":"首页"
},
{
"text":"组件"
},
{
"text":"API"
},
{
"text":"我们"
}
],
changeRed:0
},
methods:{
reds:function(index){
this.changeRed = index;
}
}
});
2. 动态样式的解决方法
- 方法1
:class="{active: isActive}"
通过改变isActive是否为true和false来动态改变样式
- 方法2
class="[lineStyle(courseClick)]"
lineStyle(isClick){
if (isClick===true){
return 'tab-items-current'
}else {
return 'class-tab-items'
}
}
3. v-show和v-if来控制元素的显示、隐藏(上面有说明)
8. vue路由传参3种的基本模式
在vue路由中,支持3种传参方式:
<li v-for="info in indexInfo" @click="getIndexInfo(indexInfo.id)">
- 方案一:
getIndexInfo(id) {
// 直接调用$router.push 实现携带参数的跳转
this.$router.push({
path: `/home/${id}`,
})
// 方案一,需要对应路由配置如下:
{
path: '/home/:id',
name: 'home',
component: home
}
// 很显然,需要在path中添加/:id来对应 $router.push 中path携带的参数。
// 在子组件中可以使用来获取传递的参数值。
$route.params.id