1.自定义指令
之前我们学习了各种指令:v-model、v-for、v-show等,除了这些指令外,Vue允许我们自定义指令。
什么时候使用自定义指令? 需要对DOM元素进行底层操作,这个时候就会用到自定义指令 。
注意:在Vue中,代码的复用和抽象主要还是通过组件。
自定义指令分为两种: 自定义局部指令:组件中通过directives选项 ,只能在当前组件中使用。 自定义全局指令:app的directive方法 ,可以在任意组件中使用。
案例:某个元素挂载完成后自动获取焦点。 (1)默认实现,不使用自定义指令.
<template>
<div>
<input type="text" ref="input">
</div>
</template>
<script>
import {
ref,
onMounted
} from "vue";
export default {
setup() {
const input = ref(null)
onMounted(() => {
input.value.focus();
})
return {
input
}
}
}
</script>
(2)定义局部指令
<input type="text" v-focus>
export default {
// 局部指令
directives:{
focus:{
mounted(el){
el.focus()
}
}
}
}
(3)定义全局指令 在main.js中定义
const app = createApp(App)
// 定义全局指令
app.directive("focus", {
mounted(el) {
el.focus()
}
})
app.mount('#app')
2.指令的生命周期
<template>
<div>
<button v-if="counter<2" @click="increment" v-phoebe>当前计数{{counter}}</button>
</div>
</template>
<script>
import { ref } from "vue"
export default {
setup(){
const counter =ref(0)
const increment = ()=>counter.value++
return {
counter,
increment
}
},
directives:{
phoebe:{
created(){
console.log("phoebe created")
},
beforeMount(){
console.log("phoebe beforeMount")
},
mounted(){
console.log("phoebe mounted")
},
beforeUpdate(){
console.log("phoebe beforeUpdate")
},
updated(){
console.log("phoebe updated")
},
beforeUnmount(){
console.log("phoebe beforeUnmounted")
},
unmounted(){
console.log("phoebe unmounted")
},
}
}
}
</script>
<style>
</style>
时间戳格式化案例 App.vue
<template>
<div>
<!-- 可以传进参数,设置时间的格式 -->
<h2 v-format-time="'YYYY/MM/DD'">{{timestamp}}</h2>
</div>
</template>
<script>
export default {
setup(){
const timestamp = 1669456723
return {
timestamp
}
}
}
</script>
将自定义指令提取出来 format-time.js文件:
// 引入第三方库dayjs
import dayjs from "dayjs"
export default function(app){
app.directive("format-time",{
mounted(el,bindings){
// 获取app.vue传入参数时间的格式
let formatString = bindings.value
// 如果没有传入使用默认格式
if(!formatString){
formatString = "YYYY-MM-DD HH-mm-ss"
}
const textContent =el.textContent
// console.log(typeof textContent) //字符串类型
// 转换数据类型
let timestamp = parseInt(textContent)
//如果时间戳是10为,代表为秒钟;统一单位
if(textContent.length === 10){
timestamp = timestamp * 1000
}
el.textContent = dayjs(timestamp).format(formatString);
// 使用第三方库 dayjs ;npm install dayjs
}
})
}
index.js
import registerFormatTime from "./format-time.js"
export default function registerDirectives(app) {
registerFormatTime(app);
}
在main.js中使用即可,(定义的全局指令)
import registerDirectives from './directives'
const app = createApp(App)
registerDirectives(app);
3.认识Teleport
组件化开发中,我们封装一个组件A,在另一个组件B中使用;那么组件A中的template元素会被挂载到组件B中的template的某个位置,最终应用程序会形成一棵DOM树结构.
某些情况下不希望挂载到这个组件树上,可以移动到Vue app之外的其他位置.通过teleport来完成.
Teleport是Vue提供的内置组件 ,翻译后有远程传输的意思.
有两个属性: to: 指定将其中的内容移动到的目标元素,可以使用选择器; disabled :是否禁用teleport的功能.
在index.html中添加一个div:
<template>
<div>
<teleport to="#phoebe">
<h2>Hello teleport</h2>
</teleport>
</div>
</template>
还可以移动组件
<template>
<div>
<teleport to="#phoebe">
<h2>Hello teleport</h2>
<hello-world></hello-world>
</teleport>
</div>
</template>
<script>
import HelloWorld from "./HelloWorld.vue"
export default{
components:{
HelloWorld
}
}
</script>
4.认识Vue插件
向Vue全局添加一些功能时,会采用Vue的插件模式.
两种编写方式: 对象类型 : 一个对象,但是必须要包含一个install的函数 ,该函数会在安装插件时执行; 函数类型 : 一个function ,这个函数会在安装插件时自动执行.
插件可以完成的功能没有限制,以下几种都可以:
- 添加全局方法或者property(属性),通过把他们添加到config.globalproperties上实现.
- 添加全局资源 :指令/过滤器/过渡等;
- 通过全局 mixin来添加一些组件选项;
- 一个库,提供自己的API,同时提供上面提到的一个或多个功能.
//创建一个vue插件 对象方式object
export default{
install(app){
console.log(app)
}
}
或者是用函数的方式创建:
//一个函数的方式
export default function(app){
console.log(app)
}
在main.js中使用插件:
//引入插件
import plugin from "./plugins/plugins01.js"
const app = createApp(App)
//使用插件
app.use(plugin)
5.vue3源码三大核心系统
Compiler模块 : 编译模板系统(将template模板编译成虚拟的VNode)
Runtime模块: 也可以称之为Renderer模块,真正渲染的模块;
Reactivity模块: 响应式系统
|