【前端开发】前端小白必会开发小技巧

编程入门 行业动态 更新时间:2024-10-09 06:21:49

【前端开发】前端小白必会开发<a href=https://www.elefans.com/category/jswz/34/1769317.html style=小技巧"/>

【前端开发】前端小白必会开发小技巧

目录

  • 1.实现一个可切换状态的按钮
    • 要求效果:
    • 代码(Javascript)
    • 效果二:
    • 代码(Javascript)
    • 代码(利用render渲染)
  • 2.代码中更改文字
    • 代码(Javascript)
  • 3.css常用样式
    • 代码(Javascript)
  • 4.如何监听多组件中的参数
    • 代码(Javascript)
  • 5.如何固定页面的按钮
    • 要求效果:
    • 代码(Javascript)
  • 6.【教考平台】表单验证配置记录
    • 代码(Javascript)
  • 7.传参处理
    • 代码(Javascript)
  • 8.子组件值变化触发父-父组件
    • 代码(Javascript)
  • 9.对象、数组的深拷贝
    • 代码(Javascript)
  • 10.遍历筛选对象对应属性的技巧
    • 代码(Javascript)
  • 11.watch监听深层数组出现视图不更新的情况
    • 代码(Javascript)
  • 12.对象object那些事
      • 1.Object.keys()以及Object.getOwnPropertyNames()
  • 13.对象数组去重(拿来主义)
      • 1.使用filter和Map
      • 2.使用reduce
      • 3.使用filter和Map
  • 14.iview表格之render函数
      • 1.渲染提示图标ToolTip
        • 要求效果:
      • 代码:
      • 2.表头渲染提示图标ToolTip(renderHeader)
        • 要求效果:
      • 代码:
  • 15.非表格多选
        • 要求效果:
      • 代码:
  • 16.自由调整iview对话框尺寸
        • 要求效果:
      • 代码:
  • 17.剪切板使用记录
      • 代码:
  • 16.利用ChatGpt输出的符合vue3+ts规范的防抖函数
        • 要求效果:
      • 代码:
    • 后续

1.实现一个可切换状态的按钮

需求:

  • 根据后台传的状态字段(0-1)切换展示颜色。

要求效果:

  • 如图,要求解决状态字段0:未解决;1:已解决。分别展示不同的颜色效果。

代码(Javascript)

      <templateslot="status"slot-scope="{ row }"><span :class="{green: row.status === 0 ,grey: row.status === 1  }">{{row.status === 0 ? '未解决' : '已解决' }}</span></template><style>
.green {display: inline-block;background: rgba(0, 204, 135, 0.1);border-radius: 3px;border: 1px solid rgba(0, 204, 135, 0.2);color: #00cc87;padding: 2px 6px;font-size: 12px;
}.grey {display: inline-block;background: #f5f9ff;border-radius: 3px;border: 1px solid rgba(122, 133, 155, 0.2);color: #3e5071;padding: 2px 6px;font-size: 12px;
}
</style>

效果二:

代码(Javascript)

                <template slot-scope="{ row }" slot="status"><span :class="statusMap[row.status].theme">{{statusMap[row.status].name}}</span></template>//-----------------------------------------------------------------export const statusMap: any = {waitAudit: { name: '待审核', theme: 'waitAudit' },repulse: { name: '审核驳回', theme: 'repulse' },auditPass: { name: '授权成功', theme: 'auditPass' },auditFail: { name: '授权失败', theme: 'auditFail' },auditing: { name: '授权中', theme: 'auditing' }
};<style>.waitAudit {display: inline-block;background: rgba(253, 215, 0, 0.103);border-radius: 10px;border: 1px solid rgba(253, 215, 0, 0.932);color: rgba(253, 215, 0, 0.932);padding: 2px 6px;font-size: 12px;}.repulse {display: inline-block;background: rgba(253, 0, 0, 0.132);border-radius: 10px;border: 1px solid rgba(253, 0, 0, 0.932);color: rgba(253, 0, 0, 0.932);padding: 2px 6px;font-size: 12px;}.auditFail {display: inline-block;background: rgba(253, 0, 0, 0.132);border-radius: 10px;border: 1px solid rgba(253, 0, 0, 0.932);color: rgba(253, 0, 0, 0.932);padding: 2px 6px;font-size: 12px;}.auditPass {display: inline-block;background: rgba(135, 253, 0, 0.132);border-radius: 10px;border: 1px solid rgba(135, 253, 0, 0.932);color: rgba(135, 253, 0, 0.932);padding: 2px 6px;font-size: 12px;}.auditing {display: inline-block;background: rgba(0, 160, 253, 0.132);border-radius: 10px;border: 1px solid rgba(0, 160, 253, 0.932);color: rgba(0, 160, 253, 0.932);padding: 2px 6px;font-size: 12px;}
</style>

