认识Vue3

1. Vue2 选项式 API vs Vue3 组合式API

组合式API:一系列函数
在这里插入图片描述

需求:点击按钮,让数字 +1

vue2实现:

<script>
export default {
  data(){
    return {
      count:0
    }
  },
  methods:{
    addCount(){
      this.count++
    }
  }
}
</script>

vue3实现:

<script setup>
import { ref } from 'vue'
const count = ref(0)
const addCount = ()=> count.value++
</script>

对比:

在这里插入图片描述

特点:

  1. 代码量变少
  2. 分散式维护变成集中式维护

2. Vue3的优势

在这里插入图片描述

使用create-vue搭建Vue3项目

1. 认识create-vue

create-vue是Vue官方新的脚手架工具,底层切换到了 vite (下一代前端工具链),为开发提供极速响应

在这里插入图片描述

2. 使用create-vue创建项目

前置条件 - 已安装16.0或更高版本的Node.js

执行如下命令,这一指令将会安装并执行 create-vue

npm init vue@latest

在这里插入图片描述
只有ESLint选Yes,其他都选择No。

进入项目目录,执行npm install安装相关依赖
在这里插入图片描述

然后执行npm run dev启动项目,看到启动成功,发现启动非常快

在这里插入图片描述

浏览器访问: http://localhost:5173/

在这里插入图片描述

熟悉项目和关键文件

在这里插入图片描述

在这里插入图片描述

App.vue文件与之前vue2明显的区别

1、vue文件直接导入,不需要注册即可使用
2、模板template中,vue2里只能有一个根节点,vue3里可以有多个根节点

组合式API - setup选项

组合式API:一系列函数

1. setup选项的写法和执行时机

写法

<script>
  export default {
    setup(){
      
    },
    beforeCreate(){
      
    }
  }
</script>

执行时机

setup()在beforeCreate钩子之前执行,所以此时是没有this这个关键字的(vue实例还没创建好)

在这里插入图片描述

2. setup中写代码的特点

在setup函数中写的数据和方法需要在末尾以对象的方式return,才能给模版使用

<script>
  export default {
    setup(){
      const message = 'this is message'
      const logMessage = ()=>{
        console.log(message)
      }
      // 必须return才可以
      return {
        message,
        logMessage
      }
    }
  }
</script>

3. <script setup>语法糖

script标签添加 setup标记,不需要再写导出语句,默认会添加导出语句(setup语法糖里,没有this关键字了)

<script setup>
  const message = 'this is message'
  const logMessage = ()=>{
    console.log(message)
  }
</script>

组合式API - reactive和ref函数

1. reactive

接收对象类型数据的参数传入,并返回一个响应式的对象

<script setup>
 // 导入
 import { reactive } from 'vue'
 // 执行函数 传入参数 变量接收
 const state = reactive({
   msg:'this is msg'
 })
 const setSate = ()=>{
   // 修改数据更新视图
   state.msg = 'this is new msg'
 }
</script>

<template>
  {{ state.msg }}
  <button @click="setState">change msg</button>
</template>

2. ref

接收简单类型或者对象类型的数据,传入并返回一个响应式的对象

<script setup>
 // 导入
 import { ref } from 'vue'
 // 执行函数 传入参数 变量接收
 const count = ref(0)
 const setCount = ()=>{
   // 修改数据更新视图必须加上.value
   count.value++
 }
</script>

<template>
  <button @click="setCount">{{count}}</button>
</template>

3. reactive 对比 ref

  1. 都是用来生成响应式数据
  2. 不同点
    1. reactive不能处理简单类型的数据
    2. ref参数类型支持更好,但是必须通过.value做访问修改
    3. ref函数内部的实现依赖于reactive函数
  3. 在实际工作中的推荐
    1. 推荐使用ref函数,减少记忆负担

组合式API - computed

计算属性基本思想和Vue2保持一致,组合式API下的计算属性只是修改了API写法

<script setup>
// 导入
import {ref, computed } from 'vue'
// 原始数据
const count = ref(0)
// 计算属性
const doubleCount = computed(()=>count.value * 2)

// 原始数据
const list = ref([1,2,3,4,5,6,7,8])
// 计算属性list,从list里找出大于2的数据
const filterList = computed(item=>item > 2)
</script>

