前言
最近使用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 入门指南与实战案例