Vue3基础入门

210 阅读3分钟

“携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第10天,点击查看活动详情

Vue3基础

选项式 API

组件的初始化还是和Vue2那样

组合式API

eg:

import { ref } from 'vue'
// ref 就是一个组合式API 
export default {
    setup(){
        const show = ref(true)
        const toggle = () => {
            show.value = !show.value
        }
        const count = ref(0)
        const increment = () => {
            count.value++
        }
        return { show,toggle,count,increment }
    }
}

setup 函数

setup 函数是 Vue3 特有的选项,作为组合式API的起点,注意以下三点:
  1. 从组件生命周期看,它在 beforeCreate 之前执行
  2. 函数中 this 不是组件实例,是 undefined
  3. 如果数据或者函数在模板中使用,需要在 setup 返回
经验:

今后在vue3的项目中几乎用不到 this

reactive 函数

1. 导入 reactive 函数
import { reactive } from 'vue'
2. 通过 reactive 函数包装成响应式对象
const obj = reactive({
    name:'zs',
    age:18
})

const btn = () => {
    obj.age++
}

3. 返回给模板使用

return { obj,btn }

组合式API-ref函数

ref 函数,可以把任意类型数据转换成响应式。

  1. vue 中导入 ref 函数
  2. setup 函数中,使用 ref 函数包装成响应式数据(不分类型)
  3. 最后 setup 函数返回一个对象,包含该响应式数据即可
❗使用 ref 的两个注意点:
  1. <script> 中需要 .value

  2. <template> 会自动解套,不需要 .value

setup 语法糖

computed 函数

  1. 导入 computed 函数 import {computed} from 'vue'

  2. 调用 computed 函数并传入一个回调函数 const computedRes = computed(() => { return xx})

  3. 函数内部记得 return 返回结果

watch 函数

watch 参数

  1. 被监听的数据

  2. 回调函数

  3. 配置项(可选)

基本写法

基础类型
import { ref,watch } from 'vue'
const money = ref(1400)
watch(money,() => {
    console.log('钱变化了', money.value)
})
复杂类型
watch(obj,() => {
    console.log('obj变化了', obj.value)
},{
    deep:true,
    immediate:true
}
     )

进阶写法

基础类型
import { ref,watch } from 'vue'
const money = ref(1400)
watch(money,(newVal,oldVal) => {
    console.log('钱变化了',newVal,oldVal)
})
复杂类型

✨通过 getters 函数写法,可以侦听对象的某个属性

✨通过数组,可同时侦听多个数据

watch(
    [()=> obj.value.age,() => obj.value.cp.age],
    (newVal,oldVal){
      console.log('obj变化了',newVal,oldVal)
    },
    {
        deep:true
    }    
)

模板ref

获取DOM元素

  1. 创建 ref const hRef = ref(null)

  2. 模板 ref 建立关联 <h1 ref="hRef"></h1>

  3. 组件挂载完毕后可以访问 DOM节点 onmounted { hRfe.value }

应用场景

//需求:获取输入框焦点
const iptRef = ref(null)

<input ref="inputRef" type="text" />
    
const focusClick = () =>{
    iptRef.value.focus()
}   

// 需求:获取输入框焦点
<audio ref="audioRef" controls>
    audioRef.value.play()

父传子

基本结构

在 script 中用defineProps获取 props

// father:
const money = ref(100)
<Children :money="money">

// son:    
<script setup>
// 在 script 中获取 props
const props = defineProps({
    money:Number,
    car:String
})

console.log('在script中获取props', props.money)
</script>

子传父 defineEmits

<ChildCom @change-money="changeMoneyFn" :money="money"></ChildCom>

定义 emit ,显式声明事件名称

const emits = defaultEmits(['changeMoney'])

const btn = () => {
    emit('changeMoney',100) // ❗注意没有 this
}

跨组件通讯

provide 提供数据

provide('count',count)

inject 获取数据

const count = inject('count')

辅助函数toRefs

