欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 美食 > Vue学习笔记5(Vue3)

Vue学习笔记5(Vue3)

2025/2/25 15:18:43 来源:https://blog.csdn.net/2401_88410373/article/details/145638210  浏览:    关键词:Vue学习笔记5(Vue3)

Vue3学习笔记

一、create-vue搭建vue3项目

create-vue是vue官方新的脚手架工具,底层切换到了vite
步骤:

  1. 查看环境条件
    node -v版本需要在16.0及以上
  2. 创建一个vue应用

npm init vue@latest

这一指令会安装并执行create-vue
在这里插入图片描述

二、项目目录和关键文件

  • index.html提供挂载点
  • src/assets图片、样式文件的目录
  • components封装的小组件
  • App.vue中
    template和script位置调换
    template中允许有多个根元素
    使用组件时不需要注册了,引入后直接就可以使用
  • main.js
    基于crate-vue创建实例
    通过mount设置挂载点

三、组合式API

1、setup选项

  1. 执行时机早于beforecreate
  2. setup函数中获取不到this(this是undefined的)
  3. 特点:可以提供数据也可以提供函数,但是都要return才能在模板中应用
    如何化简?<script setup>语法糖简化代码 只需定义不需要reture(语法糖自动帮我们reture)

2、reactive和ref函数

(1)reactive

作用:接收对象类型数据的参数传入并返回一个响应式的对象
核心步骤:

  1. 从vue包中导入reactive函数
  2. <script setup>中执行reactive函数并传入类型为对象的初始值,并使用变量接收返回值
<script setup>import {reactive} from 'vue'const state = reactive({count:100})
</script>
(2)ref

作用:接收简单类型或者对象类型的数据传入并返回一个响应式的对象
核心步骤:

  1. 从vue包中导入ref函数
  2. <script setup>中执行ref函数并传入初始值,使用变量接收ref函数的返回值
    本质:是在原有传入数据的基础上,外层包了一层对象,包成了复杂数据类型,包成复杂类型之后再借助reactive实现的响应式,注意:脚本中访问简单的数值数据,需要通过.value,在template模板中,不需要加.value
    推荐以后声明数据统一使用ref

3、computed(计算属性)

核心步骤:

  1. 导入computed函数
  2. 执行函数在回调参数中
<script setup>import {computed} from 'vue'const computedState = computed(()=>{return 基于响应式数据做计算之后的值})
</script>

4、watch函数

作用:侦听一个或多个数据的变化,数据变化时执行回调函数

(1)侦听单个数据
  1. 导入watch函数
  2. 执行watch函数传入要侦听的响应式数据(ref对象)和回调函数
<script setup>import {watch} from 'vue'const count = ref(0)watch(count,(newValue,oldValue)=>{console.log('count发生了变化')})
</script>
(2)侦听多个数据
<script setup>import {watch} from 'vue'const count = ref(0)watch([count,name],([newCount,newName],[oldCount,oldName])=>{console.log('count发生了变化')})
</script>
(3)immediate立刻执行

一进页面立刻执行一次

<script setup>import {watch} from 'vue'const count = ref(0)watch(count,(newValue,oldValue)=>{console.log('count发生了变化')},{immediate: true})
</script>
(4)deep深度监视

一进页面立刻执行一次

<script setup>import {watch} from 'vue'const count = ref(0)watch(count,(newValue,oldValue)=>{console.log('count发生了变化')},{deep: true})
</script>

默认watch是浅层监视,即
ref(简单类型)可以直接监视,ref(复杂类型)监视不到复杂类型内部数据的变化 除非复杂类型的地址被修改

(5)精确侦听对象的某个属性

精确监听age属性

watch(()=>userInfo.value.age,(newValue,oldValue)=>{console.log(newValue,oldValue)
})

三、生命周期函数

请添加图片描述

四、父子通信

(1)父传子

步骤:1.在父组件中,以给子组件添加属性的方式传值 2.在子组件中,通过props接收(借助编译器宏)
注意:子组件中script由于写了setup。所以无法直接配置props,需要通过编译器宏

const props = defineProps({car:String,money:Number
})
(2)子传父

