preface
This article mainly summarizes how to solve some practical development problems in the actual development project of VUE. You may think it is simple, but you may not have solved the idea in a short time.
Recommended reading time: 15-25 minutes
For more highlights, please follow my gold digger homepage or the Dharma soldier space blog
Common Technical answers
A characteristic style or event in the for loop for the UI style
- Judging that the UI has specific data fields (also known as the data model approach)
The data requirements are high, and you need to be able to find a good correspondence, and you need to feature component rendering for classes. When you need to change the data you can rerender it to change the style.
<li v-for="item of list" :key="item.id" :class="The item. The status? 'color':''" @click="changeColor(item.id)">{{item.name}}</li>
return {
list:[
{id:1,status:true,name:1111},
{id:2,status:true,name:222}]
}
methods:{
changeColor(id){
this.list.map((item)=>{
if(item.id==id){ item.status=! item.status; }returnitem; }}})Copy the code
- Passing in the corresponding parameters and the event source, you can change the class accordingly
The feature is more flexible, and you can also pass in whatever item attribute parameter you want to match the class, without changing the data structure returned by the interface.
<li v-for="item of list" :key="item.id" @click="changeColor($event)">{{item.name}}</li>
return {
list:[
{id:1,name:1111},
{id:2,name:222}]
}
changeColor(e){
let el=e.target;
if(el.classList.contains("color")){
el.classList.remove("color")}else{
el.classList.add("color")}}Copy the code
Calculates the use of attribute methods
If your attributes depend on the part of the data, and your data corresponding to the field is not declared in the data, only in the interface request to specify the value, then when the interface request, although the data changes, but the value of the attributes will not be updated.
Solution: Requires you to declare in data the fields on which the attribute depends, even if it is null or null
The event execution sequence is faulty
Problem description: the input box blur is defined, and then the button click event, where the default click, the order of execution is blur first followed by click. If you want the scene to click without blur events
Solution:
1 general solution: you need to change click events to @mousedown.prevent, which makes clicks better than Blur to execute, and prevents Blur from executing
2 el-Input does not take effect. It is possible to delay the execution of the event timer with a timer that loses focus and then click on the event to clear the timer. It is also possible to execute the click event logic only
The component is not updated when routing parameters change
Problem description: Route parameters change, but the component is not updated, mainly because the general obtain parameter is written in the created route hook function, when the route parameters change, the life cycle will not be re-executed.
Solution: Watch listens to the Router
Watch: {// Method 1'$route'(to, from) {// Listen for route changesif(this.$route.params.articleid){// Determine the change of the passed value // obtain the article data}} // Method 2'$route'(to, from) {
if (to.path == "/page") {/// Listen for route name. Listen for what route you jump from. Message = this.$route.query.msg
}
}
}
Copy the code
Using this in an asynchronous function cannot point to a Vue instance object
Problem description: Using traditional func in a timer or other asynchronous function causes this to not point to the vue instance. The main reason is that this points to the problem. For details, see my article “Amazing This”.
Solution: Use the arrow function or assign the variable to this (note other places where the arrow function cannot be used)
The timer is still running after the component is destroyed
Problem description: Some performance intensive timers or animations execute after component destruction, resulting in poor performance.
Solution: Destroy the timer or some animation js during the lifecycle of the destruct component
// The hook function executed before the component is destroyed is used in the same way as any other lifecycle hook function.beforeDestroy(){// I usually putsetThe Interval() timer is assigned to this instance and can then be stopped as follows. clearInterval(this.intervalId); },Copy the code
An error is reported because the case of the component name is inconsistent with that of the imported component
Problem description:
This can lead to unexpected behavior when compiling on a filesystem with other case-semantic.
Use equal casing. Compare these module identifiers:
Copy the code
Solution: You need to strictly match the case of components to avoid low-level errors
Dynamically added DOM has no style
We know that all styles in the style are scoped, so that the style in the template dom is scoped. However, the final style is not the name of the style we wrote, but the encoded style, so the DOM structure style we concatenated in the JS does not take effect.
1. When the added part of the style is not too much and is loaded dynamically, you can set it to non-scopred
2. Place the styles used to add the DOM section in the unscoped styles TAB
3 will add the part, if necessary, can write another page split vUE component
Extensions: Other UI framework styles introduced in the project, if you want to override changes, also need to be unscoped. If you want to override the entire project, you can override them by defining customer-element. SCSS in SRC /styles.
Data is directly modified in VUE, and the page view is not updated
In general, views and data are bi-directional, but sometimes when you modify an array or object value of data, the view is not updated.
data() {// data Datareturn{arr: [1,2,3], obj:{a: 1, b: 2}}; }, // The data update array view is not updated this.arr[0] ='OBKoro1'; this.arr.length = 1; console.log(arr); / / /'OBKoro1']; // The data update object view is not updated this.obj.c ='OBKoro1';
delete this.obj.a;
console.log(obj); // {b:2,c:'OBKoro1'}
Copy the code
Solution: Because of js restrictions, Vue cannot detect changes to the above array, as well as the addition/removal of objects, many people will have the problem that the view is not updated because of such operations as above.
1 this.$set(array/object you want to change, position /key you want to change, value you want to change)
this.$set(this.arr, 0, "OBKoro1"); // Change the array this.$set(this.obj, "c"."OBKoro1"); // Change the objectCopy the code
2 array native methods trigger view updates: splice(), push(), pop(), shift(), unshift(), sort(), reverse() Splice is recommended for better customization because Slice can be deleted or added anywhere in an array
Let’s say you want to walk through the array/object, process each element, and trigger the view update.
Example 1.items = example1.items.filter(example1.items = example1.items.filter(example1.items = example1.items.filter)function (item) {
return item.message.match(/Foo/)
})
Copy the code
- Codepen address, you can reproduce the problem
Requires mindless repetition of something
<div v-for="n in 5"<span style = "box-sizing: border-box; color: RGB (74, 74, 74); line-height: 22px; font-size: 14px! Important; white-space: inherit! Important;"Copy the code
Babel – plugin – transform – use the runtime
- The problem: The plug-in is compatible with and converts most es6 syntax, but some of the syntax is also unconvertible or has specific problems.
- When a component is loaded asynchronously, polyfill code is redundant
- Polyfills for global functions and instance methods are not supported. Global functions (e.g., Promise, Set, Map) are not supported, and the Set and Map data structures should not be used much. But Promise may have a bigger impact. Instance methods (e.g. ‘ABC ‘.include(‘b’), [‘1’, ‘2’, ‘3’].find((n) => n, and so on) are not supported, and this limitation disables most strings and about half of the array’s new features. Both problems are due to the fact that babel-plugin-transform-Runtime uses a sandbox mechanism to compile our code (i.e., without modifying built-in objects in the host environment). Because asynchronous components are eventually compiled into a single file, even if the same new feature is used in multiple components (e.g., object.keys ()), there will be a polyfill copy of the new feature in each compiled file. Consider not using asynchronous loading if your project is small, but the first screen can be stressful.
- Solution: In general, the Babel-plugin-transform-Runtime will work for most requirements, but when it doesn’t, the full Babel-polyfill is recommended.
- First, remove the babel-plugin-transform-Runtime from the project and uninstall the dependency:
npm un babel-plugin-transform-runtime -D
. - Then modify the Babel configuration file
// .babelrc { //... "plugins": / / / -"transform-runtime"] / /... }Copy the code
- Then, install the Babel-polyfill dependency:
npm i babel-polyfill -D
- Finally, import in the entry file
// src/main.js import 'babel-polyfill' Copy the code
- First, remove the babel-plugin-transform-Runtime from the project and uninstall the dependency:
ES6 import reference problem
In ES6, import and export of module system USES a reference to export and import (not the simple data types), that is, if in a module defines an object and export, import when used in other modules, the imported is a variable reference (pointer), if you modify attributes of the object, will affect the use of other modules.
Typically, when the system is small, we can use json.parse (json.stringify (STR)) to simply generate a new deep copy of the data object. However, when there are many components and a high degree of reuse of data objects, it is obvious that there will be performance problems. In this case, we can consider using Immutable.
For this reason, when exporting complex data types, you need to be aware of the problems that may arise when multiple components import the same data object and modify the data.
In addition, when a module defines a variable or function that uses a let rather than const, it becomes read-only and cannot be reassigned. The effect is the same as if it were declared const.
Dynamically lazy loading of components
Background: in the new features of webpack support component of lazy loading, which means we can put this when loaded into which the part of the script to load, at the same time when the package in the project, the corresponding files will be packaged separately, for the first screen optimization and other resource loading page optimization is very good. This also requires us to introduce components as needed in each page component to improve the experience.
Problem scenario: Then the problem we need to solve is: 0 WebPack is static path parsing, it is not feasible to directly pass in variables 1 it is inconvenient to write a string of code to load components each time, whether to support writing a method to load components 2 Support to differentiate between production and development environment, because development environment using lazy loading will cause hot update, resulting in slow update, So the development environment uses full default loading, and the production environment uses lazy loading
The solution is as follows: 1 WebPack path using variable concatenation, must give a relative path in advance, and then put the specific component path in
Use an arrow function to pass in the component name or relative path that needs to be passed in
3 Use process.env.node_env to determine which loading mode to use
In the original router/index.js, define a _import method to load the component.
// router/index.js
const _import = require('./_import_' + process.env.NODE_ENV)
//使用时
{
path: '/',
name: 'HelloWorld',
component: _import('HelloWorld')
},
// router/_import_development.js
module.exports = file => require('@/views/' + file + '.vue'Module.exports = file => module. Exports = exports () => import('@/views/' + file + '.vue')
Copy the code
Data in vue must be a function
Scenario: Someone who started vUE might use data as the object type when vUE was introduced separately on the page and have no problem, but in a SPA application, an error will be reported if data in the component is an object type.
Solution: Replace data with a function that returns a key-value pair of the object type.
Development: You may know that to do so, here is a little under the science reason, mainly because the root component will only be used once, so you can use objects, and child components may be used multiple times in an application, in order to avoid multiple components using the same data influence each other, so to speak data agreed to return to function types, return to object, This ensures that the sub-components do not affect each other during data rendering.
A custom component with a parent-child tag relationship failed to render
Scenario: When customizable components, it is often necessary to encapsulate the li tag under ul and the TR td tag under TABLE as a custom component. However, if we use the custom component directly, the final generated location is not what we want. Its tag is rendered outside of the tBody tag.
Vue.component("row",{
template:'<tr><td>{{content}}</td></tr>'.data() {return {
content:'this is a row'}}})Copy the code
Solution: The reason is that HTML does tag parsing, so the tag under tBody must be tr, and so on. Then we can fix this by setting the subtag to the original tag type and using is=”selfComponent”.
<tr is="row"></tr>
- VueComponents use
Development:
- Do not render vue container elements to HTML or body, otherwise prompt:
Do not mount Vue to <html> or <body> - mount to normal elements instead.
- Make sure to bind the EL property to an HTML template tag when vue creates an instance
Ref to use
Scenarios: Although Vue does not recommend direct dom manipulation, in complex scenarios where dom manipulation is needed, you can use the REF to do it. For example, let’s take a simple example of getting a DOM node through ref and getting its contents.
Solution:
<div @click="handleClick" ref="hello">hello world
</div>
handleClick(){
console.log(this.$refs.hello)
}
Copy the code
- Scenario: Suppose we have two instances of the counter component and now need to get the sum of the two counters using ref’s scheme.
The code is as follows:
<counter ref="one" @change="handleChange"></counter>
<counter ref="two" @change="handleChange"></counter>
<span>{{total}}</span>
Vue.component("counter",{
template:"<div @click='change'>{{number}}</div>".data() {return {
number:0}
},
methods:{
change(){
this.number++;
this.$emit("change")}}}) // App parent component methodhandleChange(){
this.total=this.$refs.one.number+this.$refs.two.number
},
Copy the code
-
This.$refs.name specifies the node of the native tag if it is a native tag, and the reference to the component if it is a component.
-
VueRefDemo use
Reference documentation
- Some problems in vUE project practice
- Vue practice issues summary 001