如何封装命令式组件
# 1. 传统组件封装
在传统组件封装的时候,通常是以 vue 文件形式存在,每次使用的时候,需要导入组件,然后 template
模板中挂载,然后传参,代码会显得过多冗余
<template>
<div>
<Button @click="handle">显示提示框</Button>
<div>
<MessagesBox v-model="show" />
</div>
</div>
</template>
<script setup>
import Button from "Button"
import MessagesBox from "MessagesBox"
import {ref} from "vue"
const show = ref(false)
function handle(){
show.value = true
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 2. 命令式组件封装
命令式组件则在使用的时候,直接在 js
代码中使用,只需要以函数传参形式,即可操作,节省大量重复不必要的代码
<template>
<div>
<Button @click="handle">显示提示框</Button>
</div>
</template>
<script setup>
import Button from "Button"
import showMsg from "utils/showMsg"
const handle = () => {
showMsg('显示的内容',(close)=>{
console.log('点击了确认')
close()
})
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import MessagesBox from "/components/MessagesBox.vue" // 弹窗组件
import { createApp } from "vue" // 导入创建app函数
export default function showMsg (msg,clickHandle) {
const app = createApp(MessagesBox,{
msg,
onclick(){
clickHandle && clickHandle(()=>{
app.unmount() // 卸载app
div.remove() // 移除 div 元素
});
}
})
// 页面上创建一个 div 元素
const div = document.createElement('div')
// 挂载到这个div元素上
document.body.appendChild(div)
app.mount(div)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 3. 拓展思维
上述代码中,我们还是引入了 MessagesBox 这个 vue 单组件文件,其实我们继续简化,vue 的单模板文件的本质其实就是一个个 对象,因此可修改如下 :
import { createElementVNode } from "vue" // 导入vue的虚拟函数
const MessagesBox = {
props:{
msg:{
type:String,
required:true
}
},
render(){
// 这边后续可以使用 jsx 渲染更多样式
return createElementVNode('h1',null,this.msg)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 4. css 样式的处理
目前我们全部是在 js 文件中操作,那么应该如何写样式呢?
在 react 中有两种解决方案: css module
css in Js
目前 react 常见的是第二种解决方案,react 中常用的库就是 style Component
在 vue 中支持的话,需要安装第三方库 styils/vue
import { styled } from '@styils/vue'
const div = styled({
....样式
})
1
2
3
4
5
2
3
4
5
上次更新: 12/26/2023, 8:39:40 AM