前言
最近使用vue3重新写了项目,发现人家都配置好了,使用setup语句可以非常方便的运行各种组件和状态的管理,跟react越来越像了。
最开始参考 Vue3 setup语法糖使用简易教程(上) - 掘金 的使用说明,结合setup的语法糖,熟悉之后各种组件之间的状态同步等,都变得非常的丝滑。
以下文章都是以setup语法糖来做说明
1 2 3
| <script setup> .... </script>
|
数据相关
ref
string、array、num等对象的情况下可以直接使用ref
如果不使用 ref
会导致UI模板的template不能渲染
1 2 3 4 5 6 7
| <template> <div>{{num}}</div> </template> <script setup> import { ref } from "vue"; let num=ref(1) </script>
|
ref赋值
ref 赋值需要复制给他的 data.value
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <script setup> import { reactive,ref } from "vue";
let data = ref(1) const setData = () => { data.value = 2 }
</script>
<template> <div> this is :{{ data }} <button @click="setData">setData</button> </div> </template>
|
ref拿DOM元素
ref 需要在 onMounted生命周期之后才能正常拿到数据,并且需要用ref进行包裹,不然UI无法刷新。但是需要注意的是,你在script中使用ref定义的数据,需要使用 num.value来进行取数据。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <script setup> import { ref } from "vue";
// 这里需要定义个foo变量ref(),跟下面组件说上的ref一样的名称 const foo = ref() let data = ref(1)
const setData = () => { console.log(foo.value) }
</script>
<template> <div> this is :{{ data }} <!-- 一样的名称 foo 已经在上面定义过了 --> <button ref="foo" @click="setData">setData</button> </div> </template>
|
使用reactive定义数据
reactive的定义必须是一个对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| <script setup> import { ref, reactive } from "vue";
// 这里需要定义个foo变量ref(),跟下面组件说上的ref一样的名称
let data = reactive({ foo: "bar", });
const setData = () => { data.foo = "change" }
</script>
<template> <div> <div> this is :{{ data.foo }} </div> <!-- 一样的名称 foo 已经在上面定义过了 --> <button ref="foo" @click="setData">setData</button> </div> </template>
|
常用方法
定义和调用方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <template> <div> <button @click="setFn"></button> </div> </template> <script setup> // 以下方法都可以定义函数,按自己开发习惯定义一种即可 let setFn = ()=>{ console.log("我是匿名函数"); } function setFn(){ console.log('我是普通函数'); } </script>
|
computed使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <template> <div class="box"> <!-- 在上方调用即可,结果为169 --> {{add}} </div> </template> <script setup> import { computed, ref } from "vue"; let num1 = ref(13); let num2 = ref(13); // 设置个变量接收 let add = computed(() => { return num1.value * num2.value; });
|
watch 使用
单个watch
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <template> <div class="box"> <input type="text" v-model="user" /> </div> </template> <script setup> import { watch, ref } from "vue"; // 用户名 let user = ref(); // watch监听接收两个或者三个匿名函数,第一个是监听的数值,第二个是处理监听函数,第三个是否开启深监听(可选) watch( () => user.value, (newVal, oldVal) => { console.log("新值:" + newVal + "旧值:" + oldVal); }, // 可选项,是否开启深监听 { deep: true } ); </script>
|
多个watch
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <template> <div class="box"> <input type="text" v-model="user" /> </div> </template> <script setup> import { watch, ref } from "vue"; // 用户名 let user = ref(); // watch监听接收两个或者三个匿名函数,第一个是监听的数值,第二个是处理监听函数,第三个是否开启深监听(可选) watch( () => user.value, (newVal, oldVal) => { console.log("新值:" + newVal + "旧值:" + oldVal); }, // 可选项,是否开启深监听 { deep: true } ); </script>
|
组件相关
组件引用
1 2 3 4 5 6 7 8 9 10 11
| <template> <div class="box"> <!-- 子组件引用 --> <v-child></v-child> </div> </template> <script setup> // 引入后无需注册 import vChild from '../components/child.vue' </script>
|
defineProps传参(父传子)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| //父元素 <template> <div class="box"> <!-- 子组件引用 --> <v-child msg='我给子元素带的一段话'></v-child> </div> </template> //子元素 <template> <div class="child"> 我是子组件 </div> </template> <script setup> import {defineProps} from 'vue' // 在接收时候也得注意,vue3 props接收必须规定数据类型,如果父元素数据类型出错,那么会报错 const props = defineProps({msg:String}) console.log(props); // Proxy {msg: '我给子元素带的一段话'} </script>
|
defineEmits传值(子传父)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| //子组件 <template> <div class="child"> 我是子组件 </div> </template> <script setup> import {defineEmits,onMounted} from 'vue' const emit = defineEmits() onMounted(()=>{ emit('getChildMsg','我是子元素,给父元素传的话') }) </script>
//父组件 <template> <div class="box"> <!-- 接收子组件的方法 --> <v-child @getChildMsg="getMsg"></v-child> </div> </template> <script setup> // 引入后无需注册 import vChild from "../components/child.vue"; let getMsg = e => { console.log(e); //我是子元素,给父元素传的话 }; </script>
|
defineExpose(父拿子方法)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| //子组件 <template> <div class="child"> {{val}} </div> </template> <script setup> import {ref,defineExpose} from 'vue' let val = ref('我是子组件') let fn = ()=>{ val.value='我改变了子组件' } // 暴露val和fn defineExpose({ val,fn }) </script> //父组件 <template> <div class="box"> <!-- 接收子组件的方法 --> <v-child ref ='child'></v-child> </div> </template> <script setup> // 引入后无需注册 import vChild from "../components/child.vue"; import {ref,onMounted} from 'vue'; // 获取child实例 let child = ref() onMounted(()=>{ console.log(child.value.val);//直接打印:我是子组件,并不需要加.value // 执行子组件的fn函数 child.value.fn() }) </script>
|
pinia 使用 类似vux
定义一个 pinia
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', { state: () => { return { count: 0 } }, actions: { increment() { this.count++ }, }, })
|
在一个组件中使用
先实例化,再使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| <script setup> import { ref, reactive } from "vue"; import { useCounterStore } from "@/stores/maintest";
const counterStore = useCounterStore();
let data = reactive({ foo: "bar", });
const setData = () => { counterStore.count ++ }
</script>
<template> <div class="p-10"> <div> pinia: 【{{counterStore.count}}】 </div> <button ref="foo" @click="setData">setData</button> </div> </template>
|
两个组件联动
test1.vue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| <script setup> import { ref, reactive } from "vue"; import { useCounterStore } from "@/stores/maintest"; // 这里需要定义个foo变量ref(),跟下面组件说上的ref一样的名称
const counterStore = useCounterStore()
let data = reactive({ foo: "bar", });
const setData = () => { data.foo = "change" }
</script>
<template> <div class="p-10"> <div> {{counterStore.count}} </div> <div> this is :{{ data.foo }} </div> <!-- 一样的名称 foo 已经在上面定义过了 --> <button ref="foo" @click="setData">setData</button> </div> </template>
|
test2.vue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| <script setup> import { ref, reactive } from "vue"; import { useCounterStore } from "@/stores/maintest";
// 这里需要实例化一个counterStore const counterStore = useCounterStore();
let data = reactive({ foo: "bar", });
// 设置count的值 const setData = () => { counterStore.count ++ }
</script>
<template> <div class="p-10"> <div> pinia: 【{{counterStore.count}}】 </div> <button ref="foo" @click="setData">setData</button> </div> </template>
|
实时刷新
1 2
| import { useMainStore } from "@/stores/main"; const userFilterTags = computed(()=> mainStore.userFilterTags)
|
参考
Vue3 setup语法糖使用简易教程(上) - 掘金
Vue3 setup语法糖使用简易教程(下) - 掘金
介绍 | Pinia 中文文档
单组件的编写 | Vue3 入门指南与实战案例