Pits encountered in vuex data changes in vuex and pages in components are not rendered

  • 2021-09-20 19:26:03
  • OfStack

vuex data changes, pages in components are not rendered

I believe many vuex novices will encounter such problems:

After the vuex data is updated, the place where the data is used in the plug-in is not updated

Such code


data() {
 return {
  tableData: this.$store.state.AdminInfo
 };
 }

Then use tableData in template


<el-table :data="tableData" class="tablePst">
 <el-table-column label=" Login name " prop="loginname"></el-table-column>
 <el-table-column label=" Real name " prop="realname"></el-table-column>
</el-table>

In this case, there will be a problem that the data changes are not rendered

Problem

To solve the problem, we must understand the life cycle of vue. Before the page is loaded, tableData obtains the value in store and assigns it to itself, so that tableData only has an initial value of 1. After the state changes in vuex, it will not be assigned to tableData again. Unless the page is refreshed and reloaded, and the component life cycle starts again, we can get the latest value

Solve

1. Remove the status of tableData in the component and use $store. state. AdminInfo directly in the template so that you can get the latest status value at any time


<el-table :data="$store.state.AdminInfo" class="tablePst">
 <el-table-column label=" Login name " prop="loginname"></el-table-column>
 <el-table-column label=" Real name " prop="realname"></el-table-column>
</el-table>

2. Use mapState, expose the state in vuex to the component, and then use it. See the official document of vuex mapState for details.

Additional knowledge: Solve the problem that vue modifies data pages without re-rendering (Vue does not refresh views after arrays and objects are changed)

The Rendering Mechanism of vue and Several Methods to Solve the Problem of No Refresh of Data Modified Page

This article does not talk about the principle, only talks about dry goods easy to understand and learn, (feeling can learn knowledge, trouble to this site to a praise! )

First of all, the bottom layer of vue is to pass data objects and use Object. definePropety to convert them into getter and setter, so vue does not support IE8.

1. Briefly introduce Object. definePropety under 1,

Object.defineProperty(obj, prop, descriptor)

//Parameters

obj

The object on which to define the property.

prop

The name of the property to define or modify.

descriptor

Attribute descriptors to be defined or modified


var obj = {}
 Object.defineProperty(obj, 'name', {
  get: function() {
   console.log(' My name is '+name);
   return name;
  },
  set: function(value) {
   console.log(' Your name is '+value)
   name = value;
  }
 });
  obj.name =' Zhang 3';// Your name is Zhang 3
  obj.name// My name is Zhang 3

From the above, we can simply find out. When we assign a value to the name attribute of this object, the set method will be triggered, and the get method will be triggered when the name attribute is obtained.

2. Therefore, the attributes written in data in vue can be converted into getter and setter, and in other words, they are responsive. Other data defined outside data are unresponsive rendering, which means that the page will not be refreshed if the data is changed. Therefore, the data to be rendered on the page must be written in data,

What is not required can be defined on this.


var vm = new Vue({
 data:{
  a:1
 }
})

// `vm.a`  Is responsive 

vm.b = 2
// `vm.b`  Non-responsive 

3. After a brief introduction, let's list a few examples that are not refreshed. Of course, the above is also one

Type 1: Modify a 1 attribute of an object

vue will only change attributes that have been declared in data into responses, and those that have not been declared will not respond


<template>
 <div>
   <div v-for='item in list'>{{item}}</div>
   <button @click='click'> Change </button>
   <button @click='hadelClick'> Solution </button>
 </div>
</template>
<script>
 export default({
  data(){
   return{
    list:{a:'a',b:'b'},
   }
  },
  methods: {
     click() {
     //  Undeclared Do Not Trigger Rendering 
      this.list.c='c'

     },
     hadelClick(){
      //  Solution, use vue Offered $set Method to trigger rendering 
      this.$set(this.list,'d','d')
     }
    }
 })  
</script>

Of course, if we want to add more than one attribute, we can use Object. assign () to copy the values of all enumerable attributes from one or more source objects to the target object and return the target object. (Simply put, it is merged into the first parameter)

this.list = Object.assign({},this.list,{c:'c',d:'d'})

Type 2: Modify a 1 attribute of an array object


<template>
 <div>
   <div v-for='item in list'>{{item.a}}</div>
   <button @click='click'> Change </button>
   <button @click='hadelClick'> Solution </button>
 </div>
</template>
<script>
 export default({
  data(){
   return{
    list:[{a:'vue'},{a:'react'},{a:'js'}],
   }
  },
  methods: {
     click() {
      // Want to give this directly to a certain in the array 1 Objects are assigned directly, which cannot be rendered dynamically (that is, the data is changed and the page is not rendered) 
      this.list[0] = {a:'css'} // The page is not rendered 
      console.log(this.list) //[{a:'css'},{a:'react'},{a:'js'}]
     },
     hadelClick(){
      //  Solution, use vue Offered $set Method to trigger rendering 
      this.$set(this.list[1],'a','css')
      console.log(this.list)//[{a:'css'},{a:'css'},{a:'js'}]
     }
    }
 })  
</script>

Of course, as mentioned earlier, vue traverses the data in data, transforming objects into setter and getter. So the array is no exception, so the above operation

Change to:


click(){
 this.list[0].a = css // Can still trigger setter . Realize data re-rendering 
  }
}

In vue is more array operations do not refresh, one is through index assignment, one is to modify the length of the array, how to solve it?

vue officially gave the method

Array of API, which can change the original array can trigger updates;

1. push ()

2. pop ()

3. shift ()

4. unshift ()

5. splice ()

6. sort ()

7. reverse ()

The second is to return a new array, which has changed fundamentally in the reference address, so the assignment operation can trigger the update (this is the idea of dealing with non-refresh, that is, changing the reference address and re-assigning to trigger the update)

Simply put, API with arrays directly receives the changed array with the original array.


<template>
 <div>
   <div v-for='item in list'>{{item.a}}</div>
   <button @click='click'> Change the original array </button>
   <button @click='hadelClick'> Do not change the original array </button>
 </div>
</template>
<script>
 export default({
  data(){
   return{
    list:[{a:'vue'},{a:'react'},{a:'js'}],
   }
  },
  methods: {
     click() {
      // Change the array refresh page 
       this.list.push({a:'css'})
     },
     hadelClick(){
    // Re-assign to refresh the page    
      this.list = this.list.map(item=>{
         item.a = 'css'
         return item
        })
    }
 })  
</script>

Finally, provide solutions (if none of the above can be done)

Objects and arrays are passed by reference. To become a new array to accept, you need to change the source.

Type 1


let arr = []// New Array 
this.list.forEach(item=>{ // Array to render 
  // Perform your operation, and finally use it to put it arr Medium 
  arr.push(item)
})
this.list = arr // Equivalent to returning 1 A new array can trigger rendering 

Type 2


<el-table :data="tableData" class="tablePst">
 <el-table-column label=" Login name " prop="loginname"></el-table-column>
 <el-table-column label=" Real name " prop="realname"></el-table-column>
</el-table>
0

Of course, this is only a brief introduction. For a detailed introduction of deep copy, please Baidu yourself

If none of the above can be executed, but your data has been modified, you can use this. $forceUpdate () method (forced refresh)


<el-table :data="tableData" class="tablePst">
 <el-table-column label=" Login name " prop="loginname"></el-table-column>
 <el-table-column label=" Real name " prop="realname"></el-table-column>
</el-table>
1

Related articles: