一、巧用两次watch监听控制弹窗的显示
1.在component文件夹下创建文件夹chooseIcon,创建对应文件
2.在views下面注册组件,然后在router下面配置路由
{
path:'/chooseIcon',
component:() => import ('../views/chooseIcon/index.vue')
}
3.代码
(1)component/chooseIcon/src/index.vue
<template>
<el-button @click="handleClick" type="primary">
<slot></slot>
</el-button>
<el-dialog :title="title" v-model="dialogVisible">哇大美女</el-dialog>
</template>
<script lang="ts" setup>
import { ref, watch } from "@vue/runtime-core"
let props = defineProps<{
//弹出框的标题
title:string,
//控制弹出框的显示与隐藏
visible:boolean
}>()
let emits = defineEmits(['update:visible'])
//拷贝一份父组件传递过来的visible
let dialogVisible = ref<boolean>(props.visible)
let handleClick = ()=>{
//需要修改父组件的数据
emits('update:visible',!props.visible)
}
//监听visible的变化,只能监听第一次变化,val为变化之后的数据
watch(()=>props.visible,val =>{
dialogVisible.value=val
//emits('update:visible',val)
})
//监听组件内部dialogVisible的变化
watch(()=>dialogVisible.value,val=>{
emits('update:visible',val)
})
</script>
<style lang="scss" scoped>
</style>
这里采用了两次watch监听,来控制弹框的显示与隐藏
拷贝之后,使用dialogVisible所有监听的visible变化只有第一次与父组件有关,后面的变化都有只与自己内部的visible有关,与父组件无关
(2)views/chooseIcon/index.vue
<template>
<div>
<m-choose-icon title="选择图标" v-model:visible="visible">
选择图标
</m-choose-icon>
</div>
</template>
<script lang="ts" setup>
import { ref } from '@vue/reactivity'
import mChooseIcon from '../../components/chooseIcon/src/index.vue'
let visible = ref<boolean>(false)
</script>
<style lang="scss" scoped>
</style>
二、巧用component动态组件显示所有图标
component/chooseIcon/src/index.vue
<template>
<el-button @click="handleClick" type="primary">
<slot></slot>
</el-button>
<el-dialog :title="title" v-model="dialogVisible">
<div class="container">
<div
class="item"
v-for="(item,index) in Object.keys(ElIcons)"
:key="index"
>
<div class="text">
<component :is="`el-icon-${toLine(item)}`"></component>
</div>
<div class="icon">{{item}}</div>
</div>
</div>
</el-dialog>
</template>
<script lang="ts" setup>
import * as ElIcons from '@element-plus/icons';
import { ref, watch } from "@vue/runtime-core";
import { toLine } from '../../../utils';
let props = defineProps<{
//弹出框的标题
title:string,
//控制弹出框的显示与隐藏
visible:boolean
}>()
let emits = defineEmits(['update:visible'])
//拷贝一份父组件传递过来的visible
let dialogVisible = ref<boolean>(props.visible)
let handleClick = ()=>{
//需要修改父组件的数据
emits('update:visible',!props.visible)
}
//监听visible的变化,只能监听第一次变化,val为变化之后的数据
watch(()=>props.visible,val =>{
dialogVisible.value=val
//emits('update:visible',val)
})
//监听组件内部dialogVisible的变化
watch(()=>dialogVisible.value,val=>{
emits('update:visible',val)
})
</script>
<style lang="scss" scoped>
.container{
display: flex;
align-items: center;//垂直方向居中
flex-wrap: wrap;//换行
}
.item{
width: 25%;
height: 70px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;//水平方向居中
margin-bottom: 20px;
cursor: pointer;//使得到时候可以点进去复制
}
.text{
font-size: 14px;
}
.icon{
flex: 1;
}
svg{
width: 2em;
height: 2em;
}
</style>
*不能循环对象,所有在取图标库的使用要用
v-for="(item,index) in Object.keys(ElIcons)"
三、利用命名空间修改dialog样式
修改组件库内部样式
1.自定义一个类名空间
2.现在浏览器里面调试样式
3.把调试好的类名放在入这个类名里面
4.在App.vue里面引入这个文件
5.在组件内需要改样式的元素的父元素加上这个类名
代码
index.vue
<template>
<el-button @click="handleClick" type="primary">
<slot></slot>
</el-button>
<div class="m-choose-icon-dialog-body-height">
<el-dialog :title="title" v-model="dialogVisible">
<div class="container">
<div
class="item"
v-for="(item,index) in Object.keys(ElIcons)"
:key="index"
>
<div class="text">
<component :is="`el-icon-${toLine(item)}`"></component>
</div>
<div class="icon">{{item}}</div>
</div>
</div>
</el-dialog>
</div>
</template>
<script lang="ts" setup>
import * as ElIcons from '@element-plus/icons';
import { ref, watch } from "@vue/runtime-core";
import { toLine } from '../../../utils';
let props = defineProps<{
//弹出框的标题
title:string,
//控制弹出框的显示与隐藏
visible:boolean
}>()
let emits = defineEmits(['update:visible'])
//拷贝一份父组件传递过来的visible
let dialogVisible = ref<boolean>(props.visible)
let handleClick = ()=>{
//需要修改父组件的数据
emits('update:visible',!props.visible)
}
//监听visible的变化,只能监听第一次变化,val为变化之后的数据
watch(()=>props.visible,val =>{
dialogVisible.value=val
//emits('update:visible',val)
})
//监听组件内部dialogVisible的变化
watch(()=>dialogVisible.value,val=>{
emits('update:visible',val)
})
</script>
<style lang="scss" scoped>
.container{
display: flex;
align-items: center;//垂直方向居中
flex-wrap: wrap;//换行
}
.item{
width: 25%;
height: 70px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;//水平方向居中
margin-bottom: 20px;
cursor: pointer;//使得到时候可以点进去复制
}
.text{
font-size: 14px;
}
.icon{
flex: 1;
}
svg{
width: 2em;
height: 2em;
}
</style>
styles/ui.scss
.m-choose-icon-dialog-body-height{
.el-dialog__body{
height: 500px;
overflow: scroll;
}
}
App.vue
<template>
<router-view></router-view>
</template>
<style>
@import './styles/base.scss';
@import './styles/ui.scss';
</style>
(1)这里记得,一些基本的样式我们都可以将它们封装到styles文件夹下面的一个文件下,然后进行引入
(2)我在这里把之前的App.vue中的基本样式封装到了styles下面的base.scss
*{
margin: 0;
padding: 0;
}
html,body,#app,.el-container,.el-menu{
height: 100%;
}
svg{
width: 1em;
height: 1em;
}
四、通过自定义hooks函数实现复制功能
1.创建hooks文件夹,在下面的文件中定义useCopy函数
hooks/useCopy/useCopy.ts
import { ElMessage } from "element-plus"
//复制文本
export const useCopy = (text:string)=>{
//1.创建一个input框
let input = document.createElement('input')
//2.给输入框value赋值
input.value=text
//3.追加到body里面去
document.body.appendChild(input)
//4.选择输入框的操作
input.select()
//5.执行复制操作
document.execCommand('Copy')
//删除加入的输入框
document.body.removeChild(input)
//提示用户
ElMessage.success('复制成功')
}
component/chooseIcon/src/index.vue
<template>
<el-button @click="handleClick" type="primary">
<slot></slot>
</el-button>
<div class="m-choose-icon-dialog-body-height">
<el-dialog :title="title" v-model="dialogVisible">
<div class="container">
<div
class="item"
v-for="(item,index) in Object.keys(ElIcons)"
:key="index"
@click="()=>clickItem(item)"
>
<div class="text">
<component :is="`el-icon-${toLine(item)}`"></component>
</div>
<div class="icon">{{item}}</div>
</div>
</div>
</el-dialog>
</div>
</template>
<script lang="ts" setup>
import * as ElIcons from '@element-plus/icons';
import { ref, watch } from "@vue/runtime-core";
import { toLine } from '../../../utils';
import { useCopy } from '../../../hooks/useCopy/useCopy'
let props = defineProps<{
//弹出框的标题
title:string,
//控制弹出框的显示与隐藏
visible:boolean
}>()
let emits = defineEmits(['update:visible'])
//拷贝一份父组件传递过来的visible
let dialogVisible = ref<boolean>(props.visible)
//点击按钮显示弹出框
let handleClick = ()=>{
//需要修改父组件的数据
emits('update:visible',!props.visible)
}
//监听visible的变化,只能监听第一次变化,val为变化之后的数据
watch(()=>props.visible,val =>{
dialogVisible.value=val
//emits('update:visible',val)
})
//监听组件内部dialogVisible的变化
watch(()=>dialogVisible.value,val=>{
emits('update:visible',val)
})
//点击图标
let clickItem = (item:string) =>{
let text = `<el-icon-${toLine(item)} />`
//复制文本
useCopy(text)
//关闭弹框
dialogVisible.value=false
}
</script>
<style lang="scss" scoped>
.container{
display: flex;
align-items: center;//垂直方向居中
flex-wrap: wrap;//换行
}
.item{
width: 25%;
height: 70px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;//水平方向居中
margin-bottom: 20px;
cursor: pointer;//使得到时候可以点进去复制
}
.text{
font-size: 14px;
}
.icon{
flex: 1;
}
svg{
width: 2em;
height: 2em;
}
</style>
四运行出来的界面
图标选择器.png
图标选择.png
图标复制.png
***点击选择图标才会弹出来选择框,点击选择框右上角的叉叉或者其他地方都可隐藏选择框,点击图标会进行复制,然后弹框会隐藏