const user = reactive({ name:'zg',age:80 })

const res = toRfes(user)

把 obj 的每一个属性都变成独立的 ref 对象,所以解构出来的每个属性都是响应式的 ref

const { name,age } = toRefs(user)

核心库

vue-router

基础使用

安装 npm i vue-router@4 --save

导入 创建路由实例的函数 和 创建历史模式 的函数

import { createRouter,createWebHashHistory } form 'vue-router'

// 创建路由实例

const router = createRouter({
    history:createWebHashHistory,
    routes:[]
})
export default router

挂载路由:

main.js

import router from './router'

// 以插件形式使用 router
app.use(router)

路由配置和路由组件

在路由实例的 路由表

routes: [
    { path: '/home', component: () => import('../views/HomePage.vue') },
    { path: '/login', component: () => import('../views/LoginPage.vue') },
  ],

路由链接与路由出口

<router-link> <router-view>

vue-router-组合式API

因为我们在 setup 里面没有访问 this,所以我们不能再直接访问 this.$router

或 this.$route

使用 useRouteruseRoute 函数:

import { useRouter,useRoute } from 'vue-router'

获取全局路由实例

const router = useRoute()

获取当前路由信息

const route = useRoute()

使用:

router.push('/home')

route.query/route.path/route.fullPath/route.params

pinia

基础使用

安装 npm i pinia@2 --save
main.js中使用

import { createPinia } from 'pinia'

app.use(createPinia())

pinia 的 store

三个概念,stategettersactions,可以假设这些概念相当于组件中的 data、 computed 和 methods。

✨pinia没有mutation,用起来更加方便

pinia 支持两种 API 风格:
  1. defineStore('唯一标识',选项式API配置)
  2. defineStore('唯一标识', 组合式API函数)

返回值是一个用于获取 store 的函数

建议命名规范:useXxxStore

export const useCounterStore = defineStore('counter',{
    state:() => { return { count:0 }}
})
使用
import { useCounterStore } from './store/counter'
// 调用获取 store 的函数
const counterStore = useCounterStore()

{{ counterStore.count }}

选项式API写法

state:()=>{
    return { count:100 }
}

// getters 看做 computed
  getters: {
    doubleCount() {
      // 返回计算的结果
      return this.count * 2
    },
  },
      
// 使用  {{ counterStore.doubleCount }}    
      

// actions 看做 methods,支持同步和异步,传参也很方便
  actions: {
    // 支持同步
    addCount(val) {
      this.count += val
    },
    // 支持异步
    addCountASync() {
      setTimeout(() => {
        this.count++
      }, 1000)
    },
  },
      
// 使用  @click="couterStore.addCount(10)"    

组合式API写法

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

export const useMoneyStore = defineStore('money',()=>{
    // state
    const salary = ref(1400)
    // getters
    const doubleSalary = computed(()=> saraly.value*2)
    // actions
    const addSalaryAsync = () =>{
        setTomeout(()=>{
            salary.value++
        },1000)
    }
    // actions
    const addSalary = (val)=>{
        salary.value += val
    }
    // 🚨 注意:要使用的数据或方法,记得通过 return 返回
    return {salary,doubleSalary,addSalaryAsync}
})

辅助函数storeToRefs

简化使用 store

import { storeToRefs } from 'pinia'
import { useMoneyStore } from './store/money'

const moneyStore = useMoneyStore()

❌直接解构数据会失去响应式
// const { salary,doubleSalary }  = moneyStore

✅storeToRefs 解构后还支持响应式
const { salary,doubleSalary } = storeToRefs(moneyStore)

使用:{{ salary }} {{ doubleSalary }}

合并模块管理

从合并管理的模块中导入所需的 store

src/store/index.js
export * from './counter'
export * from './money'
App.vue

import { useCounterStore,useMoneyStore } from './store'

不用分别从 ./store/counter./store/money中导入

TodoList案例

store return 回去时记得+{ } ...未完待续