Vue implements various ideas for detecting sensitive word filtering components

Vue implements various ideas for detecting sensitive word filtering components

Written in front

In the process of detecting sensitive words on the merchant side, we found some problems, which we summarize here. The idea of ​​this article is to write sensitive word detection code. The first two ideas do not adopt the component-based development idea, and the last three ideas are developed according to the changes in requirements using the component-based idea and mixins.

Requirements Analysis v1

In the merchant product module, click the product edit button to modify the product title and price. When the product title is not filled in, the Save button is grayed out; when the filled-in product title contains sensitive words, the Save button is grayed out and a prompt is given for the backend return.

In the merchant-side customization module, after customization is completed, you can directly jump to the product editing page to modify the product title and price. When the product title is not filled in, the Save button is grayed out; when the filled-in product title contains sensitive words, the Save button is grayed out and a prompt is given for the backend return.

Idea 1: Use interception method to monitor input events of input box

Because I was in charge of the product module, I didn't know that the product titles of the customized modules also needed to add sensitive word detection, so I didn't write sensitive word detection as a component at the beginning. So there is the first idea: use the interception method to monitor the input event of the input box.

Ideas:

1. As long as the input is not empty or full of spaces, the input event of the input box will be triggered after each input, and the sensitive word detection interface will be called. Frequent interface requests will cause huge pressure on the server, so the interception method can be used to reduce the frequency of interface requests;

2. Add a timer for the requested interface and add a countdown time of 1s. Delay the request interface by 1s after each input. Therefore, the previous timer can be cleared after the input event of the input box is triggered. Prevent timer overlap and repeated interface requests, and only retain the interface request for sensitive word detection triggered by the last input event. This means that if the user enters the product title continuously and the interval between each input is less than 1s, the information entered by the user for the last time will be checked by the interface to see if it complies with the sensitive word specifications; if the user enters the product title at intervals and the interval time exceeds 1s, multiple interface requests will be initiated, which will still cause considerable pressure on the server, so this method still has limitations.

//HTML for sensitive word detection
<div class="edit-title">Product Title</div>
   <el-input
     v-model="productName"
     placeholder="Please enter the product title"
     type="text"
     auto-complete="on"
     clearable
     @input="inspectSpams"
   />
<div v-if="showMessage" class="message">{{ errorMessage }}</div>

//Save button html
<el-button type="primary" @click="save" :disabled="productName === '' || showMessage === true">Save</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)
    }
  }   

Defect: After adding sensitive words to the product title, as long as the hand speed is fast enough, the sensitive words can be successfully saved by clicking the Save button within 1 second, which is contrary to our needs.

Idea 2: Use the input box's focus loss and the save button's click event

Since there are problems using the input event of the input box, is it possible to use the focus loss event of the input box and the click event of the save button? The answer is yes. However, there are two issues that require special attention in this process.

Note:

  • Need to understand out-of-focus events. What is out of focus? After entering the title in the input box, clicking anywhere outside the input box will trigger a focus loss event. So, don't forget that clicking the Save button will also trigger a loss of focus event. Therefore, you only need to request the sensitive word detection interface in the input box out of focus event, without having to repeat the request in the click event.
  • It is necessary to consider the asynchronous problems caused by triggering out-of-focus events and click events. Clicking the Save button will trigger both the out-of-focus event and the click event. The out-of-focus event will take precedence over the click event. The out-of-focus event is used to request the sensitive word detection interface, and the click event is used to modify product information. The interaction logic is to first request the sensitive word detection interface. If the status returned by the interface is successful, there is no need to display an error prompt message; otherwise, the error message returned by the backend needs to be displayed and the save button needs to be disabled. After verification is successful, request to modify the product information interface. Therefore, there is a sequence between these two methods. And the out-of-focus event must request the sensitive word interface first, and the request to modify product information must be after the sensitive word interface request is completed. We cannot allow illegal sensitive words to be successfully saved and rendered due to slow sensitive word detection. At this time, it is unnecessary to request the sensitive word detection API. Since it is impossible to determine and guarantee the two interfaces, a variable needs to be added to determine whether the sensitive word interface request has ended. If the interface has not completed the request, you need to re-initiate the request in the click event; if the interface has completed the request, just return and ignore it.

