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:
-
There is a lot of complex logic in templates that is not easy to maintain (expressions in templates are intended for simple calculations)
-
Duplicate code exists when there is the same logic multiple times
-
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:
- We just want to display the corresponding value on the interface, but this becomes multiple method calls
- 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