代码(利用render渲染)

export const statusMap: any = {waitAudit: { name: '待审核', theme: 'waitAudit', background: 'rgba(253, 215, 0, 0.103)', color:'rgba(253, 215, 0, 0.932)'},repulse: { name: '审核驳回', theme: 'repulse', background: 'rgba(253, 0, 0, 0.132)', color:'rgba(253, 0, 0, 0.932)' },auditPass: { name: '授权成功', theme: 'auditPass', background: 'rgba(253, 0, 0, 0.132)', color:'rgba(253, 0, 0, 0.932)' },auditFail: { name: '授权失败', theme: 'auditFail', background: 'rgba(135, 253, 0, 0.132)', color:'rgba(135, 253, 0, 0.932)' },auditing: { name: '授权中', theme: 'auditing', background: 'rgba(0, 160, 253, 0.132)', color:'rgba(0, 160, 253, 0.932)' }
};//-----------------------------------------------------------------{title: '状态',slot: 'status',fixed: 'right',width: 120,align: 'center',render: (h, params) => {const row: any = params.row;if (row.status) {return h('span', {style: {display: 'inline-block',background: this.statusMap[row.status].background,color: this.statusMap[row.status].color,'border-radius': '10px',border: `1px solid ${this.statusMap[row.status].color}`,padding: '2px 6px','font-size': '12px'}}, this.statusMap[row.status].name)}}},

2.代码中更改文字

代码(Javascript)

<Input type="text" v-model="name" :placeholder="`请输入${typeMap[label]}名称`" search /><script>@Prop({ default: 'st' })private label: string;// 标签名称映射typeMap: Record<string, any> = {st: '试题',sj: '试卷',klb: '课例包'}</script>

3.css常用样式

代码(Javascript)

  • css变光标小手
<style>
cursor: pointer;
</style>
  • 文本过长省略,并悬浮显示完整内容