Ideas:

  • Add a focus loss event to the input box;
  • Add a click event for the Save button.

Code:

<div class="edit-title">Product Title</div>
 <el-input
   v-model="productName"
   placeholder="Please enter the product title"
   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">Save</el-button>
 data() {
   return {
     showMessage: false,
     productName: '',
     errorMessage: '',
     timer: -1,
     hasVerified: false
   }
 },
 methods: {
  //Out of focus event (request sensitive word detection interface)
   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
   },
   //Click event (request to modify product information interface)
   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: 'Product modification successful! '
         })
       })
       .catch((message) => {
         this.$message({
           type: 'error',
           message
         })
       })
     this.showEditProductDialog = false
   }
 }

Idea 3: Use mixins to extract sensitive word detection method

I thought that sensitive word detection had been abandoned by me, but then I received a product message that I also needed to add sensitive word detection to the product title of the custom module. After that, I pressed ctrl+c and ctrl+v like a tiger, and finally found that the code was too redundant and needed to be sorted out. Here and in the following, we will only write about the sensitive word detection logic of the product module. The sensitive word detection logic of the custom module is actually similar to that of the product module. Since the style and logic of the product title editing in the custom module are almost the same as those in the product module, why not extract the public method for sensitive word detection? I happily decided on this, and after a lot of typing on the keyboard, the mixin method was formed:

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">Product Title</div>
<el-input
    v-model="productName"
    placeholder="Please enter the product title"
    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">Save</el-button>
import inspectSpams from '@/mixins/inspectSpams'

export default {
     data() {
          return {
              productName: ''
          }
      },
      mixins: [ inspectSpams ],
      methods: {
        //Click event (request to modify product information interface)
        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: 'Product modification successful! '
              })
            })
            .catch((message) => {
              this.$message({
                type: 'error',
                message
              })
            })
          this.showEditProductDialog = false
        }
      }
}

Idea 4: Use promise to encapsulate sensitive word detection components (demand-oriented v1)

Considering that the HTML structure of the product module sensitive word detection and the custom module are almost the same, it is decided to encapsulate a sensitive word detection component and put the HTML code and business logic of the product title sensitive word detection together. But in this process, there are three issues that need special attention:

Note:

  • The async function returns a promise object;
  • The props value passed in cannot be modified directly, but the props value can be modified indirectly by binding the intermediate variable to the props bidirectionally through the intermediate variable;
  • You can add a sync modifier to props in the parent component and monitor props and intermediate variables in the child component. If the value of either party changes, the changed value will be assigned to the other party, thus achieving the purpose of two-way binding.

Ideas:

  • Write a sensitive word detection component;
  • Introduce sensitive word detection component.
//Sensitive word detection component <template>
    <div>
        <el-input v-model="input" placeholder="Please enter the product title" 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 = 'Please enter the product name'
            }
            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>
//Introduce sensitive word detection component <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: 'Product modification successful! '
           })
         })
       this.showEditProductDialog = false
       })
       .catch(()=>{
         this.$message({
           type: 'error',
           message: 'Please enter a valid product name'
         })
       })
   },
   getProductListData(status, page) {
     this.$store.dispatch('products/getList', {
       limit: 16,
       status,
       order: 'id',
       direction: 'desc',
       page
     })
   }
}
</script>

<template>
    <div>
      <div class="edit-title">Product Title</div>
      <InspectSpams 
         :title.sync="productName"
         ref="productSpamsRef"
      />
      <el-button type="primary" @click="save">Save</el-button>
    </div>
</template>

Idea 5: Use slots and mixins to encapsulate sensitive word detection components (demand-oriented v2)

Requirements changes: In fact, compared with requirement v1, there is no change. Only the product title of the product module must be filled in, otherwise the save button will be disabled. The product title of the custom module can be left blank. After saving, the default is the filled-in product title + whiteboard name.

