Vue的基本使用(要点)

一、插值、指令

1. 插值

模板语法,括号内仅能使用js表达式,不能写js语句

2. 指令、动态属性

  1. 指令:以v-开头的的模板指令
  2. 动态属性:在模板中以v-bind或冒号:表示,可以写js变量

3. v-html

v-html 会有XSS风险,会覆盖子组件

二、computed和watch

1. computed

  • 具有缓存功能,依赖的数据发生变化时才会重新计算,否则直接读取缓存,因此可提高性能;
  • 具有setget方法,如果读取缓存时,get不会被调用。

2. watch

  1. watchhandler方法有oldValnewVal两个参数
  2. 深度监听,针对的是引用监听。watch默认浅监听,只监听引用对象的一层属性变化,使用deep属性,将deep设置为true可设置为深度监听
  3. 如果监听的是一个引用类型,修改对象的内容时,oldVal参数值与newVal参数值一样,因为oldValnewVal指向的是同一个地址。如果重新赋值新对象,则oldValnewVal正常。

三、class和style

  • 使用动态属性
  • style中的css属性使用驼峰式写法
  • class可以对象和数组的形式,style为对象。
<div :class="{ active: flag }"></div>
<div :class="[ active, selected ]"></div>
<div :style="backgroundStyle"</div>

