PrefaceIn a common business scenario, we need to send a related request to obtain search data after the input in the search box is completed. Frequent event triggering will result in too frequent interface requests. Therefore, we need to limit this to prohibit unnecessary requests to avoid wasting resources~ Take a business scenario concept:Introduction to anti-shake function About addEventListener Example of use: function debounce(fn) { let timeout = null; // Create a marker to store the return value of the timer return function () { clearTimeout(timeout); // Clear the previous setTimeout every time the user enters input timeout = setTimeout(() => { // Then create a new setTimeout, so that if there is more input within the interval after the input character, the fn function will not be executed fn.apply(this, arguments); }, 500); }; } function sayHi() { console.log('Anti-shake success'); } var inp = document.getElementById('inp'); inp.addEventListener('input', debounce(sayHi)); // Anti-shake Use in vue?First, let me talk about my previous pitfalls. The following code is a simplified version of a scene function debounce(fn) { let timeout = null; // Create a marker to store the return value of the timer return function () { clearTimeout(timeout); // Clear the previous setTimeout every time the user enters input timeout = setTimeout(() => { // Then create a new setTimeout, so that if there is more input within the interval after the input character, the fn function will not be executed fn.apply(this, arguments); }, 500); }; } Wrong way of using <template> <div class="search-view"> <div class="header"> <Search class="search-box" v-model='searchValue' @input = 'getSearchResult' placeholder='Search for the good stuff you want' /> <span @click="goBack" class="cancel">Cancel</span> </div> <div class="serach-view-content" /> </div> </template> <script> import Search from './components/Search'; import debounce from './config'; export default { name: 'SearchView', components: Search }, data() { return { searchValue: '' }; }, methods: { getSearchResult() { debounce(function() { console.log(this.searchValue); })(); } } }; </script> Why is it wrong?Source code level analysis Vue template compilation parsing event export const onRE = /^@|^v-on:/ export const dirRE = /^v-|^@|^:/ function processAttrs(el) { const list = el.attrsList let i, l, name, value, modifiers for (i = 0, l = list.length; i < l; i++) { name = list[i].name value = list[i].value if (dirRE.test(name)) { // Parsing modifiers modifiers = parseModifiers(name) if (modifiers) { name = name.replace(modifierRE, '') } if (onRE.test(name)) { // v-on name = name.replace(onRE, '') addHandler(el, name, value, modifiers, false, warn) } } } } Summary: The initialization event function initEvents called during the instance initialization phase actually initializes the events triggered in the listener child component registered by the parent component using v-on or @ in the template. Vue's event mechanism Vue.prototype.$on = function(event, fn) { const vm = this; if (Array.isArray(event)) { for (let i = 0; i < event.length; i++) { this.$on(event[i], fn); } } else { //This _events attribute is used as the event center of the current instance. All events bound to this instance will be stored in the event center _events attribute. (vm._events[event] || (vm._events[event] = [])).push(fn); } return vm; }; Vue.prototype.$emit = function(event) { const vm = this; let cbs = vm._events[event]; if (cbs) { cbs = cbs.length > 1 ? toArray(cbs) : cbs; let args = toArray(arguments, 1); for (let i = 0; i < cbs.length; i++) { try { cbs[i].apply(vm, args); } catch (e) { handleError(e, vm, `event handler for "${event}"`); } } } return vm; }; The initMethods method is called in vue's initState In initMethods, hang the methods method on this for (const key in methods) { if (process.env.NODE_ENV !== 'production') { if (methods[key] == null) { warn( `Method "${key}" has an undefined value in the component definition. ` + `Did you reference the function correctly?`, vm ); } // If the name is the same as a property name in props, an exception is thrown if (props && hasOwn(props, key)) { warn(`Method "${key}" has already been defined as a prop.`, vm); } /* If a method name in methods already exists in the instance vm and the method name starts with _ or $, an exception is thrown: Prompt the user that the method name is not standardized*/ if (key in vm && isReserved(key)) { warn( `Method "${key}" conflicts with an existing Vue instance method. ` + `Avoid defining component methods that start with _ or $.` ); } // Bind method to instance vm so that we can access it through this.xxx // At the same time, if let m1 = this.xxx m1() in vue, this also points to vue vm[key] = methods[key] == null ? noop : bind(methods[key], vm); } Key points:
getSearchResult.apply(this, agrs) <===> The call of apply can be written as follows this.getSearchResult(args) // And then it becomes this execution debounce(function() { console.log(this.searchValue); })(); // Here debounce returns a function so it becomes (function (fn) { clearTimeout(timeout); // Clear the previous setTimeout every time the user enters input timeout = setTimeout(() => { // Then create a new setTimeout, so that if there is more input within the interval after the input character, the fn function will not be executed fn.apply(this, arguments); }, 500); })() // At this point, it actually becomes the self-execution of the anonymous function // Since each time the input is triggered, a new anonymous function will be returned to generate a new function execution stack, so the anti-shake function fails~ So how should we call <template> <div class="search-view"> <div class="header"> <Search class="search-box" v-model='searchValue' @input = 'getSearchResult()' placeholder='Search for the good stuff you want' /> <span @click="goBack" class="cancel">Cancel</span> </div> <div class="serach-view-content"> </div> </div> </template> <script> import debounce from 'lodash.debounce'; export default { name: 'SearchView', components: Search, }, data() { return { searchValue: '', }; }, methods: { getSearchResult:debounce(function () { console.log(this.searchValue); }, 500), }, }; </script> Analyze the execution process getSearchResult().apply(this, args) <===> Ignore parameter behavior and only focus on the execution stack let func = function () { clearTimeout(timeout); // Clear the previous setTimeout every time the user enters input timeout = setTimeout(() => { // Then create a new setTimeout, so that if there is more input within the interval after the input character, the fn function will not be executed fn.apply(this, arguments); }, 500); }; this.func(args) <===> The behavior of the subcomponent triggering the input always returns the same function body. Anti-shake is successful. Similar to addEventListener introduced at the beginning of the article SummarizeThis is the end of this article about the pitfalls of using throttling functions in Vue. For more relevant content about the pitfalls of using throttling functions in Vue, please search for previous articles on 123WORDPRESS.COM or continue to browse the related articles below. I hope you will support 123WORDPRESS.COM in the future! You may also be interested in:
|
<<: centos 7 modify sshd | prohibit root login and sshd port script definition
>>: MySQL data backup and restore sample code
1. HTML code Copy code The code is as follows: Ex...
Table of contents 1. List interface display examp...
Table of contents Three steps to operate the data...
Vue+Openlayer uses modify to modify elements. The...
Table of contents 1. Installation preparation 1. ...
This article shares the specific code of JavaScri...
Preface If we want to achieve the effect of onlin...
Development Pain Points During the development pr...
Overflow Hide It means hiding text or image infor...
This article shares the specific code of JavaScri...
Today I will share with you a neon button animati...
Hello everyone, I wonder if you have the same con...
This article summarizes various ways to implement...
Ubuntu 18.04 installs mysql 5.7 for your referenc...
Structure related tags ---------------------------...