Idea: In this case, why not put the HTML for error prompts into a component, use slots to represent the fields that need to be detected, and put the logic of sensitive word detection into mixins. If sensitive word detection is required in other places in the future, it will be more flexible. In fact, this is more conducive to the principle of component reuse.

//Sensitive word detection component <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 for sensitive word detection
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: 'Product modification successful! '
       })
     })
     .catch((message) => {
       this.$message({
         type: 'error',
         message
       })
     })
   this.showEditProductDialog = false
 },
 
<div class="edit-title">Product Title</div>
<InspectSpams :isShowMessage="isShowMessage" :errorMessage="errorMessage">
 <el-input
     v-model="productName"
     placeholder="Please enter the product title"
     type="text"
     auto-complete="on"
     clearable
     @blur="inspectSpams(productName)"
 />
</InspectSpams>

Optimization and Improvement

1. Optimize the conditions for calling sensitive word detection. If the product title has not changed, there is no need to request the sensitive word detection API. Because only titles that have been successfully verified can be successfully saved, there is no need to call the interface repeatedly. You need to modify the conditions of the mixins request interface.

Idea: In the process of opening the modal box to request the product details interface based on the product ID, assign the name field of the corresponding product information to the newly added originalName variable. When calling the inspectSpams mixin method in HTML and JS, pass originalName and productName as variables.

//Modified mixins are mixed into 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. Clicking the button multiple times will repeatedly request the interface. You can use anti-shake, button countdown, encapsulate axios request, set loading for button, etc. to optimize.

Final Thoughts

In fact, the summary is not very good, the components written are not good enough, and the ideas are not very clear. I record them here mainly to summarize ideas 2 and 4. After all, I am not very familiar with the Vue documentation. There are still many areas that can be improved in the sensitive word detection component. Please point them out in the comments.

The above is the detailed content of various ideas for writing Vue components to detect sensitive words. For more information about Vue components to detect sensitive words, please pay attention to other related articles on 123WORDPRESS.COM!

You may also be interested in:
  • 4 ways to implement sensitive word filtering in Python
  • Retrieve and output sensitive words based on Python
  • Laravel framework implements sensitive word filtering function example
  • Python uses classes to implement article sensitive word filtering method example
  • A brief discussion on the implementation of Python sensitive word filtering
  • Example of sensitive word filtering method implemented in PHP
  • How to filter sensitive words using Python regular expressions
  • Python implements sensitive word filtering example in Honor of Kings
  • Python implements sensitive word filtering method
  • js implements sensitive word filtering algorithm and implementation logic
  • Java implements DFA algorithm to filter sensitive words and advertising words

<<:  How to install ionCube extension using pagoda

>>:  Detailed steps for completely uninstalling and reinstalling MySQL under Windows 10

Recommend

Summary of Node.js service Docker container application practice

This article will not explain the use and install...

Using HTML web page examples to explain the meaning of the head area code

Use examples to familiarize yourself with the mean...

CSS3 transition to achieve underline example code

This article introduces the sample code of CSS3 t...

Eight ways to implement communication in Vue

Table of contents 1. Component Communication 1. P...

Detailed tutorial on installing CentOS, JDK and Hadoop on VirtualBox

Table of contents 1. Prerequisites 1.1 Supported ...

MySQL 5.7.21 Installer Installation Graphic Tutorial under Windows 10

Install MySQL and keep a note. I don’t know if it...

Detailed examples of variable and function promotion in JavaScript

js execution Lexical analysis phase: includes thr...

Detailed example of locating and optimizing slow query sql in MySQL

Table of contents 1. How to locate and optimize s...

Summary of MySQL view principles and usage examples

This article summarizes the principles and usage ...

JavaScript to achieve stair rolling special effects (jQuery implementation)

I believe everyone has used JD. There is a very c...

Analysis of Sysbench's benchmarking process for MySQL

Preface 1. Benchmarking is a type of performance ...

Vue v-model related knowledge summary

​v-model is a Vue directive that provides two-way...

Analysis of Mysql data migration methods and tools

This article mainly introduces the analysis of My...