# vue的一些高级特性
# 自定义v-mdoel
其实本质上,v-model是v-bind以及v-on配合使用的语法糖:
<input v-model="value" />
// 就是相当于:
<input :value="value" @input="value= $event.target.value" />
# model
允许一个自定义组件在使用 v-model 时定制 prop 和 event。默认情况下,一个组件上的 v-model 会把 value 用作 prop 且把 input 用作 event,但是一些输入类型比如单选框和复选框按钮可能想使用 value prop 来达到不同的目的。使用 model 选项可以回避这些情况产生的冲突。
结合第一点的代码概括起来是个什么意思呢?就是说,本来默认是这样的:
子接收到的prop值 = value
监听子组件触发的事件名event = input 我们要在自定义组件上用啊,老是用默认的那岂不是限制了我的发挥?于是,vue在2.2.0版本中新增了一个model选项,可以让我们这样:
子接收到的prop值 = "想什么值就什么值"
监听子组件触发的事件名event = "想什么事件名就什么事件名"
// 父组件
<Child v-model='iptValue'></Child>
// 子组件
Vue.components('Child',{
model: {
prop: 'ipt',
evnet: change
}
props: {
ipt: Number
}
template: `<input type='number' :value='ipt' @change='$emit("change",parseInt($event.target.value))'>`
})
# $nextTick
# slot
# vue动态组件
动态组件是使用 component 组件,通过一个特殊的attribute is 来实现
在不同组件之间进行动态切换是非常有用的,①tab栏切换②在一个多标签的界面里[一个广告,五秒后消失,同一个地方,有一个实用的功能出现]
<!-- 组件会在 `currentTabComponent` 改变时改变 -->
<component v-bind:is="currentTabComponent"></component>
在上述示例中,currentTabComponent 可以包括
- 已注册组件的名字,或
- 一个组件的选项对象
<template>
<div>
<component :is="k1"></component>
</div>
</template>
<script>
import mo from './module.vue'
import m1 from "./Display.vue"
export default{
data(){
return {
k1:"mo"
}
},
mounted(){
setTimeout(()=>{
this.k1="m1"
},5000)
//5秒后子组件变成了m1
},
components:{
mo,m1
}
}
</script>
# vue异步组件
- 默认的打包过程:
- 默认情况下,在构建整个组件树的过程中,因为组件和组件之间是通过模块化直接依赖的,那么webpack在打包时就会将组件模块打包到一起(比如一个app.js文件中);
- 这个时候随着项目的不断庞大,app.js文件的内容过大,会造成首屏的渲染速度变慢;
- 打包时,代码的分包:
- 所以,对于一些不需要立即使用的组件,我们可以单独对它们进行拆分,拆分成一些小的代码块chunk.js;
- 这些chunk.js会在需要时从服务器加载下来,并且运行代码,显示对应的内容;
- import()函数
- 按需加载,异步加载大组件
- 什么时候用到什么时候加载
- webpack发现是动态import引入的内容会单独分包处理
<!--当需要的时候让x为true-->
<B v-if="x"/>
import A from "a.vue"//这是同步加载
compontnets:{
A,
B:()=>import("./b.vue")
}
# 异步组件
- 方法一:使用import,组件导入:( 实际应用子组件的mounted内容会在没点击到第二个组件就打印出来了? )
<template>
<div class="tenantinfo">
<el-tabs v-model="activeName" type="card" @tab-click="handleClick">
<el-tab-pane label="基本信息" name="first">
1
</el-tab-pane>
<el-tab-pane label="用户管理" name="second">
<tenantbasic/>
</el-tab-pane>
<el-tab-pane label="查看权限" name="third">
3
</el-tab-pane>
</el-tabs>
</div>
</template>
<script>
const One =()=>import("@/views/platform/components/tenantbasic.vue")
export default {
data() {
return {
activeName: 'first'
};
},
components:{
tenantbasic:One
},
}
</script>
方法二:使用require,借助vue内置组件component(动态组件的写法)
<component :is="yhgl" ></component> //is绑定的就是动态组件的名称
<template>
<div class="tenantinfo">
<el-tabs v-model="activeName" type="card" @tab-click="handleClick">
<el-tab-pane label="基本信息" name="first">
1
</el-tab-pane>
<el-tab-pane label="用户管理" name="second">
<component :is="yhgl" ></component>
</el-tab-pane>
<el-tab-pane label="查看权限" name="third">
3
</el-tab-pane>
</el-tabs>
</div>
</template>
<script>
const tenantbasic = resolve => require(['@/views/platform/components/tenantbasic.vue'], resolve)
export default {
data() {
return {
activeName: 'first'
};
},
methods: {
handleClick (tab, event) {
this.checkVue(tab.name)
},
checkVue (name) {
console.log(name)
switch (name) {
case 'second' :
this.yhgl = tenantbasic
break
case 'third' :
this.lszhzVue = lszhzCont
break;
default:
break;
}
}
}}
</script>
# Vue3异步组件 Vue.defineAsyncComponent
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>lesson 21</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
// 动态组件: 根据数据的变化,结合 compoent 这个标签,来随时动态切换组件的现实
// 异步组件: 是异步执行某些组件的逻辑,这叫做异步组件
const app = Vue.createApp({
template: `
<div>
<common-item />
<async-common-item />
</div>
`
});
app.component('common-item', {
template: `<div>hello world</div>`
});
app.component('async-common-item', Vue.defineAsyncComponent(() => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({
template: `<div>this is an async component</div>`
})
}, 4000)
})
}))
const vm = app.mount('#root');
</script>
</html>
Vue3中给我们提供了一个函数:defineAsyncComponent。defineAsyncComponent接受两种类型的参数:
- 类型一:工厂函数,该工厂函数需要返回一个Promise对象;
- 类型二:接受一个对象类型,对异步函数进行配置;
import { defineAsyncComponent } from 'vue';
const AsyncCategory = defineAsyncComponent(() => import("./AsyncCategory.vue"))
export default {
components: {
AsyncCategory,
}
}
import { defineAsyncComponent } from 'vue';
import Loading from './Loading.vue';
const AsyncCategory = defineAsyncComponent({
loader: () => import("./AsyncCategory.vue"),
loadingComponent: Loading,
// errorComponent,
// 在显示loadingComponent组件之前, 等待多长时间
delay: 2000,
/**
* err: 错误信息,
* retry: 函数, 调用retry尝试重新加载
* attempts: 记录尝试的次数
*/
onError: function(err, retry, fail,attempts) {
}
})
export default {
components: {
AsyncCategory,
Loading
}
}
# 异步组件结合Suspense
<template>
<div>
App组件
<home></home>
<suspense>
<template #default>
<async-category></async-category>
</template>
<template #fallback>
<loading></loading>
</template>
</suspense>
</div>
</template>
<script>
import { defineAsyncComponent } from 'vue';
import Loading from './Loading.vue';
const AsyncCategory = defineAsyncComponent(() => import("./AsyncCategory.vue"))
export default {
components: {
AsyncCategory,
Loading
}
}
</script>
# keep-alive
# mixin
抽离公共逻辑或者功能,使用mixin会是变量来源不明确,不利于阅读 mixin
← vueuse() vue虚拟列表优化性能 →