插槽
具名插槽
- 具名插槽顾名思义就是给插槽起一个名字,
<slot> 元素有一个特殊的 attribute:name ; - 一个不带 name 的slot,会带有隐含的名字
default 举个栗子: <slot name="left"></slot> <template v-slot:left><button>左边</button></template>
跟 v-on 和 v-bind 一样,v-slot 也有缩写; 即把参数之前的所有内容 (v-slot: ) 替换为字符 # <template #left><button>左边</button></template>
动态插槽名
可以通过 v-slot:[dynamicSlotName] 方式动态绑定一个名称 举个栗子:
<template v-slot:[name]>
<button>左边</button>
</template>
...
data(){
return{
name:"left"
}
}
作用域插槽
当一个组件被用来渲染一个数组元素时,我们使用插槽,并且希望插槽中没有显示每项的内容,Vue给我们提供了作用域插槽。 案例: 子组件ShowNames.vue
<template>
<div>
<template v-for="(item, index) in names" :keys="item">
<slot :item="item" :index="index"></slot>
</template>
</div>
</template>
<script>
export default {
props: {
names: {
type: Array,
default: () => [],
},
},
};
</script>
<style scoped>
</style>
App.vue
<template>
<div>
<show-names :names="names">
<template #default="slotProps">
<button>{{slotProps.item}}-{{slotProps.index}}</button>
</template>
</show-names>
</div>
</template>
<script>
import ShowNames from './ShowNames.vue'
export default {
components:{
ShowNames,
},
data(){
return{
names:["why","kobe","james","curry"]
}
}
}
</script>
<style scoped>
</style>
动态组件的实现
<components :is="currentTab"></components>
keep-alive
组件状态保存
<keep-alive include="home,about"></keep-alive>
<components :is="currentTab"></components>
</keep-alive>
keep-alive有一些属性:
- include - string | RegExp | Array。只有名称匹配的组件会被缓存;
- 使用逗号分隔字符串
- 正则表达式使用v-bind绑定属性
<keep-alive :include="/a|b/"> - 数组也是用v-bind绑定属性
<keep-alive :include="['a','b']"> - exclude - string | RegExp | Array。任何名称匹配的组件都不会被缓存;
- max - number | string。最多可以缓存多少组件实例,一旦达到这个数字,那么缓存组件中最近没有被访问的实例会被销毁;
- include 和 exclude prop 允许组件有条件地缓存:
- 二者都可以用逗号分隔字符串、正则表达式或一个数组来表示;
- 匹配首先检查组件自身的 name 选项
缓存组件的生命周期
- 对于缓存的组件来说,再次进入时,我们是不会执行
created 或者mounted 等生命周期函数 的
- 但是有时候我们确实希望监听到何时重新进入到了组件,何时离开了组件;
- 这个时候我们可以使用
activated 和 deactivated 这两个生命周期钩子函数 来监听
webpack的分包
默认的打包过程:
- 默认情况下,在构建整个组件树的过程中,因为组件和组件之间是通过模块化直接依赖的,那么webpack在打包时就会将组件模块打包到一起(比如一个app.js文件中);
- 这个时候随着项目的不断庞大,app.js文件的内容过大,会造成首屏的渲染速度变慢
通过import函数 导入的模块,后续webpack对其进行打包的时候会进行分包的操作,相当于拆分成一些小的代码块chunk.js
import("./utils/math").then((res)=>{
console.log(res.sum(20,30))
//此时math里面的函数都可以通过res.获取
})
异步组件的实现
如果我们的项目过大了,对于某些组件我们希望通过异步的方式来进行加载(目的是可以对其进行分包处理),Vue3提供了一个函数:defineAsyncComponent defineAsyncComponent接受两种类型的参数:
- 类型一:工厂函数,该工厂函数需要返回一个Promise对象;
import {defineAsyncComponent} from 'vue'
const AsyncComponent = defineAsyncComponent(()=>import("./AsyncComponent.vue"))
export default{
components:{
AsyncComponent
}
}
const AsyncComponent = defineAsyncComponent({
loader : () => import("./AsyncComponent"), // 工厂函数
loadingComponent: Loading, // 加载过程中显示的组件
errorComponent: Error, // 加载失败显示的组件
delay: 2000, // 在线显示loadingComponent之前的延迟(单位ms)
suspensible: true // 定义组件是否可挂起
})
异步组件就是为了实现代码的分包!
suspense
- Suspense是一个内置的全局组件,该组件有两个插槽:
- default:如果default可以显示,那么显示default的内容;
- fallback:如果default无法显示,那么会显示fallback插槽的内容;
<suspense>
<template #default>
<async-home></async-home>
</template>
<template #fallback>
<Loading></Loading>
</template>
</suspense>
$
$refs
直接获取到元素对象或者子组件实例
// 绑定到元素上
<h2 ref="title">hahahaa</h2>
// 绑定到组件实例上
<nav-bar ref="navBar"></nav-bar>
<button @click="btnClick">获取元素</button>
methods:{
btnClick(){
console.log(this.$refs.title);
//就相当于组件实例,只是做了一层proxy代理
console.log(this.$refs.navBar.message) ;
this.$refs.navBar.showMessage();
}
}
$parent
可以通过$parent来访问父元素 在Vue3中已经移除了$children的属性,所以不可以使用了
$root
可以通过$root来访问根元素
生命周期
生命周期:每个组件都可能会经历从创建、挂载、更新、卸载等一系列的过程 生命周期函数是一些钩子函数,在某个时间会被Vue源码内部进行回调
v-model
<input v-model="message"> 相当于 <input :value="message" @input="message=$event.target.value">
组件的v-model <hy-input v-model="message"></hy-input> 相当于 <hy-input :modelValue="message" @update:model-value="message=$event"></hy-input>
一个组件可以加多个v-model实现数据双向绑定
Mixin
合并规则
- 情况一:如果是data函数的返回值对象
- 返回值对象默认情况下会进行合并;
- 如果data返回值对象的属性发生了冲突,那么会保留组件自身的数据;
- 情况二:如何生命周期钩子函数
- 情况三:值为对象的选项,例如 methods、components 和 directives,将被合并为同一个对象。
- 比如都有methods选项,并且都定义了方法,那么它们都会生效;
- 但是如果对象的key相同,那么会取组件对象的键值对
全局混入
- 全局的Mixin可以使用 应用app的方法 mixin 来完成注册;
- 一旦注册,那么全局混入的选项将会影响每一个组件;
//main.js
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App);
app.mixin({
data() {
return {
}
},
methods: {
},
created(){
}
})
app.mount('#app');
|