<Tooltip class="notice-topic" placement="bottom"><span>{{ item.topic }}</span><div slot="content"><span class="topic-content">{{ item.topic }}</span></div></Tooltip>
<style>
.notice-item {.notice-topic {overflow: hidden;width: 182px;text-overflow: ellipsis; // 省略部分显示为省略号white-space: nowrap; //不换行}.topic-content {white-space: normal;}}
</style>

4.如何监听多组件中的参数

代码(Javascript)

  @Prop({ default: () => ({}) })resource: any;@Watch('resource', {deep: true,immediate: true})public getSelect(val){console.log(val);debugger;}

5.如何固定页面的按钮

需求:

  • 页面上的按钮正常情况下随页面滚动,当会被遮挡时,将其固定在页面右上角。

要求效果:


代码(Javascript)

        <div class="header-tool"><div :class="{ 'right-btns': isActive, 'right-Fixed': isFixed }" v-if="activeTab === 'waitAudit'"><Button style="margin-right: 8px;" @click="batchAudit('repulse')":disabled="currentSelection.length < 1">批量审核打回</Button></div></div>
<script>
//按钮是否固定
//不固定按钮时的样式
isActive:boolean = true;
//固定按钮时的样式
isFixed:boolean = false;//控制右上角按钮始终显示public handleScroll() {//1.先获取到dom元素(3种方法)ts中要加类型断言不然会报错:<HTMLElement>let childDom = <HTMLElement>document.querySelector('.header-tool');//2. let childDom1 = document.getElementsByClassName('right-btns');//3. let childDom = <HTMLElement>this.$refs.rightBtns;//2.getBoundingClientRect获取到元素位置    let topVal = childDom.getBoundingClientRect().top;console.log(topVal)//3.监听到距离顶端距离<100时,切换class样式if (topVal < 100) {this.isActive = false;this.isFixed = true;// childDom.style.position = 'fixed';// childDom.style.top = '50px';// childDom.style.right = '34px';}else {this.isActive = true;this.isFixed = false;}}
</script><style>.right-btns {float: right;.info-container {margin-right: 8px;span {padding: 0 5px;font-size: 13px;color: #66728e;&.number {color: #23d7ae;}}}}.right-Fixed {//-----------------//固定直接用position: fixed;固定;z-index: 10;控制层级显示float: right;position: fixed;top: 12px;right: 15px;z-index: 10;//-------------------.info-container {margin-right: 8px;span {padding: 0 5px;font-size: 13px;color: #66728e;&.number {color: #23d7ae;}}}}
</style>

6.【教考平台】表单验证配置记录

需求:

  • 教考平台的CommonForm组件表单进行输入校验的配置写法。

代码(Javascript)

 rules: {taskName: [{required: true,message: '任务名称不能为空',trigger: 'blur',type: 'string'},{pattern: /^[^%&]*$/,message: '任务名称不支持%和&字符',trigger: 'blur'},{validator: (rule: any, value: string, callback: Function) => {if (value &&value .length > 100) {callback(new Error('任务名称不得超过100个字符'));} else {callback();}}}],

7.传参处理

代码(Javascript)

//把name :"name1,name2" 改成 name : p.within("name1","name2")if (this.name) {if (/ /.test(this.name) || /%/.test(this.name) || /&/.test(this.name)) {let nameArr = '';nameArr = this.name.replace(/%/g, '","').replace(/&/g, '","').replace(/ /g, '","').split(',').join();nameArr = '"' + nameArr + '"';orConditionMap.name = 'P.within(' + nameArr + ')';orConditionMap.identifier = 'P.within(' + nameArr + ')';}else {orConditionMap.name = `P.within("${this.name}")`;orConditionMap.identifier = this.name;}}

8.子组件值变化触发父-父组件

需求:

  • 有时候我们需要利用深层的子组件影响到上一层,甚至上上层的组件
  • 利用watch、emit实现

代码(Javascript)

//子组件内@Prop({type: Array,default: () => {return []}})value: Array<Array<string>>;// 父组件传下来的值//1.监听父组件传下来的值触发emit(父组件利用子组件)@Watch('value', {deep: true,immediate: true})public watchValue (newValue: Array<any>) {//值触发TagCom组件的updateModel方法this.$emit('changeFun');}//2.直接子组件函数触发emit(子组件影响父组件)public getChangeFun(newValue: Array<any>) {this.$emit('changeFun');}//-------------------------------//父组件内<!-- 多层级级联 --><CascaderMult v-if="item.type==='multCascader'" :value="item.value" @changeFun="multCascaderChangeFun(item)"></CascaderMult>public multCascaderChangeFun (item: any) {if (item.changeFun) {item.changeFun();}}//祖组件内//通过检查type字符串内包含multCascader,调用父组件的changeFun 函数if (['select', 'cascader', 'multCascader', 'numberRange', 'yearRange'].includes(type)) {(item as any).changeFun = () => {//向再上一级组件发送emitthis.$emit('updateModel', true);}}//老祖组件//子组件这样跨越三层组件通过值变化触发updateModel函数<TagCom ref="moreTagFilter" :tagData="moreTagData" :tagArr="moreTagArr" :needAll="true" @updateModel="updateModel"></TagCom>public async updateModel () {}

9.对象、数组的深拷贝

需求:

  • 对象、数组有时候需要对里面的某个值进行拷贝,这时候直接赋值、浅拷贝,都会变成引用,改一处,原始的值也会变(浅拷贝)

代码(Javascript)

//方法一:浅拷贝的实现 注意:当拷贝对象只有一层的时候,是深拷贝
// 1.展开运算符... 实现浅拷贝
let obj1 = {name: 'Chen',hobby: ['see a film', 'write the code', 'play basketball', 'tourism']
}let obj2 = {...obj1};//2.Object.assign() 实现浅拷贝
let obj1 = {name: 'Chen',hobby: ['see a film', 'write the code', 'play basketball', 'tourism']
}let obj2 = Object.assign({}, obj1);// 3.Array.prototype.concat() 实现浅拷贝
let arr1 =  [{name: 'Chen'},'see a film', 'write the code', 'play basketball', 'tourism'
];
let arr2 = arr1.concat([]);//4. Array.prototype.concat() 实现浅拷贝
let arr1 =  [{name: 'Chen'},'see a film', 'write the code', 'play basketball', 'tourism'
];
let arr2 = arr1.slice();//深拷贝的实现
//1.  JSON.parse(JSON.stringify())实现深拷贝Object
let obj1 = {name: 'Chen',hobby: ['see a film', 'write the code', 'play basketball', 'tourism']
}
let obj2 = JSON.parse(JSON.stringify(obj1));
//  JSON.parse(JSON.stringify())实现深拷贝Array
let arr1 =  [{name: 'Chen'},'see a film', 'write the code', 'play basketball', 'tourism'
];
let arr2 = JSON.parse(JSON.stringify(arr1));

10.遍历筛选对象对应属性的技巧

代码(Javascript)

   "properties": [{"name": "year","cnName": null,"value": "2022-01-01 00:00:00.000","cnNames": ""},{"name": "numberOfOptions","cnName": null,"value": 0,"cnNames": ""},{"name": "discipline","cnName": null,"value": ["english"],"cnNames": ["英文"]},]let TempSourceData = [];const tempObj = {};properties.forEach(properties=> {const { name, value } = proItem;if (['year', 'discipline''].includes(name)) {TempSourceData.push(proItem);tempObj[name] = value;}});this.stTagData = tempObj;this.sourceData = TempSourceData;}//--------------------------sourceData = [{"name": "year","cnName": null,"value": "2022-01-01 00:00:00.000","cnNames": ""},{"name": "discipline","cnName": null,"value": ["english"],"cnNames": ["英文"]}]stTagData = {"year": "2022-01-01 00:00:00.000","discipline": ["english"],}

11.watch监听深层数组出现视图不更新的情况

需求:

  • 某些情况下,对一个数组很深的值进行更改后,视图并不会刷新,这时候可以先把原视图的值全干掉,再用nextTick在dom更新后赋值

代码(Javascript)

  @Watch('sourceData', {immediate: true,deep: true})public setStSourceData(newValue: any) {const tempObj = {};if (newValue) {newValue.forEach(item =>{const { name, value,cnNames } = item;if(name == 'sourceOfTestQuestions'){debugger;//stly1001:教学,stly1002:模考if(value == 'stly1002'){//1.tempArr 临时存一下不刷新的值(tempArr 引用类型)let tempArr = this.categoryArr;//2.需要改数组categoryArr里面的required (比较深)this.categoryArr[0].categoryFormObj.rules.category[0].required = false;//----------------------------------------//3.先把categoryArr(原视图数组)全干掉this.$set(this, 'categoryArr', []);//4.再延迟回调把更改的categoryArr赋回去this.$nextTick(()=>{this.$set(this, 'categoryArr', tempArr);}//---------------------------------------------// this.categoryFormObj.rules.category[0].required = false;}tempObj[name] = value;}if(name == 'point'){tempObj[name] = value.name;   }if(name == 'testPaperClassification'){tempObj[name] = cnNames.toString();   }});this.stSelectData = tempObj;}}

12.对象object那些事

1.Object.keys()以及Object.getOwnPropertyNames()

  • Object.keys方法和Object.getOwnPropertyNames方法都用来遍历对象的属性。
  • 区别:Object.keys方法只返回可枚举的属性,Object.getOwnPropertyNames方法还返回不可枚举的属性名。
//1.
var obj = {p1: 123,p2: 456
};
Object.keys(obj) // ["p1", "p2"]
Object.getOwnPropertyNames(obj) // ["p1", "p2"]//2.数组的length属性是不可枚举的属性
var a = ['Hello', 'World'];
Object.keys(a) // ["0", "1"]
Object.getOwnPropertyNames(a) // ["0", "1", "length"]

13.对象数组去重(拿来主义)

  • 注意:只能筛选第一层,深层的需要再次调函数去重;

1.使用filter和Map

//arr:需去重对象数组;uniId:筛选属性(字符串)
function uniqueFunc(arr, uniId){const res = new Map();return arr.filter((item) => !res.has(item[uniId]) && res.set(item[uniId], 1));
}

2.使用reduce

//arr:需去重对象数组;uniId:筛选属性(字符串)
function uniqueFunc2(arr, uniId){let hash = {}return arr.reduce((accum,item) => {hash[item[uniId]] ? '' : hash[item[uniId]] = true && accum.push(item)return accum},[])
}

3.使用filter和Map

//arr:需去重对象数组;uniId:筛选属性(字符串)
unction uniqueFunc3(arr, uniId){let obj = {}let tempArr = []for(var i = 0; i<arr.length; i++){if(!obj[arr[i][uniId]]){tempArr.push(arr[i])obj[arr[i][uniId]] = true}}return tempArr
}

14.iview表格之render函数

  • 利用render函数渲染表格内容

1.渲染提示图标ToolTip

要求效果:

代码:

{title: '授权状态',key: 'authStatus',fixed: 'right',width: 111,align: 'center',ellipsis: true,tooltip: true,render: (h, params) => {const row: any = params.row;if (row.authStatus === 'failed') {return h('div', [h('span',{class: `${row.authStatus} template-status`},this.statusMap[row.authStatus].name),h('Tooltip', {props: {content: row.extend.errorDesc,transfer: true},style: 'white-space: normal;'}, [h('i', {class: 'ivu-icon ivu-icon-ios-help-circle-outline'})])]);} else {return h('span',{class: `${row.authStatus} template-status`},this.statusMap[row.authStatus].name);}}},

2.表头渲染提示图标ToolTip(renderHeader)

要求效果:

代码:

{// title: '授权进度',key: 'progress',minWidth: 120,align: 'center',// ellipsis: true,// tooltip: true,renderHeader: (h, params) => {return h('div', [h('Tooltip', {props: {content: '授权进度:授权成功/申请授权',trigger: 'hover',size: 'small',placement: 'top-start',theme: 'light',transfer: true}}, [h('span', {domProps: {innerHTML: '授权进度'}}),h('Icon', {props: {type: 'ios-help-circle-outline'}})]),])}},

15.非表格多选

  • 多选
要求效果:

代码:

<template>
//全部全选
<Checkbox v-model="allPageSel" >当前页全选</Checkbox>
//遍历listData中的每个多选框<div class="list-item" v-for="(item, index) in listData" :key="index"><Checkbox v-if="type === 'st'" class="status-checkbox" v-model="item.checkSel" @on-change="getAllCheckSel(item,index)"></Checkbox></div>
</template><script lang="ts">
allCheckSel: Array<any> = [];
allPageSel: boolean= false;//this.listData在列表刷新时初始化checkSel ,设为falseif (res) {const data: any = res.data;const records: Array<any> = data.records;records.forEach(item => {//初始未勾选item.checkSel = false;});this.listData = records;this.checkSelToList(); }}
//全部勾选时@Watch('allPageSel', {})public allCheckBoxSel(val){//全部勾选时给this.listData所有item的checkSel 设状态this.listData = this.listData.map(sel =>{sel.checkSel = val ? true : false;return sel;})this.listData.forEach((sel) =>{this.getAllCheckSel(sel);})}//对象数组去重private uniqueFunc(arr, uniId) {const res = new Map();return arr.filter((item) => !res.has(item[uniId]) && res.set(item[uniId], 1));}//根据checkSel状态,将数据存入allCheckSelpublic getAllCheckSel(item,index){if(item.checkSel){this.allCheckSel.push(item);//根据id去重this.allCheckSel = this.uniqueFunc(this.allCheckSel, 'id');}else {this.allCheckSel = this.allCheckSel.filter(sel =>{return sel.id !== item.id;})}this.listData[index].checkSel = item.checkSel;this.syncCheckSel();}//根据id对比将allCheckSel数组里的勾选状态checkSel 赋给listData(用来回显勾选不勾选)public checkSelToList() {if(this.allCheckSel.length) {this.allCheckSel.forEach(sel => {this.listData.forEach(item => {if(sel.id === item.id) {item.checkSel = sel.checkSel;}})})}this.syncCheckSel();}//同步全勾选/勾选public syncCheckSel() {let isAllSel = true;this.listData.forEach(sel =>{if(!sel.checkSel) {isAllSel = false;}});this.allPageSel = isAllSel;}</script>

16.自由调整iview对话框尺寸

  • 可以调整组件对话框大小
要求效果:


代码:

//CSS3 resize 属性
//指定一个div元素,允许用户调整大小
div {resize:both;overflow:auto;
}

17.剪切板使用记录

  • 1、剪切板可以从剪切板粘贴图片到外界;
  • 2、可以写入图片到剪切板
  • 代码:

<template><div class="drawing-container"><div id="tui-image-editor"></div><Tooltip class="icon-copy" content="导入图片" placement="right" transfer><Icon type="ios-cut-outline" size="26" @click="getClipboardContents()" /></Tooltip><Tooltip class="icon-out" content="导出图片" placement="right" transfer><Icon type="ios-log-out" size="26" @click="writeDataToClipboard()" /></Tooltip></div>
</template>
<script>
export default {data() {return {instance: null,isCopy: null,url: '',path: img}},mounted() {const that = this// document.addEventListener('paste', function (event) {//   console.log(event)//   let items = event.clipboardData && event.clipboardData.items;//   let file = null;//   if (items && items.length) {//     // 检索剪切板 items//     for (var i = 0; i < items.length; i++) {//       if (items[i].type.indexOf('image') !== -1) {//         // 此时file就是剪切板中的图片文件//         file = items[i].getAsFile();//         break;//       }//     }//   }//   const url = window.URL.createObjectURL(file);//   console.log(url)//拿到url可以做下一步处理// });document.onkeydown = async function (event) {let key = window.event.keyCode;if (key === 86 && event.ctrlKey) {// 监听ctrl+V组合键// window.event.preventDefault(); //关闭浏览器默认快捷键            // console.log('crtl+ V 组合键',navigator.clipboard)const clipboardItems = await navigator.clipboard.read();for (const clipboardItem of clipboardItems) {for (const type of clipboardItem.types) {const blob = await clipboardItem.getType(type);console.log("已读取剪贴板中的内容:", blob, await blob.text());if (/image/.test(blob.type) && blob.size !== 267) {that.url = window.URL.createObjectURL(blob);//拿到url可以做下一步处理that.isCopy = blob.size;}}}}}},watch: {isCopy: function (newVal, oldVal) {if (this.url) {//拿到url可以做下一步处理}}},methods: {async writeDataToClipboard() {try {const base64String = this.instance.toDataURL() // base64 文件const data = window.atob(base64String.split(',')[1])const ia = new Uint8Array(data.length)for (let i = 0; i < data.length; i++) {ia[i] = data.charCodeAt(i)}const imageBlob = new Blob([ia], { type: 'image/png' }) // blob 文件const item = new ClipboardItem({[imageBlob.type]: imageBlob,});await navigator.clipboard.write([item]);this.$Message.success('图片已导出至粘贴板,Ctrl+V可粘贴');} catch (error) {this.$Message.error('图片导出失败', error);}},async getClipboardContents() {try {const clipboardItems = await navigator.clipboard.read();for (const clipboardItem of clipboardItems) {for (const type of clipboardItem.types) {const blob = await clipboardItem.getType(type);if (/image/.test(blob.type)) {const url = window.URL.createObjectURL(blob);//拿到url可以做下一步处理}}}} catch (err) {console.error("图片导入失败", err);this.$Message.error("图片导入失败", err);}},}
}
</script><style lang="scss" scoped>
.drawing-container {// height: 900px;width: 1076px;height: 658px;position: relative;border: 1px solid #000;.save {position: absolute;right: 50px;top: 15px;}.icon-copy {cursor: pointer;position: absolute;right: 1035px;top: 38px;}:hover {color: rgb(197, 197, 197);}.icon-out {cursor: pointer;position: absolute;right: 1035px;top: 568px;}:hover {color: rgb(197, 197, 197);}
}</style>

16.利用ChatGpt输出的符合vue3+ts规范的防抖函数

  • 这里我们使用了 defineComponent 函数来定义组件,使用了 ref 函数来创建响应式数据 keyword,使用了 computed 函数来计算 debounceSearch 的值。
    另外,我们对 debounce 函数的泛型类型参数做了一些调整,可以更好地支持类型推断,还调整了一些类型错误,使得代码符合 Vue 3 + TypeScript 规范。
    需要注意的是,由于 this 的类型是 unknown,而不是 any,因此需要进行类型断言。在这里,我们使用了 as 关键字将返回值的类型声明为和函数参数类型相同的泛型类型 F。
    最后,我们在 setup 函数中返回了响应式数据 keyword、计算属性 debounceSearch,以及搜索函数 search。
要求效果:

代码:

<template><el-input v-model="keyword" placeholder="请输入关键字" @input="debounceSearch"></el-input>
</template><script lang="ts">
import { defineComponent, ref, computed } from 'vue';// 防抖函数
function debounce<F extends (...args: any[]) => any>(fn: F, delay: number) {let timer: ReturnType<typeof setTimeout> | null;return function(this: unknown, ...args: Parameters<F>) {if (timer) {clearTimeout(timer);}timer = setTimeout(() => {fn.apply(this as unknown, args);}, delay);} as F;
}export default defineComponent({setup() {const keyword = ref('');const search = () => {console.log('search:', keyword.value);};const debounceSearch = computed(() => debounce(search, 500));return {keyword,debounceSearch,};},
});
</script>

后续

同时,贴上咱的个人博客,欢迎客官大老爷们来访~
青枫阁

更多推荐

【前端开发】前端小白必会开发小技巧

本文发布于:2024-03-12 21:05:32,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1732419.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:小技巧   必会

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!