1. 对 Slot 的理解
1.1 什么是 slot?
插槽(slot)是一种在 Vue 中用于组件化开发的重要概念。它允许开发者在组件中定义可灵活插入内容的位置,从而实现更高度可定制化的组件复用。
换句话来说,可以理解为 slot 在组件模板中占好了位置,当使用该组件标签时,组件标签里面的内容就会自动填坑(替换组件模板中 slot 位置),作为承载分发内容的出口。
1.2 使用场景
1. 通过插槽可以让用户可以拓展组件,去更好地复用组件和对其做定制化处理;
2. 若父组件在使用到一个复用组件的时候,获取这个组件在不同的地方有少量的更改,如果去重写组件是一件不明智的事情;
3. 通过 slot 插槽向组件内部指定位置传递内容,完成这个复用组件在不同场景的应用(比如 布局组件、表格列、下拉选、弹框显示内容等)
1.3 分类
1.3.1 默认插槽
子组件可以使用 < slot > 标签来确定渲染的位置,标签里面可以放 DOM 结构,当父组件使用的时候没有往插槽传入内容,标签内 DOM 结构就会显示在页面上。
父组件在使用的时候,直接在子组件的标签内写入内容即可。
<-- 子组件 Child.vue -->
<template>
<slot>
<p>插槽后备的内容</p>
</slot>
</template>
<-- 父组件 -->
<Child>
<div>默认插槽</div>
</Child>
1.3.2 具名插槽
子组件用 name 属性来表示插槽的名字,没有则是默认插槽
父组件中在使用时在默认插槽的基础上加上 slot 属性,值为子组件插槽 name 属性值
<-- 子组件 Child.vue -->
<template>
<slot>插槽后备的内容</slot>
<slot name="content">插槽后备的内容</slot>
</template>
<-- 父组件 -->
<Child>
<template v-slot:default>具名插槽</template>
<!-- 具名插槽用插槽名做参数 -->
<template v-slot:content>内容...</template>
</Child>
1.3.3 作用域插槽
子组件在作用域上绑定属性来将子组件的信息传给父组件使用,这些属性会被挂在父组件 v-slot 接受的对象上。
父组件中在使用时通过 v-slot:(简写:#)获取子组件的信息,在内容中使用。
<-- 子组件 Child.vue -->
<template>
<slot name="footer" testProps="子组件的值">
<h3>没传footer插槽</h3>
</slot>
</template>
<-- 父组件 -->
<Child>
<!-- 把v-slot的值指定为作用域上下文对象 -->
<template v-slot:default="slotProps">
来自子组件数据:{{ slotProps.testProps }}
</template>
<template #default="slotProps">
来自子组件数据:{{ slotProps.testProps }}
</template>
</Child>
1.4 小结
v-slot 属性只能在 < template > 上使用,但在只有默认插槽时可以在组件标签上使用 |
默认插槽名为 default ,可以省略 default 直接写 v-slot |
缩写为 # 时不能不写参数,写成 #default |
可以通过解构获取 v-slot={user},还可以重命名 v-slot="{user:newName}" 和定义默认值 v-slot="{user= '默认值'}" |
2. key的原理以及对key的理解
2.1 什么是key?
key 是给每一个 vnode 的唯一 id,也是 diff 的一种优化策略,可以根据 key,更准确、更快的找到对应的 vnode 节点。
当我们在使用 v-for 时,需要给单元加上 key
如果不用 key,Vue 会采用就地复地原则:最小化 element 的移动,并且会尝试尽最大程度在同适当的地方对相同类型的 element ,做 patch 或者 reuse。
如果使用了 key,Vue 会根据 keys 的顺序记录 element,曾经拥有了 key 的 element 如果不再出现的话,会被直接 remove 或者 destoryed
用+new Date()生成的时间戳作为 key,手动强制触发重新渲染
当拥有新值的 rerender 作为 key 时,拥有了新 key 的 Comp 出现了,那么旧 key Comp 会被移除,新 key Comp 触发渲染。
3. Vue常用的修饰符
3.1 什么是修饰符?
修饰符 是用于限定类型以及类型成员的声明的一种符号。
在 Vue 中,修饰符处理了许多 DOM 事件的细节,让我们不再需要花大量的时间去处理这些烦恼的事情,而能有更多的精力专注于程序的逻辑处理。
3.2 修饰符
3.2.1 表单修饰符(lazy、trim 和 number)
3.2.1.1 lazy
在我们填完信息,光标离开标签的时候,才会将值赋予给 value,也就是在 change 事件之后再进行信息同步。
<input type="text" v-model.lazy="value">
<p>{{value}}</p>
3.2.1.2 trim
自动过滤用户输入的首空格字符,而中间的空格不会过滤
<input type="text" v-model.trim="value">
3.2.1.3 number
自动将用户的输入值转为数值类型,但如果这个值无法被 parseFloat 解析,则会返回原来的值。
<input v-model.number="age" type="number">
3.2.2 事件修饰符
事件修饰符是对事件捕获以及目标进行了处理。
3.2.2.1 stop
阻止了事件冒泡,相当于调用了 event.stopPropagation 方法
<div @click="shout(2)">
<button @click.stop="shout(1)">ok</button>
</div>
//只输出1
3.2.2.2 prevent
阻止了事件的默认行为,相当于调用了 event.preventDefault 方法
<form v-on:submit.prevent="onSubmit"></form>
3.2.2.3 self
只当再 event.target 是当前元素自身时触发处理函数
<div v-on:click.self="doThat">...</div>
使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用
v-on:click.prevent.self
会阻止所有的点击,而v-on:click.self.prevent
只会阻止对元素自身的点击
3.2.2.4 once
绑定了事件以后只能触发一次,第二次就不会触发
<button @click.once="shout(1)">ok</button>
3.2.2.5 capture
使事件触发从包含这个元素的顶层开始往下触发
<div @click.capture="shout(1)">
obj1
<div @click.capture="shout(2)">
obj2
<div @click="shout(3)">
obj3
<div @click="shout(4)">
obj4
</div>
</div>
</div>
</div>
// 输出结构: 1 2 4 3
3.2.2.6 passive
在移动端,当我们在监听元素滚动事件的时候,会一直触发onscroll
事件会让我们的网页变卡,因此我们使用这个修饰符的时候,相当于给onscroll
事件整了一个.lazy
修饰符
<!-- 滚动事件的默认行为 (即滚动行为) 将会立即触发 -->
<!-- 而不会等待 `onScroll` 完成 -->
<!-- 这其中包含 `event.preventDefault()` 的情况 -->
<div v-on:scroll.passive="onScroll">...</div>
不要把
.passive
和.prevent
一起使用,因为.prevent
将会被忽略,同时浏览器可能会向你展示一个警告。
passive
会告诉浏览器你不想阻止事件的默认行为
3.2.2.7 native
让组件变成像html
内置标签那样监听根元素的原生事件,否则组件上使用 v-on
只会监听自定义事件
<my-component v-on:click.native="doSomething"></my-component>
3.2.3 鼠标按钮修饰符
鼠标按钮修饰符针对的就是左键、右键、中键点击,有如下:
- left 左键点击
- right 右键点击
- middle 中键点击
<button @click.left="shout(1)">ok</button>
<button @click.right="shout(1)">ok</button>
<button @click.middle="shout(1)">ok</button>
3.2.4 键盘修饰符
键盘修饰符是用来修饰键盘事件(onkeyup
,onkeydown
)的,有如下:
keyCode
存在很多,但vue
为我们提供了别名,分为以下两种:
- 普通键(enter、tab、delete、space、esc、up...)
- 系统修饰键(ctrl、alt、meta、shift...)
// 只有按键为keyCode的时候才触发
<input type="text" @keyup.keyCode="shout()">
// 还可以通过以下方式自定义一些全局的键盘码别名
Vue.config.keyCodes.f2 = 113
3.2.5 v-bind 修饰符
3.2.5.1 async
能对props
进行一个双向绑定
//父组件
<comp :myMessage.sync="bar"></comp>
//子组件
this.$emit('update:myMessage',params);
// 上面为简写
//父亲组件
<comp :myMessage="bar" @update:myMessage="func"></comp>
func(e){
this.bar = e;
}
//子组件js
func2(){
this.$emit('update:myMessage',params);
}
使用async
需要注意以下两点:
-
使用
sync
的时候,子组件传递的事件名格式必须为update:value
,其中value
必须与子组件中props
中声明的名称完全一致 -
注意带有
.sync
修饰符的v-bind
不能和表达式一起使用 -
将
v-bind.sync
用在一个字面量的对象上,例如v-bind.sync=”{ title: doc.title }”
,是无法正常工作的
3.2.5.2 props
设置自定义标签属性,避免暴露数据,防止污染HTML结构
<input id="uid" title="title1" value="1" :index.prop="index">
3.2.5.3 camel
将命名变为驼峰命名法,如将view-Box
属性名转换为 viewBox
<svg :viewBox="viewBox"></svg>
3.3 应用场景
根据每一个修饰符的功能,我们可以得到以下修饰符的应用场景:
- .stop:阻止事件冒泡
- .native:绑定原生事件
- .once:事件只执行一次
- .self :将事件绑定在自身身上,相当于阻止事件冒泡
- .prevent:阻止默认事件
- .caption:用于事件捕获
- .once:只触发一次
- .keyCode:监听特定键盘按下
- .right:右键