步骤:1.父组件中给子组件标签通过@绑定事件 2.子组件内部通过emit方法触发事件(借助编译宏)

//App.vue
<script setup>
import SonCom from '@/components/son-com.vue'
import {ref} from 'vue'
const money = ref(100)
const getMoney=()=>{money.value+=10
}
const changeFn=(newMoney)=>{money.value=newMoney
}
</script><template><div><h3>父组件 - {{ money }}<button @click="getMoney">挣钱</button>        子传父1.绑定自定义事件</h3><SonCom car="宝马车" :money="money"        父传子1.给子组件添加属性@changeMoney="changeFn"></SonCom>     子传父4.在父组件中通过@事件名监听</div>
</template>
<style scoped>
</style>//son-com.vue
<script setup>
//由于写了setup,所以无法直接配置props选项
//需要借助编译器宏,接收子组件传递的数据
const props = defineProps({        父传子2.通过编译器宏生成props方法car:String,money:Number
})
const emit = defineEmits(['changeMoney'])        子传父2.通过编译器宏生成emit方法
console.log(props);
const buy=()=>{        子传父3.触发自定义事件,传递参数emit('changeMoney',5)
}
</script><template><!-- 对于props传递过来的数据,模板中可以直接使用 --><div class="son">我是子组件 - {{ car }} - {{ money }}        父传子3.模板中可以直接使用通过props传递过来的数据/props.xxx使用<button @click="buy">花钱</button></div>
</template><style scoped>
.son {border:1px solide black;padding:30px;
}
</style>

五、模版引用

通过ref标识获取真实的dom对象或者组件实例对象
步骤:

  1. 调用ref函数生成一个ref对象
  2. 通过ref标识绑定ref对象到标签
  3. 通过ref对象.value即可访问到绑定的元素(dom必须渲染完)

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

//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)//生命周期钩子,作用是确保dom渲染完
onMounted(()=>{// console.log(inp.value)// inp.value.focus()
})const clickFn = () => {inp.value.focus()
}const testRef = ref(null)//调用ref函数生成一个ref对象
const getCom = () => {console.log(testRef.value.count)testRef.value.sayHi()
}
</script><template><div><input ref='inp' type="text"><button @click="clickFn">点击让输入框聚焦</button></div><!-- 绑定ref对象到标签 --><TestCom ref="testRef"></TestCom><button @click='getCom'>获取组件</button>
</template><style scoped></style>//test-com.vue
<script setup>
const count = 999
const sayHi = () => {console.log('打招呼')
}defineExpose({count,sayHi
})
</script><template><div>我是用于测试的组件-{{ count }}</div>
</template><style scoped></style>

六、provide和inject

作用:顶层组件向任意的底层组件传递数据和方法,实现跨层组件通信
顶层组件通过provide提供数据,底层组件通过inject获取数据

传普通数据步骤:

  1. 通过provide函数提供数据
provide('key',顶层组件中的函数)
  1. inject函数获取数据
const message = inject('key')

传响应式数据步骤:

  1. 通过provide函数提供数据
const count = ref(1000)
provide('count',count)
  1. inject函数获取数据
const count = inject('count')

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

//App.vue
const setCount=()=>{count.value++
}
provide('setCount-key',setCount)//bottom-com.vue
const setCount=inject('setCount-key')
//App.vue
<script setup>
import CenterCom from '@/components/center-com.vue'
import { provide,ref } from 'vue'
//1.跨层传递普通数据
provide('theme-color','pink')
//2.跨层传递响应式数据
const count = ref(100)
provide('count',count)setTimeout(() => {count.value=500
}, 2000)//3.跨层级传递函数=>给子孙后代传递可以修改数据的方法
provide('changeCount' , (newCount) => {count.value = newCount
})
</script><template><div><h1>我是顶层组件</h1><CenterCom></CenterCom></div>
</template><style scoped></style>//center-com.vue
<script setup>
import BottomCom from './bottom-com.vue'
</script><template><div><h2>我是中间层组件</h2><BottomCom></BottomCom></div>
</template><style scoped></style>//bottom-com.vue
<script setup>
import {inject} from 'vue'
const themeColor=inject('theme-color')
const count=inject('count')
const changeCount=inject('changeCount')
const clickFn=()=>{changeCount(10000)
}
</script><template><div><h3>我是底层组件-{{ themeColor }}-{{ count }}</h3><button @click="clickFn">更新count</button></div>
</template><style scoped></style>

