Vue 3 部分新特性解析
1. 引言
Vue 3 引入了许多新特性和改进,使得开发更加高效和灵活。本文将深入探讨 Vue 3 的高阶部分,包括 Composition API、自定义指令、插件开发、状态管理和性能优化。
2. Composition API
2.1 引入 Composition API
Composition API 是 Vue 3 中引入的一种新的代码组织方式,它允许你更灵活地组织和复用逻辑。
2.1.1 基本用法
<template>
<div>
<p>Count: {{ count }}</p>
<button @click="increment">Increment</button>
</div>
</template>
<script>
import { ref } from 'vue';
export default {
setup() {
const count = ref(0);
const increment = () => {
count.value++;
};
return {
count,
increment
};
}
};
</script>
2.1.2 使用多个逻辑组合
<template>
<div>
<p>Count: {{ count }}</p>
<button @click="increment">Increment</button>
<p>Double Count: {{ doubleCount }}</p>
</div>
</template>
<script>
import { ref, computed } from 'vue';
export default {
setup() {
const count = ref(0);
const increment = () => {
count.value++;
};
const doubleCount = computed(() => count.value * 2);
return {
count,
increment,
doubleCount
};
}
};
</script>
2.2 生命周期钩子
在 Composition API 中,生命周期钩子以 on
开头。
<template>
<div>
<p>Component is mounted!</p>
</div>
</template>
<script>
import { onMounted } from 'vue';
export default {
setup() {
onMounted(() => {
console.log('Component is mounted!');
});
return {};
}
};
</script>
3. 自定义指令
3.1 创建自定义指令
自定义指令可以让你对 DOM 元素进行底层操作。
<template>
<div v-focus></div>
</template>
<script>
export default {
directives: {
focus: {
mounted(el) {
el.focus();
}
}
}
};
</script>
3.2 全局注册自定义指令
// main.js
import { createApp } from 'vue';
import App from './App.vue';
const app = createApp(App);
app.directive('focus', {
mounted(el) {
el.focus();
}
});
app.mount('#app');
4. 插件开发
4.1 创建插件
插件可以用来扩展 Vue 的功能。
// myPlugin.js
export default {
install(app, options) {
app.config.globalProperties.$myMethod = function (methodOptions) {
console.log(options, methodOptions);
};
}
};
4.2 使用插件
// main.js
import { createApp } from 'vue';
import App from './App.vue';
import MyPlugin from './myPlugin';
const app = createApp(App);
app.use(MyPlugin, { someOption: true });
app.mount('#app');
5. 状态管理
5.1 使用 Vuex 4
Vuex 是 Vue 的状态管理库,适用于大型应用。
5.1.1 安装 Vuex
npm install vuex@next
5.1.2 创建 Store
// store/index.js
import { createStore } from 'vuex';
export default createStore({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++;
}
},
actions: {
increment({ commit }) {
commit('increment');
}
},
getters: {
doubleCount: (state) => state.count * 2
}
});
5.1.3 使用 Store
// main.js
import { createApp } from 'vue';
import App from './App.vue';
import store from './store';
const app = createApp(App);
app.use(store);
app.mount('#app');
5.1.4 在组件中使用
<template>
<div>
<p>Count: {{ count }}</p>
<p>Double Count: {{ doubleCount }}</p>
<button @click="increment">Increment</button>
</div>
</template>
<script>
import { mapState, mapGetters, mapActions } from 'vuex';
export default {
computed: {
...mapState(['count']),
...mapGetters(['doubleCount'])
},
methods: {
...mapActions(['increment'])
}
};
</script>
5.2 使用 Pinia
Pinia 是 Vue 3 的新状态管理库,更简单易用。
5.2.1 安装 Pinia
npm install pinia
5.2.2 创建 Store
// stores/counter.js
import { defineStore } from 'pinia';
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0
}),
actions: {
increment() {
this.count++;
}
},
getters: {
doubleCount: (state) => state.count * 2
}
});
5.2.3 使用 Store
// main.js
import { createApp } from 'vue';
import App from './App.vue';
import { createPinia } from 'pinia';
const app = createApp(App);
const pinia = createPinia();
app.use(pinia);
app.mount('#app');
5.2.4 在组件中使用
<template>
<div>
<p>Count: {{ count }}</p>
<p>Double Count: {{ doubleCount }}</p>
<button @click="increment">Increment</button>
</div>
</template>
<script>
import { useCounterStore } from '../stores/counter';
export default {
setup() {
const counterStore = useCounterStore();
return {
count: counterStore.count,
doubleCount: counterStore.doubleCount,
increment: counterStore.increment
};
}
};
</script>
6. 性能优化
6.1 使用 v-once
v-once
可以用于渲染静态内容,避免不必要的更新。
<template>
<div v-once>
<p>This content will never change.</p>
</div>
</template>
6.2 使用 v-memo
v-memo
可以缓存计算属性的结果,避免不必要的重新计算。
<template>
<div v-memo="[list]">
<ul>
<li v-for="item in list" :key="item.id">{{ item.name }}</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
list: [
{ id: 1, name: 'Item 1' },
{ id: 2, name: 'Item 2' }
]
};
}
};
</script>
6.3 使用 key
key
属性可以强制 Vue 重新渲染组件。
<template>
<div>
<button @click="toggle">Toggle</button>
<component :is="currentComponent" :key="currentComponent"></component>
</div>
</template>
<script>
import ComponentA from './ComponentA.vue';
import ComponentB from './ComponentB.vue';
export default {
components: {
ComponentA,
ComponentB
},
data() {
return {
currentComponent: 'ComponentA'
};
},
methods: {
toggle() {
this.currentComponent = this.currentComponent === 'ComponentA' ? 'ComponentB' : 'ComponentA';
}
}
};
</script>
6.4 使用 keep-alive
keep-alive
可以缓存组件实例,避免重新创建和销毁。
<template>
<div>
<button @click="toggle">Toggle</button>
<keep-alive>
<component :is="currentComponent"></component>
</keep-alive>
</div>
</template>
<script>
import ComponentA from './ComponentA.vue';
import ComponentB from './ComponentB.vue';
export default {
components: {
ComponentA,
ComponentB
},
data() {
return {
currentComponent: 'ComponentA'
};
},
methods: {
toggle() {
this.currentComponent = this.currentComponent === 'ComponentA' ? 'ComponentB' : 'ComponentA';
}
}
};
</script>