基于Vue框架怎样实现敏感词过滤组件,方法是什么
Admin 2022-07-20 群英技术资讯 417 次浏览
在做商户端敏感词检测的过程中,发现了一些问题,特在此总结。本文的行文思路是编写敏感词检测代码,前两个思路未采用组件化的开发思想,后三个思路根据需求变更,采用组件化的思想和mixins混入进行开发。
在商户端产品模块,点击产品编辑按钮,可以修改产品的标题和价格。当没有填写产品标题时,置灰保存按钮;当填写的产品标题属于敏感词时,置灰保存按钮并给出后端返回的提示。
在商户端定制模块,定制完成后,直接跳转到产品编辑页面,可以修改产品标题和价格。当没有填写产品标题时,置灰保存按钮;当填写的产品标题属于敏感词时,置灰保存按钮并给出后端返回的提示。
因为本人负责的是产品模块,不知道定制模块的产品标题也需要增加敏感词检测,所以最开始并没有将敏感词检测写成组件。于是有了第一种思路:使用截流方法监听输入框的input事件。
思路:
1.只要输入不为空或者全是空格,每次输入后都会触发输入框的input事件,调用敏感词检测接口。频繁地请求接口会给服务器造成巨大的压力,因此可以使用截流方法降低接口请求的频率;
2.为请求的接口增加一个定时器,并添加一个倒计时间,记为1s,每次输入后都延迟1s请求接口。于是可以在输入框的input事件触发后,清除掉上一个定时器。防止定时器叠加,重复请求多次接口,只保留最后一次input事件触发的敏感词检测的接口请求。这也就意味着,如果用户连续输入产品标题,且每次输入的间隔时间小于1s,则用户最后一次输入的信息会被接口检测是否合乎敏感词规范;如果用户间隔着输入产品标题,且间隔时间都超过1s,则会发起多次接口请求,还是会对服务器造成不小的压力,所以这种方法还是存在局限性。
//敏感词检测的html <div class="edit-title">产品标题</div> <el-input v-model="productName" placeholder="请输入产品标题" type="text" auto-complete="on" clearable @input="inspectSpams" /> <div v-if="showMessage" class="message">{{ errorMessage }}</div> //保存按钮的html <el-button type="primary" @click="save" :disabled="productName === '' || showMessage === true">保存</el-button>
data() { return { productName: '', errorMessage: '', showMessage: false, timer: -1 } }, methods: { inspect() { if(this.productName.trim() !== '') { this.$store.dispatch('products/inspectSpams', this.productName).catch((err)=>{ this.errorMessage = err.response.data.message this.showMessage = true }) } }, inspectSpams() { this.showMessage = false clearTimeout(this.timer) this.timer = setTimeout(() => { this.inspect() }, 1000) } }
缺陷: 当为产品标题添加敏感词后,只要手速足够快,在1s内点击保存按钮,还是可以成功保存敏感词,这与我们的需求相违背。
既然使用输入框的input事件存在问题,那是否能够使用输入框的失焦事件和保存按钮的点击事件呢?答案是可以的。只不过在这个过程中,有两个问题需要特别注意。
注意事项:
思路:
代码:
<div class="edit-title">产品标题</div> <el-input v-model="productName" placeholder="请输入产品标题" type="text" auto-complete="on" clearable @blur="inspectSpams" /> <div v-if="showMessage" class="message">{{ errorMessage }}</div> <el-button type="primary" @click="save" :disabled="!productName || showMessage">保存</el-button>
data() { return { showMessage: false, productName: '', errorMessage: '', timer: -1, hasVerified: false } }, methods: { //失焦事件(请求敏感词检测接口) async inspectSpams() { this.hasVerified = false this.showMessage = false if(this.productName.trim() !== '') { await this.$store.dispatch('products/inspectSpams', this.productName).catch((err) => { this.errorMessage = err.response.data.message this.showMessage = true }) } this.hasVerified = true }, //点击事件(请求修改产品信息接口) async save() { if(!this.hasVerified) { await this.inspectSpams() } const variants = this.variants.map((variant) => { return { id: variant.id, price: variant.price, } }) const params = { variants, name: this.productName } params.productId = this.productId await this.$store.dispatch('products/editProduct', params) .then(async() => { await this.getProductListData(this.productStatus, 1) this.$message({ type: 'success', message: '产品修改成功!' }) }) .catch((message) => { this.$message({ type: 'error', message }) }) this.showEditProductDialog = false } }
本以为敏感词检测就这样离我而去了,结果收到产品消息,同样需要给定制模块的产品标题增添敏感词检测。之后就是一顿ctrl+c和ctrl+v操作猛如虎,最后发现代码冗余过多,需要对代码进行整理。此处和后续都只写产品模块的敏感词检测逻辑,定制模块的敏感词检测逻辑其实和产品模块大同小异。 既然定制模块的产品标题编辑和产品模块的样式和逻辑相差无几,那何不抽取敏感词检测公共方法呢?就这么愉快地决定了,键盘上一顿狂敲乱打后,混入方法就成型了:
export default { data() { return { hasVerified: false, showMessage: false, errorMessage: '' } }, methods: { async inspectSpams(name) { this.hasVerified = false this.showMessage = false if(name.trim() !== '') { await this.$store.dispatch('products/inspectSpams', name).catch((err) => { this.errorMessage = err.response.data.message this.showMessage = true }) } this.hasVerified = true } } }
<div class="edit-title">产品标题</div> <el-input v-model="productName" placeholder="请输入产品标题" type="text" auto-complete="on" clearable @blur="inspectSpams(productName)" /> <div v-if="showMessage" class="message">{{ errorMessage }}</div> <el-button type="primary" @click="save" :disabled="!productName || showMessage">保存</el-button>
import inspectSpams from '@/mixins/inspectSpams' export default { data() { return { productName: '' } }, mixins: [ inspectSpams ], methods: { //点击事件(请求修改产品信息接口) async save() { if(!this.hasVerified) { await this.inspectSpams(this.productName) } const variants = this.variants.map((variant) => { return { id: variant.id, price: variant.price, } }) const params = { variants, name: this.productName } params.productId = this.productId await this.$store.dispatch('products/editProduct', params) .then(async() => { await this.getProductListData(this.productStatus, 1) this.$message({ type: 'success', message: '产品修改成功!' }) }) .catch((message) => { this.$message({ type: 'error', message }) }) this.showEditProductDialog = false } } }
考虑到产品模块敏感词检测和定制模块的html结构相差无几,决定封装一个敏感词检测组件,将产品标题敏感词检测的html代码和业务逻辑放在一起。但在这个过程中,有三个问题需要特别注意:
注意事项:
思路:
//敏感词检测组件 <template> <div> <el-input v-model="input" placeholder="请输入产品标题" type="text" clearable @blur="inspectSpams" /> <div v-if="isShowMessage" class="message">{{ errorMessage }}</div> </div> </template> <script> export default { props: { title: { required: true, type: String } }, data() { return { input: '', isShowMessage: false, errorMessage: '', hasVerified: true } }, watch: { title: { handler(val) { this.input = val }, immediate: true }, input(val) { this.$emit('update:title', val) } }, methods: { async inspectSpams() { this.hasVerified = false this.isShowMessage = false if (this.input !== '') { await this.$store.dispatch('products/inspectSpams', this.input).catch((err) => { this.errorMessage = err.response.data.message this.isShowMessage = true }) } this.hasVerified = true }, init() { this.isShowMessage = false }, async verify() { if (!this.hasVerified) { await this.inspectSpams() } const emptyInput = this.input.trim() if (emptyInput === '') { this.isShowMessage = true this.errorMessage = '请输入产品名称' } return new Promise((resvole, reject) => { if (Boolean(!emptyInput || this.isShowMessage)) { reject() } else { resvole() } }) } } } </script> <style> .message { font-weight: bold; color: red; margin-top: 10px; } </style>
//引入敏感词检测组件 <script> import { mapState } from 'vuex' import InspectSpams from '@/components/InspectSpams' export default { name: 'List', components: { InspectSpams }, data() { return { productName: '' } }, computed: { ...mapState({ variants: (state) => state.products.detail.variants }), }, methods: { save() { this.$refs.productSpamsRef.verify() .then(async()=>{ const variants = this.variants.map((variant) => { return { id: variant.id, price: variant.price, } }) const params = { variants, name: this.productName } params.productId = this.productId await this.$store.dispatch('products/editProduct', params) .then(async() => { await this.getProductListData(this.productStatus, 1) this.$message({ type: 'success', message: '产品修改成功!' }) }) this.showEditProductDialog = false }) .catch(()=>{ this.$message({ type: 'error', message: '请输入合法的产品名称' }) }) }, getProductListData(status, page) { this.$store.dispatch('products/getList', { limit: 16, status, order: 'id', direction: 'desc', page }) } } </script> <template> <div> <div class="edit-title">产品标题</div> <InspectSpams :title.sync="productName" ref="productSpamsRef" /> <el-button type="primary" @click="save">保存</el-button> </div> </template>
需求变更: 其实相比需求v1来说,也没发生什么变化。只是产品模块的产品标题必须得填写,不然得禁止保存按钮,而定制模块的产品标题可以不填写,保存后默认为填写的产品标题 + 白板名称。
思路: 既然如此,何不把给错误提示的html放入一个组件中,使用插槽占位表示需要检测的字段,而将敏感词检测的逻辑放到mixins中。后续如果还有其它地方需要进行敏感词检测,会显得更加灵活,其实这样反倒更利于组件的复用原则。
//敏感词检测组件 <template> <div> <slot /> <div v-if="isShowMessage" class="message"> {{ errorMessage }} </div> </div> </template> <script> export default { props: { isShowMessage: { required: true, type: Boolean }, errorMessage: { required: true, type: String } } } </script> <style> .message { font-weight: bold; color: red; margin-top: 10px; } </style>
//敏感词检测的mixins export default { data() { return { isShowMessage: false, errorMessage: '', hasVerified: true } }, methods: { async inspectSpams(name) { this.hasVerified = false this.isShowMessage = false if (name.trim() !== '') { await this.$store.dispatch('products/inspectSpams', name).catch((err) => { this.errorMessage = err.response.data.message this.isShowMessage = true }) } this.hasVerified = true } } }
import InspectSpams from '@/components/InspectSpams' import inspectSpams from '@/mixins/inspectSpams' components: { InspectSpams }, mixins: [ inspectSpams ], async save() { if(!this.hasVerified) { await this.inspectSpams(this.productName) } const variants = this.variants.map((variant) => { return { id: variant.id, price: variant.price, } }) const params = { variants, name: this.productName } params.productId = this.productId await this.$store.dispatch('products/editProduct', params) .then(async() => { await this.getProductListData(this.productStatus, 1) this.$message({ type: 'success', message: '产品修改成功!' }) }) .catch((message) => { this.$message({ type: 'error', message }) }) this.showEditProductDialog = false }, <div class="edit-title">产品标题</div> <InspectSpams :isShowMessage="isShowMessage" :errorMessage="errorMessage"> <el-input v-model="productName" placeholder="请输入产品标题" type="text" auto-complete="on" clearable @blur="inspectSpams(productName)" /> </InspectSpams>
1.优化调用敏感词检测的条件。如果产品标题没有发生变化,则不需要再请求敏感词检测接口。因为只有经过检验成功的标题才能被成功保存,所以无需多次重复调用接口,需要修改mixins请求接口的条件。
思路: 在根据产品id打开模态框请求产品详情接口的过程中,将对应产品信息的name字段赋值给新增的originalName变量。在html和js调用混入方法inspectSpams的过程中,将originalName和productName作为变量传入即可。
//修改后的mixins混入 export default { data() { return { isShowMessage: false, errorMessage: '', hasVerified: true } }, methods: { async inspectSpams(originalName, currentName) { this.hasVerified = false this.isShowMessage = false if (originalName !== currentName && currentName.trim() !== '') { await this.$store.dispatch('products/inspectSpams', currentName).catch((err) => { this.errorMessage = err.response.data.message this.isShowMessage = true }) } this.hasVerified = true } } }
2.多次点击按钮会重复请求接口。可以使用防抖、按钮启用倒计时、封装axios请求、给button设置loading等方式进行优化。
其实总结得不是很好,编写的组件也不够好,思路也不太清晰,记录在这里主要是对思路二和思路四做个总结,毕竟对vue的文档还是不太熟悉。在敏感词检测组件中,其实还有很多可以改进的地方,欢迎大家在评论区中指出。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
JS有哪些好用的小技巧呢?下文有实例供大家参考,对大家了解操作过程或相关知识有一定的帮助,而且实用性强,希望这篇文章能帮助大家,下面我们一起来了解看看吧。
这篇文章主要介绍了React三大属性之Refs的使用详解,帮助大家更好的理解和学习使用React,感兴趣的朋友可以了解下
本篇文章给大家带来了关于javascript的相关知识,其中主要介绍了关于基础语法的相关问题,JavaScript是互联网上最流行的脚本语言,下面就一起来看一下,希望对大家有帮助。
这篇文章主要介绍了JavaScript实现图片合成下载的示例,帮助大家更好的理解和学习JavaScript,感兴趣的朋友可以了解下
目录引言设计原则1. 明确不同角色的职责2. 发挥代码的威力,而不是限制3. 各个层面的可扩展性4. 专注而不是发散Sunmao 的工作原理响应最新的状态组件间交互布局与样式类型安全在组件间复用代码可扩展的可视化编辑器保持开放引言尽管现在越来越多的人开始对低代码开发感兴趣,但已有低代码方案的一些局限性仍然让大家有所保留
成为群英会员,开启智能安全云计算之旅
立即注册Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008