七、新特性defineOptions宏

可以定义除props、emits、expose、slots之外的任意选项

<script setup>defineOptions({name:'xxx',inheritAttrs:false,...其他更多自定义属性})
</script>

八、新特性defineModel

<Child v-model=''>
等于
<Child :modelValue='' @update:modelValue=''>
//父
const txt = ref('12345')
<MyInput v-model='txt'></MyInput>
//子
const modelValue=defineModel()
<inputtype='text':value="modelValue"@input="e=>modelValue=e.target.value"

九、Pinia

1、介绍

Pinia是Vue的最新的状态管理工具,是Vuex的替代品

  1. 去掉了mutations(有state、actions(既支持同步也支持异步)、getters)
  2. 提供了符合组合式风格的API(和Vue3新语法统一)
  3. 去掉了moduls概念,每一个store都是一个独立的模块
  4. 配合TypeScript更友好

2、添加Pinia到Vue项目

  1. 使用vite创建一个空的vue3项目

npm create vue@latest

  1. 按照官方文档安装pinia到项目中
    • 安装 npm install pinia
    • 导入
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'const pinia = createPinia()
const app = createApp(App)app.use(pinia)
app.mount('#app')

3、Pinia基本语法

//counter.js
import {defineStore} from 'pinia'
//定义store
//defineStore(仓库的唯一标识,()=>{})
export const useCounterStore = defineStore('counter',()=>{    基于useCounterStore函数就可以使用defineStore仓库//声明数据 state-countconst count = ref(0)//声明操作数据的方法action(普通函数)const addCount = () => count.value++//声明基于数据派生的计算属性getters(computed)const double = computed(()=>count.value*2)//声明数据 state-msgconst msg = ref('hello pinia')return {count,addCount,double...msg,}
})
//App.vue
import {useCounterStore} from ''
const counterStore = useCounterStore() //返回一个对象
{{counterStore.count}}-{{counterStore.double}}
<button @click="counterStore.addCount">+</button>

4、action异步实现

//channels.js
import {defineStore} from 'pinia'
export const useChannelStore = defineStore('channel',()=>{//声明数据const channelList = ref([])//声明操作数据的方法const getList = async=>{//支持异步(直接写异步请求)const {data:{data}}=await axios.get('')channelList.value = data.channelsconsole.log(data.channels)}//声明getters相关return{channelList,getList}
})//App.vue
import {useChannelStore} from ''
const channelStore = useChannelStore()
<button @click='channelStore.getList'>获取频道数据</button>
<ul><li v-for='item in channelStore.channelList' :key='item.id'>{{item.name}}</li>
</ul>

5、Pinia-storeToRefs方法

不能直接对store进行解构,会丢失响应式,需要使用storeToRefs方法

import {storeToRefs} from 'Pinia'
const {count,msg}=storeToRefs(counterStore)
action可以直接解构

6、Pinia持久化

https://prazdevs.github.io/pinia-plugin-persistedstate/zh/guide/config.html
作用:操作后会将配置了持久化的数据存入本地,即刷新页面后数据也不会重置

  1. 安装

npm i pinia-plugin-persistedstate

  1. 将插件添加到pinia实例中
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)
  1. 在需要配置pinia持久化的组件中配置
import { defineStore } from 'pinia'
import { ref } from 'vue'export const useStore = defineStore('main',() => {const someState = ref('hello pinia')return { someState }},//在声明并return完后进行配置{persist: true,},
)

指定state中哪些数据需要持久化

import { defineStore } from 'pinia'export const useStore = defineStore('store', {state: () => ({save: {me: 'saved',notMe: 'not-saved',},saveMeToo: 'saved',}),persist: {pick: ['save.me', 'saveMeToo'],},
})

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词