今天继续和大家分享Vue2知识点
computed:
computed是 Vue 中的一种响应式特性,用于声明计算属性。它基于已有的响应式数据(如data 或props),计算并返回新的数据,具有缓存能力,从而提高性能。
- 性能优化:
computed
属性的值会被缓存,只有当它依赖的数据发生变化时才会重新计算。 - 计算属性会缓存结果,只有当依赖的响应式数据发生变化时才会重新计算。
- 如果依赖数据没有变化,访问计算属性时直接返回缓存值。
- 代码简洁:避免在模板中直接写复杂的逻辑。
- 逻辑复用:将数据处理逻辑抽离到计算属性,便于复用和维护。
<template>
<div>
<p>原始数据:{
{ num }}</p>
<p>计算属性:{
{ doubleNum }}</p>
</div>
</template>
<script>
export default {
data() {
return {
num: 5,
};
},
computed: {
// 定义一个计算属性
doubleNum() {
return this.num * 2;
},
},
};
</script>
计算属性的读写:
计算属性默认只有getter,但也可以定义setter,从而实现双向绑定。
<template>
<input v-model="fullName" />
</template>
<script>
export default {
data() {
return {
firstName: "John",
lastName: "Doe",
};
},
computed: {
fullName: {
get() {
return `${this.firstName} ${this.lastName}`;
},
set(value) {
const parts = value.split(" ");
this.firstName = parts[0] || "";
this.lastName = parts[1] || "";
},
},
},
};
</script>
watch:
数据监听和响应:
最常见的使用场景是当某个数据发生变化时,需要执行一些逻辑,例如发送网络请求、更新另一个数据或执行一些计算操作。
export default {
data() {
return {
searchText: '',
searchResults: []
};
},
watch: {
searchText(newValue) {
// 当 searchText 发生变化时,发起网络请求
this.fetchSearchResults(newValue);
}
},
methods: {
async fetchSearchResults(query) {
// 发送网络请求
const results = await fetch(`/api/search?query=${query}`);
this.searchResults = await results.json();
}
}
};
深度监听:
当要观察的数据是一个对象或数组时,默认情况下,
watch
只会观察到对象或数组的引用是否发生变化,而不会观察对象或数组内部元素的变化。如果需要深度观察对象或数组内部元素的变化,可以使用deep:true。
export default {
data() {
return {
user: {
name: '',
age: 0
}
};
},
watch: {
user: {
handler(newValue, oldValue) {
console.log('user 对象发生了变化');
},
deep: true
}
}
};
computed和watch的区别:
computed
:
- 主要用于计算属性,根据依赖的数据自动计算出新的值。
- 计算属性是基于它们的依赖进行缓存的,只有依赖的数据发生变化时才会重新计算。
- 适合于根据其他数据计算出一个新的值,例如根据
firstName
和lastName
计算出fullName
。watch:
- 主要用于观察数据的变化并执行相应的操作。
- 更侧重于执行一些异步或复杂的逻辑,例如发送网络请求、修改其他数据等
store:
store 是 Vuex 的核心概念。它本质上是一个容器,应用里的大部分状态(state)都存于其中。可以把 store 视作一个全局的状态仓库,所有组件都能够对其中的数据进行访问和修改。不过,在进行修改操作时,需要遵循特定的规则和流程,这样做是为了确保状态具备可预测性与可维护性
state:
state是一个单一的对象,它包含了应用中所有需要共享的状态数据。在 Vuex 的设计理念里,整个应用的状态集中存放在
state
中,使得数据的管理和维护更加方便和可预测。
定义:
在创建 Vuex store 时,可以通过 state
选项来定义应用的初始状态。以下是一个简单的示例:
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
// 创建一个新的 store 实例
const store = new Vuex.Store({
state: {
count: 0,
message: 'Hello Vuex!'
}
});
export default store;
在这个例子中, state 对象包含了两个状态属性 :count 和message。
在组件中访问:
在 Vue 组件中,可以通过 this.$store.state 来访问 store 中的状态。以下是一个组件中使用state的示例:
<template>
<div>
<p>Count: {
{ count }}</p>
<p>Message: {
{ message }}</p>
</div>
</template>
<script>
export default {
computed: {
count() {
return this.$store.state.count;
},
message() {
return this.$store.state.message;
}
}
};
</script>
这里使用计算属性来获取state中的数据,这样可以在数据发生变化时自动更新视图。
使用辅助函数:
为了简化在组件中访问state的代码,Vuex 提供了mapState辅助函数。以下是使用mapState的示例:
<template>
<div>
<p>Count: {
{ count }}</p>
<p>Message: {
{ message }}</p>
</div>
</template>
<script>
import { mapState } from 'vuex';
export default {
computed: {
...mapState(['count', 'message'])
}
};
</script>
mapState函数接受一个数组或对象作为参数,返回一个计算属性对象。使用扩展运算符...将其展开到组件的computed选项中。
mutations:
在 Vuex 的架构中,state是存储应用状态的容器,而mutations则是唯一可以修改 state的途径。mutations本质上是一些同步的方法,之所以强调同步,是因为这样可以方便地追踪 state的变化,保证状态修改的可预测性。
定义:
在创建 Vuex store 时,可以通过 mutations选项来定义一系列的 mutations。每个 mutation都是一个函数,它接收两个参数:第一个参数是 state对象,也就是当前的状态;第二个参数是payload,即传递给这个 mutation的额外数据。
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state, payload) {
// 修改 state 中的数据
state.count += payload || 1;
},
decrement(state) {
state.count--;
}
}
});
export default store;
在上述代码中,定义了两个 mutations: increment 用于增加 count 的值,decrement 用于减少 count 的值。increment 函数接收一个可选的 payload 参数,如果传递了该参数,则将 count 增加相应的值;如果没有传递,则默认增加 1。
在组件中访问:
increment可以带参数,但是decrement不可以
<template>
<div>
<p>Count: {
{ count }}</p>
<button @click="incrementCount">增加</button>
<button @click="decrementCount">减少</button>
<button @click="incrementByFive">增加 5</button>
</div>
</template>
<script>
export default {
computed: {
count() {
return this.$store.state.count;
}
},
methods: {
incrementCount() {
// 触发 increment mutation
this.$store.commit('increment');
},
decrementCount() {
// 触发 decrement mutation
this.$store.commit('decrement');
},
incrementByFive() {
// 传递 payload 触发 increment mutation
this.$store.commit('increment', 5);
}
}
};
</script>
使用辅助函数:
为了简化在组件中触发mutations 的代码,Vuex 提供了mapMutations辅助函数。以下是使用 mapMutations 的示例:
<template>
<div>
<p>Count: {
{ count }}</p>
<button @click="increment">增加</button>
<button @click="decrement">减少</button>
</div>
</template>
<script>
import { mapMutations } from 'vuex';
export default {
computed: {
count() {
return this.$store.state.count;
}
},
methods: {
...mapMutations(['increment', 'decrement'])
}
};
</script>
在 Vuex 中,action 是用于处理异步操作的重要概念,它和 mutations配合,使得我们可以更灵活地管理应用的状态。下面从多个方面详细介绍 action。
action:
mutations只能进行同步操作,因为只有这样才能保证状态变化的可追踪性。但在实际开发中,很多时候需要进行异步操作,比如发送网络请求、设置定时器等,这时就需要用到 action
。
action可以包含任意异步操作,并且通过触发 mutations来间接修改 state。
定义:
在创建 Vuex store 时,可以通过 actions选项来定义一系列的 actions。每个 action都是一个函数,它接收一个上下文对象 context 作为第一个参数,这个 context 对象包含了和 store 实例几乎相同的方法和属性,例如commit(用于触发mutations)、state(当前状态)、getters等;第二个参数是payload,即传递给这个 action的额外数据。
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++;
}
},
actions: {
incrementAsync(context) {
// 模拟异步操作,例如网络请求
setTimeout(() => {
// 触发 mutations 来修改 state
context.commit('increment');
}, 1000);
},
incrementByAmount(context, payload) {
setTimeout(() => {
for (let i = 0; i < payload; i++) {
context.commit('increment');
}
}, 1000);
}
}
});
export default store;
在上述代码中,定义了两个 actions:incrementAsync用于异步增加 count 的值,通过setTimeout 模拟了一个 1 秒后的异步操作,然后触发 increment mutation;incrementByAmout 接收一个 payload 参数,用于指定要增加的次数,同样在 1 秒后多次触发increment mutation
在组件中访问:
在组件中,可以使用 this.$store.dispatch 方法来触发 actions。
<template>
<div>
<p>Count: {
{ count }}</p>
<button @click="incrementAsync">异步增加</button>
<button @click="incrementByAmount">异步增加 5</button>
</div>
</template>
<script>
export default {
computed: {
count() {
return this.$store.state.count;
}
},
methods: {
incrementAsync() {
// 触发 incrementAsync action
this.$store.dispatch('incrementAsync');
},
incrementByAmount() {
// 传递 payload 触发 incrementByAmount action
this.$store.dispatch('incrementByAmount', 5);
}
}
};
</script>
在这个组件中,通过点击不同的按钮来触发不同的 actions:incrementAsync方法触发 incrementAsync action;incrementByAmout 方法触发 incrementByAmout action并传递payload为 5。
使用辅助函数:
为了简化在组件中触发 actions的代码,Vuex 提供了mapActions 辅助函数。
<template>
<div>
<p>Count: {
{ count }}</p>
<button @click="incrementAsync">异步增加</button>
<button @click="incrementByAmount(5)">异步增加 5</button>
</div>
</template>
<script>
import { mapActions } from 'vuex';
export default {
computed: {
count() {
return this.$store.state.count;
}
},
methods: {
...mapActions(['incrementAsync', 'incrementByAmount'])
}
};
</script>
getter:
state存储着应用的状态数据,但有时候我们需要对这些数据进行一些处理或计算后再使用,这时就可以使用 getter。getter会根据 state的数据计算出一个新的值,并且具有缓存特性,只有当依赖的 state数据发生变化时,getter才会重新计算。
定义:
在创建 Vuex store 时,可以通过 getters 选项来定义一系列的 getters 。每个 getter都是一个函数,它接收 state作为第一个参数,还可以接收其他 getters 作为第二个参数,方便在 getter之间进行相互调用。
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
todos: [
{ id: 1, text: '学习 Vuex', done: true },
{ id: 2, text: '练习项目', done: false }
]
},
getters: {
// 获取已完成的 todos
finishedTodos(state) {
return state.todos.filter(todo => todo.done);
},
// 获取已完成 todos 的数量,这里使用了其他 getter
finishedTodosCount(state, getters) {
return getters.finishedTodos.length;
}
}
});
export default store;
在组件中访问:
在 Vue 组件中,可以通过this.$store.getters 来访问 store 中的 getters 。
<template>
<div>
<p>已完成的 todos 数量: {
{ finishedTodosCount }}</p>
<ul>
<li v-for="todo in finishedTodos" :key="todo.id">{
{ todo.text }}</li>
</ul>
</div>
</template>
<script>
export default {
computed: {
finishedTodos() {
return this.$store.getters.finishedTodos;
},
finishedTodosCount() {
return this.$store.getters.finishedTodosCount;
}
}
};
</script>
这里使用计算属性来获取 getters 中的数据,这样可以在数据发生变化时自动更新视图。
使用辅助函数:
为了简化在组件中访问getters 的代码,Vuex 提供了mapGetters 辅助函数。
<template>
<div>
<p>已完成的 todos 数量: {
{ finishedTodosCount }}</p>
<ul>
<li v-for="todo in finishedTodos" :key="todo.id">{
{ todo.text }}</li>
</ul>
</div>
</template>
<script>
import { mapGetters } from 'vuex';
export default {
computed: {
...mapGetters(['finishedTodos', 'finishedTodosCount'])
}
};
</script>
mapGetters 函数接受一个数组或对象作为参数,返回一个计算属性对象。使用扩展运算符 ...
将其展开到组件的 computed 选项中。