在Vue3中,一些属性的调用方法会与Vue2下的有所不同,所以整理了在开发过程中实现过的功能。
el-input组件在鼠标光标位置插入内容
1.封装函数insertAfterCursor,在该函数执行时将指定字符串插入到el-input光标所在的位置。
2.获取元素会用到refs,ref是用来操作某个元素节点的,可以说是document.getElementById的语法糖,在vue2中,可以通过this.来访问到$refs,在vue3中没有this这样获取不到了,但是官网提供了其他方法,在setup()中定义const xxx=ref(null),对应元素上绑定ref="xxx",作为其ref。
3.在vue3中,ref主要有两种用法:
第一种使用方式:操作元素节点:
1.在组件上声明
<el-form ref="form"></el-form>
2.需要手动声明再使用,Vue3基本取消this的使用,也就是更多的内容为声明式使用
let form = ref();
3.然后通过form.value操作其内容
form.value.validate()
第二种使用方式:声明响应式数据
<template>
<div>
<el-input type="textarea" placeholder="请输入内容" v-model="ContentText" ref="cursorInputRef"></el-input> //挂载ref,获取文本中的位置属性
<el-button @click="insertAfterCursor">插入</el-button>
</div>
</template>
<script setup>
import { ref } from 'vue'
const ContentText = ref('')
const cursorInputRef = ref(null)
const insertAfterCursor = () => {
const input = cursorInputRef.value.$refs.textarea; //由el-input的原本元素决定是input还是textarea
const start = input.selectionStart; //光标位置,字符串开头则为0,第二个字符左面则为1,以此类推;如选中段文字则为光标范围起始位置
const end = input.selectionEnd; //选中段文字则为光标范围结束位置,否则值与selectionStart相同
const value = input.value; //文本域中输入字符串的值
const word = "123"; //要插入的内容
ContentText.value = value.slice(0, start) + word + value.slice(end); //根据光标位置将原字符串分为两个字符串,在两个字符串之间插入目标字符串,最终拼接为插入后的字符串
input.selectionStart = input.selectionEnd = start + word.length;
}
</script>
<style lang="scss">
</style>
el-popover实现下拉框与el-scrollbar滚动区域列表实现触底懒加载
1.封装函数listScroll执行判断触底条件并执行触底事件。
<template>
<el-popover placement="bottom" :width="400" trigger="click">
<template #reference>
<div class="input-body">
<span class="body-placeholder" v-if="listValue == ''"> //没数据时渲染暗文
请输入分类名称
</span>
<span class="body-content" v-if="listValue != ''"> //有数据时渲染下拉列表选中的值
<el-tag type="info" class="body-tag">{{ listValue }}</el-tag>
</span>
</div>
</template>
<el-scrollbar class="options-area" @scroll="listScroll">
<div ref="listHeight"> //通过ref获取容器高度
<div v-for=" item in listOptions " class="option-item"
@click="addOption(item, $event)"> //列表项勾选与取消选择事件
<el-checkbox class="option-item-checkbox" :model-value="listValue == item.label"></el-checkbox> //根据条件判断勾选框是否渲染为勾选状态
<span :class="listValue == item.label ? 'option-item-text-active' : 'option-item-text'">{{
item.label }}</span>
</div>
</div>
</el-scrollbar>
</el-popover>
</template>
<script setup>
import { ref } from 'vue'
const listValue = ref('') //下拉框选中的值
const listHeight = ref(null) //获取容器高度
const listOptions = ref([{ label: '选项1', value: '001' }, { label: '选项2', value: '002' }, { label: '选项3', value: '003' }, { label: '选项4', value: '004' }, { label: '选项5', value: '005' }, { label: '选项6', value: '006' }, { label: '选项7', value: '007' }, { label: '选项8', value: '008' }, { label: '选项9', value: '009' }, { label: '选项10', value: '010' }]) //第一页默认列表数据
const pageSize = ref(10) //每页数据数量
const pageNumber = ref(1) //页码
const listTotal = ref(12) //数据总数,接口返回赋值
const moreListOptions = ref([{ label: '选项11', value: '011' }, { label: '选项12', value: '012' }]) //懒加载要获取的第二页数据
const addOption = (val, e) => {
if (e.target.tagName !== 'INPUT') return //冒泡拦截,防止点击事件触发两次
if (listValue.value == val.label) { //选中值为已选中值则清空
listValue.value = ''
} else { 勾选中赋值
listValue.value = val.label
}
}
const listScroll = async () => {
const el = event.target
const scrollHeight = listHeight.value.scrollHeight
if (scrollHeight - el.scrollTop - el.clientHeight == 0) { //判定是否滚动条到底部
console.log('触底了')
if (listOptions.value.length < listTotal.value) { //当前列表数据长度还没到数据总数
console.log('符合懒加载条件')
const pageNum = pageNumber.value + 1 //传下一页的页码值
pageNumber.value = pageNumber.value + 1 //记录的页码值也同步新一页
getList(pageNum) //调接口
}
}
}
const getList = async (pageNum) => {
try {
// let req = {
// page_no: pageNum ? pageNum : 1, //查懒加载后新的页码或第一页
// page_size: pageSize.value,
// }
// let res = await xxApi.xxx(req)
// if (res.errcode === 0) {
// listOptions.value = req.page_no === 1 ? res.data.list : listOptions.value.concat(res.data.list) 如果查的页码为1,则列表直接为返回的列表值;如果不是1的话就是懒加载查新的页,查到的结果拼接现有的列表数据
// listTotal.value = res.data.total
// } else {
// ElMessage.error('【' + res.errcode + '】' + res.errmsg)
// }
listOptions.value = listOptions.value.concat(moreListOptions.value)
} catch (err) {
console.log('查询列表数据错误!', err)
}
}
</script>
<style lang="scss">
.input-body {
width: 400px;
height: 30px;
border: 1px solid #dcdee2;
border-radius: 0 3px 3px 0;
float: left;
cursor: pointer;
.body-placeholder {
height: 30px;
font-size: 12px;
line-height: 30px;
margin-left: 10px;
color: #ccc;
}
.body-content {
height: 30px;
font-size: 12px;
line-height: 30px;
.body-tag {
margin-left: 5px;
}
}
.body-icon {
float: right;
color: #ccc;
font-size: 16px;
margin: 6px 10px 0 0;
}
}
.options-area {
height: 200px !important;
padding-right: 8px;
.option-item {
cursor: pointer;
.option-item-checkbox {
margin-left: 8px;
}
.option-item-text {
margin-left: 8px;
display: inline-block;
height: 32px;
line-height: 32px;
color: #666666;
}
.option-item-text-active {
margin-left: 8px;
display: inline-block;
height: 32px;
line-height: 32px;
color: #197afb;
}
}
.option-item:hover {
background: #e8eaec;
}
}
</style>