Calculate attribute

In some cases, we may need to do some transformation of the data before display, or we may need to combine multiple data for display

Write expressions in templates

<template id="template">
  <h2>{{ `${user.firstName} ---- ${user.lastName}` }}</h2>
  <h2>{{ `${user.firstName} ---- ${user.lastName}` }}</h2>
  <h2>{{ `${user.firstName} ---- ${user.lastName}` }}</h2>
</template>

<script>
  Vue.createApp({
    template: '#template',

    data() {
      return {
        user: {
          firstName: 'Klaus',
          lastName: 'Wang'
        }
      }
    }
  }).mount('#app')
</script>
Copy the code

Disadvantages:

  1. There is a lot of complex logic in templates that is not easy to maintain (expressions in templates are intended for simple calculations)

  2. Duplicate code exists when there is the same logic multiple times

  3. When used multiple times, many operations need to be performed multiple times, there is no cache;

Implementation in Methods

<template id="template">
  <h2>{{ getFullname() }}</h2>
  <h2>{{ getFullname() }}</h2>
  <h2>{{ getFullname() }}</h2>
</template>

<script>
  Vue.createApp({
    template: '#template',

    data() {
      return {
        user: {
          firstName: 'Klaus',
          lastName: 'Wang'
        }
      }
    },

    methods: {
      getFullname() {
        return `${this.user.firstName} ---- ${this.user.lastName}`
      }
    }
  }).mount('#app')
</script>
Copy the code

Disadvantages:

  1. We just want to display the corresponding value on the interface, but this becomes multiple method calls
  2. When a method is used multiple times, there is no cache and it needs to be calculated multiple times

computed

<template id="template">
    <h2>{{ fullName }}</h2>
    <h2>{{ fullName }}</h2>
    <h2>{{ fullName }}</h2>
  </template>

  <script>
    Vue.createApp({
      template: '#template',

      data() {
        return {
         user: {
           firstName: 'Klaus',
           lastName: 'Wang'
         }
        }
      },

      computed: {
        fullName() {
          return `${this.user.firstName} ---- ${this.user.lastName}`
        }
      }
    }).mount('#app')
  </script>
Copy the code

Compute attributes VS Methods

Computed properties are cached

Evaluated properties are evaluated only when they are first called or when dependencies change

<template id="template">
<h2>{{ fullName }}</h2>
<h2>{{ fullName }}</h2>
<h2>{{ fullName }}</h2>

<h2>{{ getFullname() }}</h2>
<h2>{{ getFullname() }}</h2>
<h2>{{ getFullname() }}</h2>
</template>

<script>
  Vue.createApp({
    template: '#template',

    data() {
      return {
        user: {
          firstName: 'Klaus',
          lastName: 'Wang'
        }
      }
    },

    computed: {
      fullName() {
        return `${this.user.firstName} ---- ${this.user.lastName}`
      }
    },

    methods: {
      getFullname() {
        return `${this.user.firstName} ---- ${this.user.lastName}`
      }
    }
  }).mount('#app')
</script>
Copy the code

A computed property is essentially an object

A complete written

computed: {
  fullName: {
    set() {
      return `The ${this.user.firstName} ---- The ${this.user.lastName}`
    },

      get(v) {
        const names = v.split(The '-')
        this.firstName = names[0].trim()
        this.lastName = names[1].trim()
      }
  }
}
Copy the code
methods: {
  // When the method is written, it is the syntactic sugar that calculates the attribute, that is, only the get method is implemented, but not the set method
  getFullname() {
    return `The ${this.user.firstName} ---- The ${this.user.lastName}`}}Copy the code

watch

During development, we defined the data in the object returned by data, which is bound to the template by means of interpolation syntax and so on

When the data changes, the template is automatically updated to show the latest data

But in some cases, we want to listen for changes in the code logic and implement the corresponding processing logic,

This is where you need to use the watch listener

watch: {
  // Parameter 1: new value parameter 2: old value before modification
  fullName(newV, oldV) {
    console.log(newV, oldV)
  }
}
Copy the code

Configuration options

watch: {
  fullName: {
    // Deep listening. By default, vue only listens on reference addresses for complex data types
    // There is no way to hear when an object's properties change
    // If you want to be heard, you must use deep listen
    deep: true.// The listener executes when the corresponding value has changed after rendering
    // Set immediate to true if we want the first render to be performed immediately
    // The listener will be executed on the first render (which means oldV is undefined)
    immediate: true.handler(newV, oldV) {
      console.log(newV, oldV)
    }
  }
}
Copy the code

Other writing

String form

watch: {
  // Separate the handler function from the methods
  fullName: 'handleWatch'
},

methods: {
  handleWatch(newV, oldV) {
    console.log(newV, oldV)
  }
}
Copy the code

An array of writing

watch: {
  fullName: [
    'handlefullNameChange'.// Vue automatically iterates through the values in the array and executes, so this function can be an anonymous function
    function(newV, oldV) {
      console.log(newV, oldV)
    },

    {
      immediate: true.handler(newV, oldV) {
        console.log('immediate', newV, oldV)
      }
    }
  ]
},
Copy the code

Monitor properties

watch: {
  'user.name'(newV, oldV) {
    console.log('immediate', newV, oldV)
  }
}
Copy the code

But vue cannot listen for changes in the array object members

// The following is incorrect. The value will change, but the listener will not be triggered
watch: {
  'user[0].name'(newV, oldV) {
    console.log('immediate', newV, oldV)
  }
}
Copy the code

Deep listener

Vue.createApp({
  template: '#template'.data() {
    return {
      users: [{name:'Klaus'},
        {name:'Steven'},
        {name:'James'}}},watch: {
    users: {
      deep: true.handler(newV, oldV) {
        // oldV is meaningless in listeners that reference data types.
        // For the old and new values in the reference data type, only the assignment to the address is referenced, and no shallow or deep copy is made
        console.log(newV === oldV) // => true}}},methods: {
    handleClick() {
      this.users[0].name = 'Alex'
    }
  }
}).mount('#app')
Copy the code

$set

created() {
  // $watch is set in the same way as in the Watch Option
  // The second handler function can be the arrow function, because the outer scope is created function, the inner this is the current component data proxy object
  this.$watch('fullName'.(newV, oldV) = > console.log(newV, oldV), {
    immediate: true.deep: true})}Copy the code

Tips: vue3 has removed the listener, you can use to calculate attribute, method (defined in the component of the local methods or defined in the app. Config. GlobalProperies global method)

// Replace the filter with the calculate attribute to add ¥before the price
filterBooks() {
  return this.books.map(item= > {
    // In order to prevent the data to be presented from contaminating the old data for the actual logical judgment,
    // Shallow copies of these complex types of data are required
    const newItem = Object.assign({}, item);
    newItem.price = "Selections" + item.price;
    returnnewItem; })}Copy the code