VueVue3-Setup语法糖
WaterBoat<script setup></script>
是一种编译时语法糖,用于在单文件组件中使用组合式 API,如果你同时使用单文件组件和组合式 API,建议使用该语法。
它与普通语法相比,代码更加简洁、性能更加强悍、更好的 TS 支持。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <script setup> // 此处代码将会被编译为 setup 函数代码 // 也就是说此处代码将会在组件每次创建实例时执行 // 在内部声明的顶级变量和函数都可以在模板中你直接使用 const msg = "Hello Vue3 setup";
function log() { console.log(msg); } </script>
<template> <div @click="log">{{ msg }}</div> </template>
|
1 2 3 4 5 6 7 8 9 10
| <script setup> // 在此处可以直接导入外部的辅助方法在模板直接使用 import { capitalize } from "./helps";
const msg = "Hello Vue3 setup"; </script>
<template> {{ capitalize(msg) }} </template>
|
1 2 3 4 5 6 7 8 9
| <script setup> import { ref } from "vue";
const count = ref(0); </script>
<template> <div @click="count++">{{ count }}</div> </template>
|
1 2 3 4 5 6 7 8
| <script setup> // 在此处可以直接导入组件在模板中使用, 不再需要手动注册组件 import HelloWorld from "@/components/HelloWorld"; </script>
<template> <HelloWorld /> </template>
|
1 2 3 4 5 6 7 8
| <!-- src/App.vue --> <script setup> import HelloWorld from "./components/HelloWorld"; </script>
<template> <HelloWorld msg="Hello Vue script setup" /> </template>
|
1 2 3 4 5 6 7 8 9
| <!-- src/components/HelloWorld.vue --> <script setup> // 定义该组件接收的 Props // defineProps 在此处可以直接使用无需导入 defineProps({ msg: String }); </script> <template> {{ msg }} </template>
|
1 2 3 4 5 6 7 8
| <!-- src/components/HelloWorld.vue --> <script setup> // defineEmits 在此处可以直接使用无需导入 defineEmits(["delete"]); </script> <template> <button @click="$emit('delete')">delete button</button> </template>
|
1 2 3 4 5 6 7 8 9 10 11
| <!-- src/App.vue --> <script setup> import HelloWorld from "./components/HelloWorld"; function onDeleteHandler() { alert("deleted"); } </script>
<template> <HelloWorld @delete="onDeleteHandler" /> </template>
|
1 2 3 4 5 6
| <!-- src/components/HelloWorld.vue --> <script setup> const count = 0; // 定义当前组件向外暴露的数据 defineExpose({ count }); </script>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <!-- src/App.vue --> <script setup> import HelloWorld from "./components/HelloWorld"; import { ref } from "vue"; const instance = ref(null); function log() { console.log(instance.value.count); } </script>
<template> <HelloWorld ref="instance" /> <button @click="log">button</button> </template>
|
1 2 3 4 5 6 7 8 9 10
| <!-- src/components/HelloWorld.vue --> <script setup> import { useSlots, getCurrentInstance } from "vue"; // 获取组件实例 const currentInstance = getCurrentInstance(); // 获取插槽 const slots = useSlots(); // 通过 JSX 渲染模板 currentInstance.render = () => <div>{slots.default()}</div>; </script>
|
1 2 3 4 5 6 7 8 9 10
| <!-- src/App.vue --> <script setup> import HelloWorld from "./components/HelloWorld"; </script>
<template> <HelloWorld> <h1>Hello World</h1> </HelloWorld> </template>
|
1 2 3 4
| <!-- src/App.vue --> <script setup> const post = await fetch(`/api/post/1`).then((r) => r.json()); </script>
|
1 2
| yarn add pinia npm install pinia
|
1 2 3
| import { createPinia } from "pinia";
app.use(createPinia());
|
创建 store,存储状态
1 2 3 4 5 6
| import { defineStore } from "pinia";
export const useUser = defineStore("user", { state: () => ({ username: "张三" }), });
|
使用状态
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <!-- src/App.vue --> <script setup> import { useUser } from "@/stores/user"; import { storeToRefs } from "pinia";
const user = useUser(); // 以下为错误写法,状态丢失响应性 // const {username, age} = useUser();
// 以下为正确写法, 保持了数据的响应性 const { username, age } = storeToRefs(user); </script> <template> <!-- 直接获取并使用不会破坏数据响应性 --> <p>{{ user.username }}</p> <p>{{ username }}</p> </template>
|
更改状态
1 2 3 4 5 6 7 8 9 10 11
| import { defineStore } from "pinia";
export const useUser = defineStore("user", { state: () => ({ username: "张三", age: 20, hobbies: [] }), actions: { updateUsername(username) { this.username = username; }, }, });
|
1 2 3 4 5 6 7 8 9
| <!-- src/App.vue --> <script setup> import { useUser } from "@/stores/user"; const user = useUser(); </script> <template> {{ user.username }} <button @click="user.updateUsername('李四')">updateUsername</button> </template>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <!-- src/App.vue --> <script setup> import { useUser } from "@/stores/user"; const user = useUser(); </script> <template> {{ user.username }} {{ user.age }} <button @click="user.$patch({ username: '王五' })">updateUsername</button> <button @click=" user.$patch((state) => { state.hobbies.push('足球'); state.age = 30; }) " > button </button> </template>
|
重置状态
1 2 3 4 5 6 7 8 9
| <!-- src/App.vue --> <script setup> import { useUser } from "@/stores/user"; import { storeToRefs } from "pinia"; const user = useUser(); </script> <template> <button @click="user.$reset">reset</button> </template>
|
替换状态
1 2 3 4 5 6 7 8 9 10 11
| <!-- src/App.vue --> <script setup> import { useUser } from "@/stores/user"; const user = useUser(); </script> <template> {{ user.username }} {{ user.age }} <button @click="user.$state = { username: '赵六', age: 50 }"> replace state </button> </template>
|
getters,getters 就是 store 中的计算属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import { defineStore } from "pinia";
export const useUser = defineStore("user", { state: () => ({ count: 25 }), getters: { doubleCount(state) { return state.count * 2; }, doubleCountPlusOne() { console.log(this); return this.doubleCount + 1; }, }, });
|
1 2 3 4 5 6
| <!-- src/App.vue --> <script setup> import { useUser } from "@/stores/user"; const user = useUser(); </script> <template>{{ user.doubleCount }} {{ user.doubleCountPlusOne }}</template>
|
Getter 传递参数
1 2 3 4 5 6 7 8 9 10 11 12 13
| import { defineStore } from "pinia";
export const useUser = defineStore("user", { state: () => ({ count: 25 }), getters: { countPlus(state) { return (count) => state.count + count; }, }, });
|
1 2 3 4 5 6 7 8
| <!-- src/App.vue --> <script setup> import { useUser } from "@/stores/user"; const user = useUser(); </script> <template> {{ user.countPlus(5) }} </template>
|
Action
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import { defineStore } from "pinia"; import axios from "axios";
export const useUser = defineStore("user", { state: () => ({ profile: null }), actions: { async getUserInfo(id) { let { data } = await axios.get( `https://jsonplaceholder.typicode.com/users/${id}`, ); this.profile = data; }, }, });
|
1 2 3 4 5 6 7 8 9
| <!-- src/App.vue --> <script setup> import { useUser } from "@/stores/user"; const user = useUser(); </script> <template> {{ user.profile }} <button @click="user.getUserInfo(1)">getUserInfo</button> </template>
|