vue實(shí)現(xiàn)檢測敏感詞過濾組件的多種思路
寫在前面
在做商戶端敏感詞檢測的過程中,發(fā)現(xiàn)了一些問題,特在此總結(jié)。本文的行文思路是編寫敏感詞檢測代碼,前兩個(gè)思路未采用組件化的開發(fā)思想,后三個(gè)思路根據(jù)需求變更,采用組件化的思想和mixins混入進(jìn)行開發(fā)。
需求分析v1
在商戶端產(chǎn)品模塊,點(diǎn)擊產(chǎn)品編輯按鈕,可以修改產(chǎn)品的標(biāo)題和價(jià)格。當(dāng)沒有填寫產(chǎn)品標(biāo)題時(shí),置灰保存按鈕;當(dāng)填寫的產(chǎn)品標(biāo)題屬于敏感詞時(shí),置灰保存按鈕并給出后端返回的提示。
在商戶端定制模塊,定制完成后,直接跳轉(zhuǎn)到產(chǎn)品編輯頁面,可以修改產(chǎn)品標(biāo)題和價(jià)格。當(dāng)沒有填寫產(chǎn)品標(biāo)題時(shí),置灰保存按鈕;當(dāng)填寫的產(chǎn)品標(biāo)題屬于敏感詞時(shí),置灰保存按鈕并給出后端返回的提示。
思路一:使用截流方法監(jiān)聽輸入框的input事件
因?yàn)楸救素?fù)責(zé)的是產(chǎn)品模塊,不知道定制模塊的產(chǎn)品標(biāo)題也需要增加敏感詞檢測,所以最開始并沒有將敏感詞檢測寫成組件。于是有了第一種思路:使用截流方法監(jiān)聽輸入框的input事件。
思路:
1.只要輸入不為空或者全是空格,每次輸入后都會觸發(fā)輸入框的input事件,調(diào)用敏感詞檢測接口。頻繁地請求接口會給服務(wù)器造成巨大的壓力,因此可以使用截流方法降低接口請求的頻率;
2.為請求的接口增加一個(gè)定時(shí)器,并添加一個(gè)倒計(jì)時(shí)間,記為1s,每次輸入后都延遲1s請求接口。于是可以在輸入框的input事件觸發(fā)后,清除掉上一個(gè)定時(shí)器。防止定時(shí)器疊加,重復(fù)請求多次接口,只保留最后一次input事件觸發(fā)的敏感詞檢測的接口請求。這也就意味著,如果用戶連續(xù)輸入產(chǎn)品標(biāo)題,且每次輸入的間隔時(shí)間小于1s,則用戶最后一次輸入的信息會被接口檢測是否合乎敏感詞規(guī)范;如果用戶間隔著輸入產(chǎn)品標(biāo)題,且間隔時(shí)間都超過1s,則會發(fā)起多次接口請求,還是會對服務(wù)器造成不小的壓力,所以這種方法還是存在局限性。
//敏感詞檢測的html <div class="edit-title">產(chǎn)品標(biāo)題</div> <el-input v-model="productName" placeholder="請輸入產(chǎn)品標(biāo)題" 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) } }
缺陷: 當(dāng)為產(chǎn)品標(biāo)題添加敏感詞后,只要手速足夠快,在1s內(nèi)點(diǎn)擊保存按鈕,還是可以成功保存敏感詞,這與我們的需求相違背。
思路二:使用輸入框的失焦和保存按鈕的點(diǎn)擊事件
既然使用輸入框的input事件存在問題,那是否能夠使用輸入框的失焦事件和保存按鈕的點(diǎn)擊事件呢?答案是可以的。只不過在這個(gè)過程中,有兩個(gè)問題需要特別注意。
注意事項(xiàng):
- 需要理解失焦事件。 何為失焦?在輸入框內(nèi)輸入完標(biāo)題之后,點(diǎn)擊輸入框外的任意地方都會觸發(fā)失焦事件。所以,千萬不要忘記點(diǎn)擊保存按鈕同樣會觸發(fā)失焦事件。因此,只需要在輸入框失焦事件中請求敏感詞檢測接口,無需在點(diǎn)擊事件中重復(fù)請求。
- 需要考慮觸發(fā)失焦事件和點(diǎn)擊事件帶來的的異步問題。 點(diǎn)擊保存按鈕會同時(shí)觸發(fā)失焦事件和點(diǎn)擊事件,失焦事件會優(yōu)先點(diǎn)擊事件執(zhí)行。失焦事件用于請求敏感詞檢測接口,點(diǎn)擊事件用于修改產(chǎn)品信息。交互邏輯是先請求敏感詞檢測接口,如果接口返回的狀態(tài)是成功,則不需要顯示錯(cuò)誤提示信息;否則需要顯示后端返回的錯(cuò)誤信息,并禁用保存按鈕。待校驗(yàn)成功之后再請求修改產(chǎn)品信息的接口。因此,這兩個(gè)方法是存在一個(gè)先后順序的。而且一定是失焦事件請求敏感詞接口在前,請求修改產(chǎn)品信息在敏感詞接口請求結(jié)束之后。不能因?yàn)槊舾性~檢測過慢導(dǎo)致非法的敏感詞已經(jīng)成功保存并渲染,此時(shí)再請求敏感詞檢測接口是沒必要的。由于無法確定和保證兩個(gè)接口的,所以需要增加一個(gè)變量來判斷敏感詞接口是否請求結(jié)束。如果接口沒有請求結(jié)束,需要在點(diǎn)擊事件中重新發(fā)起請求;如果接口已經(jīng)完成請求,則直接return忽略掉。
思路:
- 為輸入框添加失焦事件;
- 為保存按鈕添加點(diǎn)擊事件。
代碼:
<div class="edit-title">產(chǎn)品標(biāo)題</div> <el-input v-model="productName" placeholder="請輸入產(chǎn)品標(biāo)題" 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 }, //點(diǎn)擊事件(請求修改產(chǎn)品信息接口) 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: '產(chǎn)品修改成功!' }) }) .catch((message) => { this.$message({ type: 'error', message }) }) this.showEditProductDialog = false } }
思路三:使用mixins抽取敏感詞檢測方法
本以為敏感詞檢測就這樣離我而去了,結(jié)果收到產(chǎn)品消息,同樣需要給定制模塊的產(chǎn)品標(biāo)題增添敏感詞檢測。之后就是一頓ctrl+c和ctrl+v操作猛如虎,最后發(fā)現(xiàn)代碼冗余過多,需要對代碼進(jìn)行整理。此處和后續(xù)都只寫產(chǎn)品模塊的敏感詞檢測邏輯,定制模塊的敏感詞檢測邏輯其實(shí)和產(chǎn)品模塊大同小異。 既然定制模塊的產(chǎn)品標(biāo)題編輯和產(chǎn)品模塊的樣式和邏輯相差無幾,那何不抽取敏感詞檢測公共方法呢?就這么愉快地決定了,鍵盤上一頓狂敲亂打后,混入方法就成型了:
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">產(chǎn)品標(biāo)題</div> <el-input v-model="productName" placeholder="請輸入產(chǎn)品標(biāo)題" 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: { //點(diǎn)擊事件(請求修改產(chǎn)品信息接口) 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: '產(chǎn)品修改成功!' }) }) .catch((message) => { this.$message({ type: 'error', message }) }) this.showEditProductDialog = false } } }
思路四:使用promise封裝敏感詞檢測組件(面向需求v1)
考慮到產(chǎn)品模塊敏感詞檢測和定制模塊的html結(jié)構(gòu)相差無幾,決定封裝一個(gè)敏感詞檢測組件,將產(chǎn)品標(biāo)題敏感詞檢測的html代碼和業(yè)務(wù)邏輯放在一起。但在這個(gè)過程中,有三個(gè)問題需要特別注意:
注意事項(xiàng):
- async函數(shù)返回的是一個(gè)promise對象;
- 不能直接修改傳入的props值,但是可以通過中間變量,將中間變量和props雙向綁定,從而間接地修改props的值;
- 可以在父組件給props增加sync修飾符,在子組件中對props和中間變量進(jìn)行監(jiān)聽。如果任意一方的值發(fā)生變化,都會將改變后的值賦予給另一方,從而達(dá)到雙向綁定的目的。
思路:
- 編寫敏感詞檢測組件;
- 引入敏感詞檢測組件。
//敏感詞檢測組件 <template> <div> <el-input v-model="input" placeholder="請輸入產(chǎn)品標(biāo)題" 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 = '請輸入產(chǎn)品名稱' } 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: '產(chǎn)品修改成功!' }) }) this.showEditProductDialog = false }) .catch(()=>{ this.$message({ type: 'error', message: '請輸入合法的產(chǎn)品名稱' }) }) }, getProductListData(status, page) { this.$store.dispatch('products/getList', { limit: 16, status, order: 'id', direction: 'desc', page }) } } </script> <template> <div> <div class="edit-title">產(chǎn)品標(biāo)題</div> <InspectSpams :title.sync="productName" ref="productSpamsRef" /> <el-button type="primary" @click="save">保存</el-button> </div> </template>
思路五:使用插槽和mixins封裝敏感詞檢測組件(面向需求v2)
需求變更: 其實(shí)相比需求v1來說,也沒發(fā)生什么變化。只是產(chǎn)品模塊的產(chǎn)品標(biāo)題必須得填寫,不然得禁止保存按鈕,而定制模塊的產(chǎn)品標(biāo)題可以不填寫,保存后默認(rèn)為填寫的產(chǎn)品標(biāo)題 + 白板名稱。
思路: 既然如此,何不把給錯(cuò)誤提示的html放入一個(gè)組件中,使用插槽占位表示需要檢測的字段,而將敏感詞檢測的邏輯放到mixins中。后續(xù)如果還有其它地方需要進(jìn)行敏感詞檢測,會顯得更加靈活,其實(shí)這樣反倒更利于組件的復(fù)用原則。
//敏感詞檢測組件 <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: '產(chǎn)品修改成功!' }) }) .catch((message) => { this.$message({ type: 'error', message }) }) this.showEditProductDialog = false }, <div class="edit-title">產(chǎn)品標(biāo)題</div> <InspectSpams :isShowMessage="isShowMessage" :errorMessage="errorMessage"> <el-input v-model="productName" placeholder="請輸入產(chǎn)品標(biāo)題" type="text" auto-complete="on" clearable @blur="inspectSpams(productName)" /> </InspectSpams>
優(yōu)化與改進(jìn)
1.優(yōu)化調(diào)用敏感詞檢測的條件。如果產(chǎn)品標(biāo)題沒有發(fā)生變化,則不需要再請求敏感詞檢測接口。因?yàn)橹挥薪?jīng)過檢驗(yàn)成功的標(biāo)題才能被成功保存,所以無需多次重復(fù)調(diào)用接口,需要修改mixins請求接口的條件。
思路: 在根據(jù)產(chǎn)品id打開模態(tài)框請求產(chǎn)品詳情接口的過程中,將對應(yīng)產(chǎn)品信息的name字段賦值給新增的originalName變量。在html和js調(diào)用混入方法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.多次點(diǎn)擊按鈕會重復(fù)請求接口??梢允褂梅蓝?、按鈕啟用倒計(jì)時(shí)、封裝axios請求、給button設(shè)置loading等方式進(jìn)行優(yōu)化。
寫在最后
其實(shí)總結(jié)得不是很好,編寫的組件也不夠好,思路也不太清晰,記錄在這里主要是對思路二和思路四做個(gè)總結(jié),畢竟對vue的文檔還是不太熟悉。在敏感詞檢測組件中,其實(shí)還有很多可以改進(jìn)的地方,歡迎大家在評論區(qū)中指出。
以上就是vue編寫檢測敏感詞匯組件的多種思路的詳細(xì)內(nèi)容,更多關(guān)于vue編寫檢測敏感詞匯組件的資料請關(guān)注腳本之家其它相關(guān)文章!
- Python實(shí)現(xiàn)敏感詞過濾的4種方法
- 基于python實(shí)現(xiàn)檢索標(biāo)記敏感詞并輸出
- laravel框架實(shí)現(xiàn)敏感詞匯過濾功能示例
- python用類實(shí)現(xiàn)文章敏感詞的過濾方法示例
- 淺談Python 敏感詞過濾的實(shí)現(xiàn)
- PHP實(shí)現(xiàn)的敏感詞過濾方法示例
- 利用Python正則表達(dá)式過濾敏感詞的方法
- Python 實(shí)現(xiàn)王者榮耀中的敏感詞過濾示例
- python 實(shí)現(xiàn)敏感詞過濾的方法
- js實(shí)現(xiàn)敏感詞過濾算法及實(shí)現(xiàn)邏輯
- Java實(shí)現(xiàn)DFA算法對敏感詞、廣告詞過濾功能示例
相關(guān)文章
vue3.0實(shí)現(xiàn)復(fù)選框組件的封裝
這篇文章主要為大家詳細(xì)介紹了vue3.0實(shí)現(xiàn)復(fù)選框組件的封裝代碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09Vue常用傳值方式、父傳子、子傳父及非父子實(shí)例分析
這篇文章主要介紹了Vue常用傳值方式、父傳子、子傳父及非父子,結(jié)合實(shí)例形式分析了vue.js常見的傳值方式及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下2020-02-02用vue設(shè)計(jì)一個(gè)數(shù)據(jù)采集器
這篇文章主要介紹了如何用vue設(shè)計(jì)一個(gè)數(shù)據(jù)采集器,幫助大家更好的理解和學(xué)習(xí)使用vue框架,感興趣的朋友可以了解下2021-04-04vue input 輸入校驗(yàn)字母數(shù)字組合且長度小于30的實(shí)現(xiàn)代碼
這篇文章主要介紹了vue input 校驗(yàn)字母數(shù)字組合且長度小于30的實(shí)現(xiàn)代碼,文章給大家補(bǔ)充介紹了在Vue.Js下使用el-input框只能輸入數(shù)字并限制位數(shù)并且限制中文輸入以及粘貼功能,感興趣的朋友跟隨腳本之家小編一起看看吧2018-05-05Vue默認(rèn)插槽,具名插槽,作用域插槽定義及使用方法
這篇文章主要介紹了Vue默認(rèn)插槽,具名插槽,作用域插槽定義及使用方法,插槽的作用是在子組件中某個(gè)位置插入父組件的自定義html結(jié)構(gòu)和data數(shù)據(jù),下面詳細(xì)內(nèi)容需要的小伙伴可以參考一下2022-03-03vue中Echarts使用動態(tài)數(shù)據(jù)的兩種實(shí)現(xiàn)方式
這篇文章主要介紹了vue中Echarts使用動態(tài)數(shù)據(jù)的兩種實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10