export default {
    data(){
        return {
            active: 'active',
            selected: 'selected',
            backgroundStyle: {
                fontSize: '12px',
                backgroundColor: '#ffffff'
            }
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

四、条件渲染

  1. v-ifv-elseifv-else,可以使用变量,也可以中===表达式
  2. v-show,使用同v-if
  3. v-ifv-show的区别是什么?
  • 区别:如果v-showv-if条件为true,节点都会渲染,都会被加入到dom树中。如果条件为falsev-if节点不会被渲染,v-show节点还是会被渲染,只是把它设置为display: none
  • 使用场景:如果频繁切换条件,则使用v-show,可以减少性能开销。如果不频繁更改条件,则使用v-if,因为如果频繁的改变条件,dom节点被频繁的装载和卸载销毁,会消耗不必要的性能。

五、循环(列表)渲染

1. v-for遍历数组和对象

<ul>
    <!-- 数组遍历 -->
    <li v-for="(item, index) in array" :key="item.id">{item}</li>
    
    <!-- 对象遍历 -->
    <li v-for="(val, key, index) in array" :key="key">{val}</li>
</ul>
1
2
3
4
5
6
7

2. key的重要性

  • 使用v-for时,为什么要使用key属性?
  • 为什么key尽量使用与数据相关的属性,不要使用indexrandom

为什么? 没有key时,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法。keyvnode的唯一标识,通过keydiff算法操作更准确、更快速。

  • 更准确:带key时就不是“就地复用”,通过key判断新旧节点可以避免“就地复用”的情况。
  • 更快速diff算法利用key的唯一性,存储于map中,通过唯一标识获取对应的节点,比遍历方式更快

3. v-for和v-if不能同时使用

因为v-for的优先级比v-if优先级高,每一次循环都要进行一次判断,会使渲染速度减慢。

六、事件

1. event参数、自定义参数

<!--无参数时,默认带有event-->
<div @click="handleClick1"></div>

<!--多个参数,需要event参数-->
<div @click="handleClick2(2, $event)"></div>

export default {
    methods: {
        handleClick1(e) {
            // e 
            // 1. 原生event对象
            // 2. 监听被挂在当前元素
        },
        
        handleClick2(param, e) {
            // e 同上
        }
    }

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

2. 事件修饰符,按键修饰符

(1)事件修饰符

  • click 单击事件

  • stop 阻止事件继续传播

  • prevent

  • capture 添加事件监听器时使用事件捕获模式,即内部元素触发时先在这里处理,然后才交由内部元素处理

  • submit

  • self 只当event.target自身元素触发时生效,内部元素触发无效

  • 修饰符可以串联使用,如下:

<div v-on:click.stop.prevent="handler"></div>
1
  • 无处理函数,只有修饰符,如下:
<div v-on:submit.prevent></div>
1

(2)按键修饰符

  • enter 回车键按下时触发
  • ctrl.exact 只有ctrl按下时触发
  • click.exact 没有任何系统修饰符被按下时触发

。。。

3. 【观察】事件被绑定到哪里

event.target event.currentTarget

4. v-model

  • v-model 在各个表单控件中的使用
  • v-model.trim 去空格
  • v-model.number 限制只能输入数字

七、组件的基本使用

1. props和$emit

(1)props

export default {
    // 方式一:无类型声明
    props: ['param'],
    
    // 方式二:类型声明
    props: Array,
    
    // 方式三:其他限制参数的属性
    props: {
        type: Array,
        required: true, // true or false
        default: () => [], // 默认值
        validator: () => boolean, // 参数校验
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

(2)$emit

$emit配合props可以进行父子组件的通信

2. 组件间通讯

(1) 父子组件通信

$emitprops

(2) 全局通信

let event = new Vue();
// 发射事件
event.$emit('flag', param)
// 事件监听
event.$on('flag', handler)
// 事件注销,一定要注销事件,否则会重复添加处理函数,导致多次调用处理函数的bug和内存泄漏
event.$off(handler)
1
2
3
4
5
6
7

(3) 与子孙组件的通信

通过使用provideinject,可以跨越多层级的组件进行通信

// 提供依赖
provide() {
    return {
        key: value
    }
}

// 依赖注入
inject: ['key']

1
2
3
4
5
6
7
8
9
10

3. 组件的生命周期

八、Vue的高级特性

1. 自定义v-model

<!--组件A-->
<template>
    <input type="text" :value="param" @input="$emit('change', $event.target.value)"/>
</template>
<!--
1. 上面的 input 使用 :value
2. 上面的 $emit的change,对应model选项的event
3. 上面的 :valute的param,对应props的param
-->

<!--组件B-->
<template>
    <A v-model="name" />
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 组件A
export default {
    model: {
        prop: 'param', // 对应props param
        event: 'change'
    },
    props: {
        param: {
            type: String,
            default: () => ''
        }
    }
}

// 组件B
export default {
    data() {
        return {
            name: ''
        }
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

2. $nextTick

  • Vue是异步渲染
  • data改变之后,DOM不会立即渲染
  • $nextTick会在DOM渲染之后触发,此时才能获取数据更新渲染完成后的最新DOM

总结:

  1. 异步渲染,$nextTick 待 DOM 渲染完成后回调
  2. 在同一个tick内,不管data更改多少次,Vue最后会收集整合data,之后只进行一次渲染

3. slot插槽

(1)插槽的基本使用

(2)具名插槽

(3)作用域插槽

<!-- A组件 -->
<template>
    <div>
        <slot v-bind:user="user"></slot>
    </div>
</template>

<!-- B组件 -->
<template>
    <!-- 拥有具名插槽时 -->
    <A>
        <!-- 默认插槽 -->
        <template v-slot:default="userProps">
            {{ userProps.user.firstName }}
        </template>
        <!-- 具名插槽 -->
        <template v-slot:xxx="xxxProps">
            
        </template>
    </A>
    
    <!-- 只有默认插槽时 -->
    <A v-slot="userProps">
        {{ userProps.user.firstName }}
    </A>
</template>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

4. 动态组件和异步组件

(1)动态组件

<!--
    三个要素:
    1. <component />组件
    2. 动态属性 :is
    3. 组件名称
-->

<component :is="componentName"></component>
1
2
3
4
5
6
7
8

(2)异步组件

  1. 使用异步组件时,不会将异步组件的代码打包到bundle里,需要使用时再请求组件代码,可以有效的减少首次加载时的加载时间,提高加载性能。
  2. import函数的使用

5. keep-alive

6. mixin

(1)抽离多个组件的相同逻辑,可以复用

(2)mixin的合并策略

  1. 组件和mixin中data和methods具有相同变量时,组件的变量会覆盖mixin中的变量;
  2. 组件和mixin中具有相同的生命周期钩子时,mixin的钩子先于组件的钩子被调用。

(3)mixin具有的一些问题

  • 变量来源不明,不利于阅读和追溯
  • 变量命名冲突
  • 复杂度变高

(4)Vue3 的Composition API旨在解决mixin的上述缺点

九、Vue生态

1. vuex

考点:

  1. vuex的基本概念、vuex的基本使用和常用API
  2. 考察state数据结构的设计

(1)基本概念

  • state
  • getters
  • action
  • mutation

(2)常用API

  • dispatch
  • commit
  • mapState
  • mapGetters
  • mapMutations
  • mapActions

(3)vuex逻辑图

注意:只有在action中才可以进行异步操作

3fbcaaf4ad0b947e613b7fd288b662e7.png

2. vue-router

(1)路由模式

  • hash模式(默认),如http://abc.com/#/user/10
  • H5 history模式,如http://abc.com/user/10

H5 history模式需要server端支持,如无特殊情况使用前者

(2)路由配置

  • 动态路由参数,path:user/:id
  • 组件懒加载,component: () => import('./compoentA')