计算属性注意点:

  1. 计算属性里不应该有“副作用”,如异步请求、修改dom
  2. 避免直接修改计算属性的值,计算属性应该是只读的,特殊情况可以配置get、set

组合式API - watch

侦听一个或者多个数据的变化,数据变化时执行回调函数,两个额外参数:
1、immediate控制立刻执行
2、deep开启深度侦听

1. 侦听单个数据

<script setup>
  // 1. 导入watch
  import { ref, watch } from 'vue'
  const count = ref(0)
  // 2. 调用watch 侦听count的变化
  watch(count, (newValue, oldValue)=>{
    console.log(`count发生了变化,老值为${oldValue},新值为${newValue}`)
  })
</script>

2. 侦听多个数据

侦听多个数据,第一个参数可以改写成数组的写法

<script setup>
  // 1. 导入watch
  import { ref, watch } from 'vue'
  const count = ref(0)
  const name = ref('cp')
  // 2. 调用watch 侦听count和name的变化
  watch([count, name], ([newCount, newName],[oldCount,oldName])=>{
    console.log(`count或者name变化了,[newCount, newName],[oldCount,oldName])
  })
</script>

3. immediate

在侦听器创建时立即出发回调(一进页面立即执行),响应式数据变化之后继续执行回调

<script setup>
  // 1. 导入watch
  import { ref, watch } from 'vue'
  const count = ref(0)
  // 2. 调用watch 侦听变化
  watch(count, (newValue, oldValue)=>{
    console.log(`count发生了变化,老值为${oldValue},新值为${newValue}`)
  },{
    immediate: true
  })
</script>

4. deep

通过watch监听的ref对象默认是浅层侦听的,直接修改嵌套的对象属性不会触发回调执行,需要开启deep

<script setup>
  // 1. 导入watch
  import { ref, watch } from 'vue'
  const state = ref({ count: 0 })
  // 2. 监听对象state
  watch(state, ()=>{
    console.log('数据变化了')
  })
  const changeStateByCount = ()=>{
    // 直接修改不会引发回调执行
    state.value.count++
  }
</script>

<script setup>
  // 1. 导入watch
  import { ref, watch } from 'vue'
  const state = ref({ count: 0 })
  // 2. 监听对象state 并开启deep
  watch(state, ()=>{
    console.log('数据变化了')
  },{deep:true})
  const changeStateByCount = ()=>{
    // 此时修改可以触发回调
    state.value.count++
  }
</script>

精确侦听对象的某个属性

需求:在不开启deep的情况下,侦听age变化,只有age变化时才执行回调
在这里插入图片描述

组合式API - 生命周期函数

1. 选项式对比组合式

在这里插入图片描述

2. 生命周期函数基本使用

  1. 导入生命周期函数
  2. 执行生命周期函数,传入回调
<scirpt setup>
import { onMounted } from 'vue'
onMounted(()=>{
  // 自定义逻辑
})
</script>

3. 执行多次

生命周期函数执行多次的时候,会按照顺序依次执行

<scirpt setup>
import { onMounted } from 'vue'
onMounted(()=>{
  // 自定义逻辑
})

onMounted(()=>{
  // 自定义逻辑
})
</script>

组合式API - 父子通信

1. 父传子

基本思想

  1. 父组件中给子组件绑定属性
  2. 子组件内部通过props选项接收数据

由于组件使用的setup,无法直接配置props选项,需要借助编译器宏defineProps函数
在这里插入图片描述

2. 子传父

基本思想

  1. 父组件中给子组件标签通过@绑定事件
  2. 子组件内部通过 emit 方法触发事件

在这里插入图片描述

组合式API - 模版引用

概念:通过 ref标识 ,获取页面中真实的 dom对象或者组件实例对象

1. 基本使用

实现步骤:

  1. 调用ref函数生成一个ref对象
  2. 通过ref标识绑定ref对象到标签

在这里插入图片描述
案例:点击按钮让输入框聚焦

App.vue

<script setup>
import TestCom from '@/components/test-com.vue'
import { onMounted, ref } from 'vue'

// 模板引用(可以获取dom,也可以获取组件)
// 1. 调用ref函数,生成一个ref对象
// 2. 通过ref标识,进行绑定
// 3. 通过ref对象.value即可访问到绑定的元素(必须渲染完成后,才能拿到)
const inp = ref(null)

// 生命周期钩子 onMounted
onMounted(() => {
  // console.log(inp.value)
  // inp.value.focus()
})
const clickFn = () => {
  inp.value.focus()
}

// --------------------------------------
const testRef = ref(null)
const getCom = () => {
  console.log(testRef.value.count)
  testRef.value.sayHi()
}
</script>

<template>
  <div>
    <input ref="inp" type="text">
    <button @click="clickFn">点击让输入框聚焦</button>
  </div>
  <TestCom ref="testRef"></TestCom>
  <button @click="getCom">获取组件</button>
</template>

test-com.vue

<script setup>
const count = 999
const sayHi = () => {
  console.log('打招呼')
}

defineExpose({
  count,
  sayHi
})
</script>

<template>
  <div>
    我是用于测试的组件 - {{ count }}
  </div>
</template>

2. defineExpose

默认情况下在 <script setup>语法糖下组件内部的属性和方法是不开放给父组件访问的,可以通过defineExpose编译宏指定哪些属性和方法容许访问

说明:指定testMessage属性可以被访问到

在这里插入图片描述

获取模板引用的时机是什么?组件挂载完毕

defineExpose编译宏的作用是什么?显式暴露组件内部的属性和方法

组合式API - provide和inject

1. 作用和场景

顶层组件向任意的底层组件传递数据和方法,实现跨层组件通信

在这里插入图片描述

2. 跨层传递普通数据

实现步骤

  1. 顶层组件通过 provide 函数提供数据
  2. 底层组件通过 inject 函数接收数据

注意,二者的键(key)的名字要统一

在这里插入图片描述
案例

顶层组件App.vue

<script setup>
import CenterCom from '@/components/center-com.vue'
import { provide, ref } from 'vue'

// 1. 跨层传递普通数据
provide('theme-color', 'pink')

</script>

<template>
<div>
  <h1>我是顶层组件</h1>
  <CenterCom></CenterCom>
</div>
</template>

中间层组件center-com.vue

<script setup>
import BottomCom from './bottom-com.vue'
</script>

<template>
<div>
  <h2>我是中间组件</h2>
  <BottomCom></BottomCom>
</div>
</template>

底层组件bottom-com.vue

<script setup>
import { inject } from 'vue'
//接收顶层组件的数据
const themeColor = inject('theme-color')
</script>

<template>
<div>
  <h3>我是底层组件-{{ themeColor }} </h3>
</div>
</template>

3. 跨层传递响应式数据

在调用provide函数时,第二个参数设置为ref对象

在这里插入图片描述

案例

顶层组件App.vue

<script setup>
import CenterCom from '@/components/center-com.vue'
import { provide, ref } from 'vue'

// 2. 跨层传递响应式数据
const count = ref(100)
provide('count', count)

setTimeout(() => {
  count.value = 500
}, 2000)
</script>

<template>
<div>
  <h1>我是顶层组件</h1>
  <CenterCom></CenterCom>
</div>
</template>

中间层组件center-com.vue

<script setup>
import BottomCom from './bottom-com.vue'
</script>

<template>
<div>
  <h2>我是中间组件</h2>
  <BottomCom></BottomCom>
</div>
</template>

底层组件bottom-com.vue

<script setup>
import { inject } from 'vue'
//接收顶层组件的数据
const count = inject('count')

</script>

<template>
<div>
  <h3>我是底层组件-{{ count}} </h3>
</div>
</template>

4. 跨层传递方法

顶层组件可以向底层组件传递方法,底层组件调用方法修改顶层组件的数据

在这里插入图片描述

案例:底层组件调方法修改顶层组件的数据

顶层组件App.vue

<script setup>
import CenterCom from '@/components/center-com.vue'
import { provide, ref } from 'vue'

// 2. 跨层传递响应式数据
const count = ref(100)
provide('count', count)

// 3. 跨层传递函数 => 给子孙后代传递可以修改数据的方法
provide('changeCount', (newCount) => {
  count.value = newCount
})

</script>

<template>
<div>
  <h1>我是顶层组件</h1>
  <CenterCom></CenterCom>
</div>
</template>

中间层组件center-com.vue

<script setup>
import BottomCom from './bottom-com.vue'
</script>

<template>
<div>
  <h2>我是中间组件</h2>
  <BottomCom></BottomCom>
</div>
</template>

底层组件bottom-com.vue

<script setup>
import { inject } from 'vue'
//接收顶层组件的数据
const count = inject('count')

//修改顶层组件的数据
const changeCount = inject('changeCount')

const clickFn = () => {
  changeCount(1000)
}
</script>

<template>
<div>
  <h3>我是底层组件-{{ count}} </h3>
  <button @click="clickFn">更新count</button>
</div>
</template>

Vue3.3 新特性-defineOptions

背景说明:

<script setup> 之前,如果要定义 props, emits 可以轻而易举地添加一个与 setup 平级的属性。

但是用了 <script setup> 后,就没法这么干了, setup 属性已经没有了,自然无法添加与其平级的属性。


为了解决这一问题,引入了 defineProps 与 defineEmits 这两个宏。但这只解决了 props 与 emits 这两个属性。

如果我们要定义组件的 name 或其他自定义的属性,还是得回到最原始的用法——再添加一个普通的 <script> 标签。

这样就会存在两个 <script> 标签。让人无法接受。


所以在 Vue 3.3 中新引入了 defineOptions 宏。顾名思义,主要是用来定义 Options API 的选项。可以用 defineOptions 定义任意的选项, props, emits, expose, slots 除外(因为这些可以使用 defineXXX 来做到)

在这里插入图片描述

Vue3.3 新特性-defineModel

在Vue3中,自定义组件上使用v-model, 相当于传递一个modelValue属性,同时触发 update:modelValue 事件

在这里插入图片描述

我们需要先定义 props,再定义 emits 。其中有许多重复的代码。如果需要修改此值,还需要手动调用 emit 函数。

APP.vue

<script setup>
import MyInput from '@/components/my-input.vue'
import { ref } from 'vue'
const txt = ref('123456')
</script>

<template>
<div>
  <MyInput v-model="txt"></MyInput>
  {{ txt }}
</div>
</template>

my-input.vue

<script setup>
defineProps({
  modelValue: String
})
const emit = defineEmits(['update:modelValue'])
</script>

<template>
<div>
  <input 
    type="text" 
    :value="modelValue" 
    @input="e => emit('update:modelValue', e.target.value)"
  >
</div>
</template>

于是乎 defineModel 诞生了。

在这里插入图片描述

生效需要配置 vite.config.js

import { fileURLToPath, URL } from 'node:url'

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue({
      script: {
        defineModel: true
      }
    }),
  ],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  }
})

my-input.vue简化为

<script setup>
import { defineModel } from 'vue'
const modelValue = defineModel()
</script>

<template>
<div>
  <input 
    type="text" 
    :value="modelValue" 
    @input="e => modelValue = e.target.value"
  >
</div>
</template>

Pinia

什么是Pinia

Pinia是VUE的最新状态管理工具,是VueX的替代品

在这里插入图片描述
特点:

  1. 提供了更加简单的API(去掉了mutation)
  2. 提供符合,组合式风格的API(和vue3的新语法统一)
  3. 去掉了modules概念,每一个store都是一个独立的模块
  4. 配合TypeScript更加友好,提供可靠的类型推断

手动添加Pinia到vue项目

在实际开发中,关于Pinia的配置,可以在项目启动创建时自动添加,现在我们初次学习,从零开始:

  1. 使用vite创建一个空的vue3项目
npm create vue@latest

在这里插入图片描述
cd进入项目目录,安装一下依赖

npm i

在这里插入图片描述

启动查看效果

npm run dev

App.vue

<script setup>
import Son1Com from '@/components/Son1Com.vue'
import Son2Com from '@/components/Son2Com.vue'
</script>

<template>
  <div>
    <h3>
      App.vue根组件 -0
    </h3>
    <Son1Com></Son1Com>
    <Son2Com></Son2Com>
    <hr>
    
  </div>
</template>
<style scoped>

</style>

Son1Com.vue

<script setup>

</script>

<template>
  <div>
    我是Son1.vue - 0
    <button>+</button>
  </div>
</template>

<style scoped>

</style>

Son2Com.vue

<script setup>

</script>

<template>
  <div>
    我是Son2.vue - 0
    <button>-</button>
  </div>
</template>

<style scoped>

</style>

pinia基本语法

最终想达到的效果:点击加号减号时,对应的数字可以变化,且三个数字联动
在这里插入图片描述
2. 按照官网文档安装Pinia到项目中

在这里插入图片描述
找到如下操作步骤
在这里插入图片描述
然后我们开始安装依赖
在这里插入图片描述
找到main.js导包
在这里插入图片描述
上边最后一行是链式写法,也可以拆开写,如下
在这里插入图片描述

使用步骤:

  1. 定义store模块
  2. 组件里使用store

定义store,可以参考官网
在这里插入图片描述
声明数据

项目里创建store,新建src/store/counter.js

import { defineStore } from 'pinia'
import { computed, ref } from 'vue'

// 定义store
// defineStore(仓库的唯一标识, () => { ... })
export const useCounterStore = defineStore('counter', () => {
  // 声明数据 state - count
  const count = ref(100)
  // 声明数据 state - msg
  const msg = ref('hello pinia')
  
  return {
    count,
    msg,
  }
})

App.vue页面里调用上边的数据

import { useCounterStore } from '@/store/counter'

在这里插入图片描述

声明方法

src/store/counter.js

import { defineStore } from 'pinia'
import { computed, ref } from 'vue'

// 定义store
// defineStore(仓库的唯一标识, () => { ... })
export const useCounterStore = defineStore('counter', () => {

  // 声明数据 state - count
  const count = ref(100)
  
  // 声明操作数据的方法 action (普通函数)
  const addCount = () => count.value++
  const subCount = () => count.value--

  return {
    count,
    addCount,
    subCount,
  }
})

src/components/Son1Com.vue页面里调用上边的方法
在这里插入图片描述

声明基于数据派生的计算属性 getters

src/store/counter.js

import { defineStore } from 'pinia'
import { computed, ref } from 'vue'

// 定义store
// defineStore(仓库的唯一标识, () => { ... })
export const useCounterStore = defineStore('counter', () => {
  // 声明数据 state - count
  const count = ref(100)

  // 声明操作数据的方法 action (普通函数)
  const addCount = () => count.value++
  const subCount = () => count.value--

  // 声明基于数据派生的计算属性 getters (computed)
  const double = computed(() => count.value * 2)

  // 声明数据 state - msg
  const msg = ref('hello pinia')
  return {
    count,
    double,
    addCount,
    subCount,
    msg,
  }
})

src/components/Son1Com.vue页面里调用上边的double 方法
在这里插入图片描述

action异步实现

编写方式:异步action的函数写法和组件中获取异步数据的写法完全一致

需求:在Pinia中获取频道列表数据,并把数据渲染到App组件的模板中

后端接口的数据结构
在这里插入图片描述
先装axios : yarn add axios

新建仓库:src/store/channel.js

import { defineStore } from 'pinia'
import { ref } from 'vue'
import axios from 'axios'

export const useChannelStore = defineStore('channel', () => {
  // 声明数据
  const channelList = ref([])

  // 声明操作数据的方法
  const getList = async () => {
    // 支持异步
    const { data: { data }} = await axios.get('http://geek.itheima.net/v1_0/channels')
    channelList.value = data.channels
  }

  // 声明getters相关
  return {
    channelList,
    getList
  }
})

App.vue页面里调用(点击按钮获取数据)
在这里插入图片描述
由于目前数据没做渲染,所以需要打开浏览器控制台来看后台返回的数据

在这里插入图片描述
在页面里把后台数据渲染出来

<button @click="getList">获取频道数据</button>
<ul>
  <li v-for="item in channelStore.channelList" :key="item.id">{{ item.name }}</li>
</ul>

storeToRefs方法

如果是直接这样解析数据,会丢失响应式
在这里插入图片描述
使用storeToRefs来解决
在这里插入图片描述
直接解析方法与属性

在这里插入图片描述

Pinia持久化插件

官网

  1. 安装插件pinia-plugin-persistedstate
npm i pinia-plugin-persistedstate
  1. main.js 使用
import persist from 'pinia-plugin-persistedstate'
。。。。
app.use(createPinia().use(persist))
  1. store仓库中,persist: true 开启,如在store/counter.js进行持久化
    在这里插入图片描述

重启项目,点击按钮改变数据后,再刷新浏览器,发现数据是改变后的数
在这里插入图片描述
也可以在控制台看到数据,且有key和value
在这里插入图片描述
其中,key默认就是仓库store的唯一标识
在这里插入图片描述
如果想改这个key值的话,查看官网

在这里插入图片描述

如,counter.js改造如下
在这里插入图片描述
也可以修改storage,默认是localStorage,可以修改为sessionStorage
在这里插入图片描述
如果不希望整个state都持久化,只是持久化部分数据
在这里插入图片描述

个人总结

一 vue3优势

Vue2是选项式 API , Vue3是组合式API (组合式API:一系列函数)。如点击按钮,让数字加1的功能,vue2与vue3二者实现分别如下

在这里插入图片描述

二 搭建vue3项目

步骤

  1. npm init vue@latest,只有ESLint选Yes,其他都选择No。
  2. cd到目录里,执行npm install安装依赖
  3. 启动npm run dev

vue底层切换到了 vite (下一代前端工具链),为开发提供极速响应

生成的项目文件:

在这里插入图片描述

App.vue文件与之前vue2明显的区别:

  1. vue文件直接导入,不需要注册即可使用
  2. 模板template中,vue2里只能有一个根节点,vue3里可以有多个根节点

三 组合式API

组合式API-setup选项

setup()在beforeCreate钩子之前执行,所以此时是没有this这个关键字的(vue实例还没创建好)。在setup函数中写的数据和方法需要在末尾以对象的方式return,才能给模版使用。<script setup>语法糖不需要再写导出语句,默认会添加导出语句(setup语法糖里,没有this关键字了)

<script setup>
  const message = 'this is message'
  const logMessage = ()=>{
    console.log(message)
  }
</script>

组合式API - reactive和ref函数

reactive:接收对象类型数据的参数传入,并返回一个响应式的对象

<script setup>
 // 导入
 import { reactive } from 'vue'
 // 执行函数 传入参数 变量接收
 const state = reactive({
   msg:'this is msg'
 })
 const setSate = ()=>{
   // 修改数据更新视图
   state.msg = 'this is new msg'
 }
</script>

<template>
  {{ state.msg }}
  <button @click="setState">change msg</button>
</template>

ref:接收简单类型或者对象类型的数据,传入并返回一个响应式的对象

<script setup>
 // 导入
 import { ref } from 'vue'
 // 执行函数 传入参数 变量接收
 const count = ref(0)
 const setCount = ()=>{
   // 修改数据更新视图必须加上.value
   count.value++
 }
</script>

<template>
  <button @click="setCount">{{count}}</button>
</template>

推荐使用ref函数,减少记忆负担。

组合式API - computed

计算属性基本思想和Vue2保持一致,组合式API下的计算属性只是修改了API写法

<script setup>
// 导入
import {ref, computed } from 'vue'
// 原始数据
const count = ref(0)
// 计算属性
const doubleCount = computed(()=>count.value * 2)

// 原始数据
const list = ref([1,2,3,4,5,6,7,8])
// 计算属性list,从list里找出大于2的数据
const filterList = computed(item=>item > 2)
</script>
  1. 计算属性里不应该有“副作用”,如异步请求、修改dom
  2. 避免直接修改计算属性的值,计算属性应该是只读的,特殊情况可以配置get、set

组合式API - watch

<script setup>
  // 1. 导入watch
  import { ref, watch } from 'vue'
  const count = ref(0)
  // 2. 调用watch 侦听count的变化
  watch(count, (newValue, oldValue)=>{
    console.log(`count发生了变化,老值为${oldValue},新值为${newValue}`)
  })
</script>

侦听多个数据的话,第一个参数可以改写成数组的写法

immediate:在侦听器创建时立即出发回调(一进页面立即执行),响应式数据变化之后继续执行回调

deep:通过watch监听的ref对象默认是浅层侦听的,直接修改嵌套的对象属性不会触发回调执行,需要开启deep

可以配置精确侦听对象的某个属性

组合式API - 生命周期函数

vue2的选项式对比vue3的组合式

在这里插入图片描述

生命周期函数的使用

  1. 导入生命周期函数
  2. 执行生命周期函数,传入回调
<scirpt setup>
import { onMounted } from 'vue'
onMounted(()=>{
  // 自定义逻辑
})
</script>

生命周期函数执行多次的时候,会按照顺序依次执行

<scirpt setup>
import { onMounted } from 'vue'
onMounted(()=>{
  // 自定义逻辑
})

onMounted(()=>{
  // 自定义逻辑
})
</script>

组合式API - 父子通信

父传子

基本思想

  1. 父组件中给子组件绑定属性
  2. 子组件内部通过props选项接收数据

由于组件使用的setup,无法直接配置props选项,需要借助编译器宏defineProps函数

在这里插入图片描述

子传父

基本思想

  1. 父组件中给子组件标签通过@绑定事件
  2. 子组件内部通过 emit 方法触发事件

在这里插入图片描述

组合式API - 模版引用

通过 ref标识 ,获取页面中真实的 dom对象或者组件实例对象

实现步骤:

  1. 调用ref函数生成一个ref对象
  2. 通过ref标识绑定ref对象到标签

场景:点击按钮让输入框聚焦

defineExpose

默认情况下在 <script setup>语法糖下,组件内部的属性和方法是不开放给父组件访问的,可以通过defineExpose编译宏指定哪些属性和方法容许访问

获取模板引用的时机是什么?组件挂载完毕

defineExpose编译宏的作用是什么?显式暴露组件内部的属性和方法

组合式API - provide和inject

顶层组件向任意的底层组件传递数据和方法,实现跨层组件通信

  1. 顶层组件通过 provide 函数提供数据
  2. 底层组件通过 inject 函数接收数据

跨层传递普通数据、跨层传递响应式数据、跨层传递方法

四 vue3.3新特性-defineOptions

<script setup> 之前,如果要定义 props, emits 可以轻而易举地添加一个与 setup 平级的属性。但是用了 <script setup> 后,就没法这么干了, setup 属性已经没有了,自然无法添加与其平级的属性。前边的defineProps 与 defineEmits 这两个宏,只解决了 props 与 emits 这两个属性,如果我们要定义组件的 name 或其他自定义的属性,还是得回到最原始的用法——再添加一个普通的 <script> 标签。这样就会存在两个 <script> 标签。让人无法接受。

所以在 Vue 3.3 中新引入了 defineOptions 宏。顾名思义,主要是用来定义 Options API 的选项。可以用 defineOptions 定义任意的选项, props, emits, expose, slots 除外(因为这些可以使用 defineXXX 来做到)

五 Vue3.3 新特性-defineModel

在Vue3中,自定义组件上使用v-model, 相当于传递一个modelValue属性,同时触发 update:modelValue 事件

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们需要先定义 props,再定义 emits 。其中有许多重复的代码。如果需要修改此值,还需要手动调用 emit 函数。

于是乎 defineModel 诞生了。

六 Pinia

概念

Pinia是VUE的最新状态管理工具,是VueX的替代品。去掉了mutation、去掉了modules概念,每一个store都是一个独立的模块。

创建项目:

npm create vue@latest
# 。。。。。。。。。
# add Pinia选择yes
# 进入项目目录后,安装依赖
 npm i
# 启动项目
npm run dev

安装Pinia

查看官网步骤

yarn add pinia
# 或者使用 npm
npm install pinia

main.js里导入包、实例化

使用Pinia

定义store模块:src/store/counter.js,里边可以定义函数

组件里导入并使用store

action异步实现

异步action的函数写法和组件中获取异步数据的写法完全一致

组件里需要使用storeToRefs来解析pinia里的异步数据,否则会丢失数据。

Pinia持久化

安装插件:npm i pinia-plugin-persistedstate

main.js里导入使用插件

store仓库里开启持久化:如src/store/counter.js设置persist: true开启持久化,可以配置只持久化部分数据、配置持久化数据的key值、可以修改默认的localStorage为自定义的如sessionStorage

Logo

助力广东及东莞地区开发者,代码托管、在线学习与竞赛、技术交流与分享、资源共享、职业发展,成为松山湖开发者首选的工作与学习平台

更多推荐