typescript总结笔记(8)常见面试题


## v-html

computed 和 watch

computed 和 watch 的区别

  1. computed有缓存,若data不改变是不会重新计算。watch
  2. watch的深度监听
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    computed: {
    fullname () {
    return this.firstname + ' ' +this.secondname
    },
    computedObj1 () {
    console.log('computedObj1 is change!')
    return this.obj
    },
    compuptedObj2:{
    get() {
    return this.num * 2
    },
    set(value) {
    this.num = value / 2
    }
    },
    },
1
2
3
4
5
6
7
8
9
10
11
12
watch: {
watchObj : {
immediate: true,
deep: true,
handler (new) {

}
},
watchNum (oldVal,newVal) {

}
}

style 和 class

v-if 和 v-show 的区别

v-for

可以遍历数组和对象

为什么要使用key?

v-forv-if为什么不能一起使用?
v-for的优先级比v-if高,所以列表item很多的时候,会先将所有列表item渲染出来,然后再一个个的v-if判断。对性能影响会较差。

event的使用,$event

vue中,的$event是原生的,事件被挂载到当前元素上面了。
事件修饰符:
vue中的事件是有修饰符的,我最常用的是@click.stop,可以阻止事件冒泡。
事件修饰符也可以串联写。

按键修饰符:

v-model

包括 表单的v-model 和 自定义v-model

1. 表单的v-model

1
2
<input type = "text" v-model="name"/>
<div>{{name}}</div>

是下面写法的语法糖,相当于:

1
2
<input type = "text" @input="name = $event.target.value" :value="name">
<div>{{name}}</div>

2. 自定义组件v-model

vue2vue3写法略微不同

父子组件通信 props $emit

父传子

父组件

1
2
<TableChoise @deleteItem="deleteItemEvent" :list="Lists"/>

js部分

1
2
3
deleteItemEvent(item){
console.log(item)
}

子组件

1
<div @click="deleteItemSon($event,list)"></div>

js部分

1
2
3
4
5
6
7
8
9
props: {
Lists: {
type: Array,
default() {
return []
}
}
}
// props: [Lists]

子传父

1
2
3
4
5
methods: {
deleteItemSon ($event,list) {
this.$emit('deleteItem',list)
}
}

组件间的通信 自定义事件

1. eventBus

2. 自定义事件

event.\$on('自定义事件名',触发的事件) 定义自定义事件
event.\$off('自定义事件名') 卸载自定义事件
event.\$emit('自定义事件名',参数) 触发自定义事件

3. 依赖注入 provider/inject

(1)写法
根组件中:

1
2
3
4
5
6
7
8
9
10
11
12
13
// 依赖注入
data () {
return {
message: 'aaaaaaaaa'
}
}
provide () {
return {
message: this.message, // 不会使依赖有响应
// message: computed(() => this.message)
// vue3可以通过导入computed去实现响应式
}
},

任意子孙组件中:

1
inject: ['message'],

依赖注入默认不是相应式的。

vue2.0如何实现响应式的依赖注入?

两种方法,一种可以将根组件的this当做依赖传入,然后用this调用响应式变量。
另一种可以将依赖当做函数传入
父组件

1
2
3
4
5
6
7
provide () {
return {
parents: this // 第一种方法
// vue的provide虽然不是响应式的,但可以将响应式的this传入后,使用this去调用。
parentName: () => this.name // 第二种方法
}
},

任一子孙组件

1
inject: ['parents','parentName'],

子孙组件vue模板

1
2
3
4
  <input type = "text" value = "" v-model = "parents.message"/>
{{message}}
<!-- 用函数依赖注入时,this不能省略 -->
{{ this.parentName() }}

也可以看
官网提供的实例:点击查看
响应式依赖注入:点击查看

组件生命周期

created mounted有什么区别?
created是创建了变量,js中存在了template,但还没有开始渲染
mounted是网页已经绘制完成了,已经渲染了
父子组件的生命周期钩子调用顺序?

自定义v-model

首先,要知道input 和 change两个事件的区别,input是在文本框的值改变时立即触发,而change是在文本框失去焦点时触发。

vue2.2+版本后,新增加了一个model选项,model选项允许自定义prop和event。官方原文是这样的:允许一个自定义组件在使用 v-model 时定制 prop 和 event。默认情况下,一个组件上的 v-model 会把 value 用作 prop 且把 input 用作 event,但是一些输入类型比如单选框和复选框按钮可能想使用 value prop 来达到不同的目的。使用 model 选项可以回避这些情况产生的冲突。

vue2和vue3写法不同。

$nextTick

因为vue是异步框

架,在data改变后,dom不一定会立即渲染。
如果此时想去获取dom中的数据,可能会获取不到。
但如何知道开始渲染了?就在nextTick中获取

1
2
3
this.$nextTick(function() {
console.log('dom done')
})

动态/异步组件

动态组件:
有时候不知道要加载什么组件,可以动态加载

1
<component :is="data中定义的变量,可以根据具体情况修改">

异步组件:
很常用。
内网开发的对内部人员用的网站,像echarts这种很大的组件,会严重影响性能。因为是vue是单文件实现多页切换,首页可能用不到图表也去加载的话,就会影响性能,此时就可以去异步加载。

1
2
3
4
import { defineAsyncComponent } from 'vue'
xxx: defineAsyncComponent(()=>{
import('xxx')
})
1
<xxx>

slot

作用域插槽
具名插槽

keep-alive

1
2
3
4
5
<!-- aaacomponent可以被缓存,bbbcomponent不能被缓存,exclude优先级高于include,exclude和include内部可以写正则去控制 -->
<keep-alive include="aaacomponent" exclude="bbbcomponent">
<aaacomponent />
<bbbcomponent />
</keep-alive>

mixin

多个组件有相同的逻辑,可以放入mixin中。
组件中:

1
2
3
4
import myMixin from './mixin'
export default {
mixins: [myMixin], // 可以引入多个minxin,[myMixin1, myMixin2, myMixin3,...]
}

在mixin.js中

1
2
3
4
5
6
7
8
9
10
export default {
data () {
return {
mixinData: 'mixinData'
}
},
methods: {

},
}

缺点:

  1. 变量来源不明确,引的多了不知道从哪儿来的
  2. 多个mixin引入,如果是不同人开发的话,很有可能里面有变量名冲突。
  3. mixin有可能出现多对多的关系,就是多个组件引入了一个mixin,一个组件还可以引入多个mixin,代码一旦复杂度提升,就会开始头疼了。。。
    vue3和vue2的区别
    v-model
1
2
3
<template>

</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

export default {
computed: {
// 写法1
fullname () {
return this.firstname + this.lastname
}
// 写法2
computedObj: {
get () {
return this.num * 2
}
set () {

}
}
}
}