-
v-bind="{ a: 1, b: 1 }"
这种写法可以将对象里的所有属性绑定 -
v-on="onChange($event, ...arguments)"
这种写法可以传事件对象为第一个参数,其他参数依次往后传递。 -
v-show
不能放在template
上使用,也不能和v-else
使用,为false
时元素会加上display:none
-
v-for
可以和template
标签一起使用
<template v-for="item in list"></template>
- 数组更新检测
- push()
- pop()
- shift()
- unshift()
- splice()
- sort()
- reserve()
- v-for中的key是什么作用?
官方的解释:
- key属性主要用在Vue的虚拟DOM算法,在新旧nodes对比时辨识VNodes;
- 如果不使用key,Vue会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法;
- 而使用key时,它会基于key的变化重新排列元素顺序,并且会移除/销毁key不存在的元素;
Vue事实上会对于有key和没有key会调用两个不同的方法;有key,那么就使用 patchKeyedChildren
方法;没有key,那么久使用 patchUnkeyedChildren
方法;
没有key的过程如下:
- c和d来说它们事实上并不需要有任何的改动;
-
但是因为我们的c被f所使用了,所有后续所有的内容都要一次进行改动,并且最后进行新增;
image.png
有key的diff算法如下:
第一步的操作是从头开始进行遍历、比较:
- a和b是一致的会继续进行比较;
- c和f因为key不一致,所以就会break跳出循环;
第二步的操作是从尾部开始进行遍历、比较:
image.png
第三步是如果旧节点遍历完毕,但是依然有新的节点,那么就新增节点:
image.png
第四步是如果新的节点遍历完毕,但是依然有旧的节点,那么就移除旧节点:
image.png
第五步是最特色的情况,中间还有很多未知的或者乱序的节点:
所以我们可以发现,Vue在进行diff算法的时候,会尽量利用我们的key来进行优化操作:
- 在没有key的时候我们的效率是非常低效的;
- 在进行插入或者重置顺序的时候,保持相同的key可以让diff算法更加的高效;
-
源码如何对computedd的setter和getter处理呢?
事实上非常的简单,Vue源码内部只是做了一个逻辑判断而已;
image.png -
watch监听对象
image.png
- 使用一个选项deep进行更深层的侦听;
- 使用immediate选项, 望一开始的就会立即执行一次
- watch其他监听器的写法:
watch: {
a: 'onChange'
},
methods: {
onChange (val, old) {}
}
还可以在created的生命周期中,使用 this.$watchs 来侦听:
- 第一个参数是要侦听的源
- 第二个参数是侦听的回调函数callback;
- 第三个参数是额外的其他选项,比如deep、immediate;
- v-model的原理
v-model的原理其实是背后有两个操作:
- v-bind绑定value属性的值;
- v-on绑定input事件监听到函数中,函数会获取最新的值赋值到绑定的属性中;
- v-model修饰符
- lazy
如果我们在v-model后跟上lazy修饰符,那么会将绑定的事件切换为 change 事件,只有在提交时(比如回车)
才会触发; - number
如果我们希望转换为数字类型,那么可以使用 .number 修饰符,在我们进行逻辑判断时,如果是一个string类型,在可以转化的情况下会进行隐式转换的 - trim
如果要自动过滤用户输入的守卫空白字符,可以给v-model添加 trim 修饰符
-
当我们传递给一个组件某个属性,但是该属性并没有定义对应的props或者emits时,就称之为 非Prop的Attribute,常见的包括class、style、id属性等。当组件有单个根节点时,非Prop的Attribute将自动添加到根节点的Attribute中,如果我们不希望组件的根元素继承attribute,可以在组件中设置 inheritAttrs: false。可以通过 $attrs来访问所有的 非props的attribute,多个根节点的attribute如果没有显示的绑定,那么会报警告,我们必须手动的指定要绑定到哪一个属性上。
-
子组件向父组件emit事件:
vue3新增申明emits:
可以是一个数组:
emits: ["add", "sub", "addN"]
也可以是对象用来验证参数,只是起到警告作用,验证不通过依然会传给父组件:
emits: {
add: null,
sub: null,
addN: (num, name, age) => {
console.log(num, name, age);
if (num > 10) {
return true
}
return false;
}
},
- 非父子组件的通信
- Provide和Inject
父组件
子组件provide() { return { name: "why", age: 18, length: computed(() => this.names.length) // ref对象 .value } },
<template>
<div>
HomeContent: {{name}} - {{age}} - {{length.value}}
</div>
</template>
<script>
export default {
inject: ["name", "age", "length"],
}
</script>
<style scoped>
</style>
- 全局事件总线mitt库
npm install mitt
import mitt from 'mitt';
const emitter = mitt();
export default emitter;
btnClick() {
console.log("about按钮的点击");
emitter.emit("why", {name: "why", age: 18});
}
created() {
emitter.on("why", (info) => {
console.log("why:", info);
});
emitter.on("kobe", (info) => {
console.log("kobe:", info);
});
emitter.on("*", (type, info) => {
console.log("* listener:", type, info);
})
}
- 异步组件的使用
const AsyncCategory = defineAsyncComponent(() => import("./AsyncCategory.vue"))
const AsyncCategory = defineAsyncComponent({
loader: () => import("./AsyncCategory.vue"),
loadingComponent: Loading,
// errorComponent,
// 在显示loadingComponent组件之前, 等待多长时间
delay: 2000,
/**
* err: 错误信息,
* retry: 函数, 调用retry尝试重新加载
* attempts: 记录尝试的次数
*/
onError: function(err, retry, attempts) {
}
})
- 组件的v-model
组件的v-model实际做了两件事:
<hy-input v-model="message"></hy-input>
<!-- 绑定两个v-model -->
<hy-input v-model="message" v-model:title="title"></hy-input>
<hy-input :modelValue="message" @update:model-value="message = $event"></hy-input>
组件需要$emit(update:modelValue)。
配合组件自己的input的v-model使用:
<template>
<div>
<input v-model="value">
</div>
</template>
<script>
export default {
props: {
modelValue: String
},
emits: ["update:modelValue"],
computed: {
value: {
set(value) {
this.$emit("update:modelValue", value);
},
get() {
return this.modelValue;
}
}
},
methods: {
btnClick(event) {
this.$emit("update:modelValue", event.target.value);
}
}
}
</script>
<style scoped>
</style>
网友评论