Vue2+Vue3 130~180集学习条记

[复制链接]
发表于 2025-9-25 17:53:39 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
Vue2+Vue3 130~180集(Vue3)学习条记

一、create-vue搭建vue3项目

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

  • 检察环境条件
    node -v版本必要在16.0及以上
  • 创建一个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选项


  • 实验机遇早于beforecreate
  • setup函数中获取不到this(this是undefined的)
  • 特点:可以提供数据也可以提供函数,但是都要return才气在模板中应用
    怎样化简?<script setup>语法糖简化代码 只需界说不必要reture(语法糖主动帮我们reture)
2、reactive和ref函数

(1)reactive

作用:吸收对象范例数据的参数传入并返回一个相应式的对象
核心步调:

  • 从vue包中导入reactive函数
  • 在<script setup>中实验reactive函数并传入范例为对象的初始值,并使用变量吸收返回值
  1. <script setup>
  2.         import {reactive} from 'vue'
  3.         const state = reactive({
  4.                 count:100
  5.         })
  6. </script>
复制代码
(2)ref

作用:吸收简朴范例大概对象范例的数据传入并返回一个相应式的对象
核心步调:

  • 从vue包中导入ref函数
  • 在<script setup>中实验ref函数并传入初始值,使用变量吸收ref函数的返回值
    本质:是在原有传入数据的底子上,外层包了一层对象,包成了复杂数据范例,包成复杂范例之后再借助reactive实现的相应式,注意:脚本中访问简朴的数值数据,必要通过.value,在template模板中,不必要加.value
    保举以后声明数据同一使用ref
3、computed(盘算属性)

核心步调:

  • 导入computed函数
  • 实验函数在回调参数中
  1. <script setup>
  2.         import {computed} from 'vue'
  3.         const computedState = computed(()=>{
  4.                 return 基于响应式数据做计算之后的值
  5.         })
  6. </script>
复制代码
4、watch函数

作用:侦听一个或多个数据的变革,数据变革时实验回调函数
(1)侦听单个数据


  • 导入watch函数
  • 实验watch函数传入要侦听的相应式数据(ref对象)和回调函数
  1. <script setup>
  2.         import {watch} from 'vue'
  3.         const count = ref(0)
  4.         watch(count,(newValue,oldValue)=>{
  5.                 console.log('count发生了变化')
  6.         })
  7. </script>
复制代码
(2)侦听多个数据
  1. <script setup>
  2.         import {watch} from 'vue'
  3.         const count = ref(0)
  4.         watch(
  5.                 [count,name],
  6.                 ([newCount,newName],[oldCount,oldName])=>{
  7.                         console.log('count发生了变化')
  8.                 }
  9.         )
  10. </script>
复制代码
(3)immediate立刻实验

一进页面立刻实验一次
  1. <script setup>
  2.         import {watch} from 'vue'
  3.         const count = ref(0)
  4.         watch(count,(newValue,oldValue)=>{
  5.                 console.log('count发生了变化')
  6.         },{
  7.                 immediate: true
  8.         })
  9. </script>
复制代码
(4)deep深度监视

一进页面立刻实验一次
  1. <script setup>
  2.         import {watch} from 'vue'
  3.         const count = ref(0)
  4.         watch(count,(newValue,oldValue)=>{
  5.                 console.log('count发生了变化')
  6.         },{
  7.                 deep: true
  8.         })
  9. </script>
复制代码
默认watch是浅层监视,即
ref(简朴范例)可以直接监视,ref(复杂范例)监视不到复杂范例内部数据的变革 除非复杂范例的地点被修改
(5)准确侦听对象的某个属性

准确监听age属性
  1. watch(()=>userInfo.value.age,(newValue,oldValue)=>{
  2.         console.log(newValue,oldValue)
  3. })
复制代码
三、生命周期函数


四、父子通讯

(1)父传子

步调:1.在父组件中,以给子组件添加属性的方式传值 2.在子组件中,通过props吸收(借助编译器宏)
注意:子组件中script由于写了setup。以是无法直接设置props,必要通过编译器宏
  1. const props = defineProps({
  2.         car:String,
  3.         money:Number
  4. })
复制代码
(2)子传父

步调:1.父组件中给子组件标签通过@绑定变乱  2.子组件内部通过emit方法触发变乱(借助编译宏)
  1. //App.vue
  2. <script setup>
  3. import SonCom from '@/components/son-com.vue'
  4. import {ref} from 'vue'
  5. const money = ref(100)
  6. const getMoney=()=>{
  7.   money.value+=10
  8. }
  9. const changeFn=(newMoney)=>{
  10.   money.value=newMoney
  11. }
  12. </script>
  13. <template>
  14.   <div>
  15.     <h3>
  16.       父组件 - {{ money }}
  17.       <button @click="getMoney">挣钱</button>
  18.     </h3>
  19.     <SonCom
  20.     car="宝马车"
  21.     :money="money"        父传子1.给子组件添加属性
  22.     @changeMoney="changeFn"></SonCom>     子传父4.在父组件中通过@事件名监听
  23.   </div>
  24. </template>
  25. <style scoped>
  26. </style>
  27. //son-com.vue
  28. <script setup>
  29. //由于写了setup,所以无法直接配置props选项
  30. //需要借助编译器宏,接收子组件传递的数据
  31. const props = defineProps({        父传子2.通过编译器宏生成props方法
  32.   car:String,
  33.   money:Number
  34. })
  35. const emit = defineEmits(['changeMoney'])        子传父2.通过编译器宏生成emit方法
  36. console.log(props);
  37. const buy=()=>{        子传父3.触发自定义事件,传递参数
  38.   emit('changeMoney',5)
  39. }
  40. </script>
  41. <template>
  42.   <!-- 对于props传递过来的数据,模板中可以直接使用 -->
  43.   <div class="son">
  44.     我是子组件 - {{ car }} - {{ money }}        父传子3.模板中可以直接使用通过props传递过来的数据/props.xxx使用
  45.     <button @click="buy">花钱</button>      子传父1.绑定自定义事件
  46.   </div>
  47. </template>
  48. <style scoped>
  49. .son {
  50.   border:1px solide black;
  51.   padding:30px;
  52. }
  53. </style>
复制代码
五、模版引用

通过ref标识获取真实的dom对象大概组件实例对象
步调:

  • 调用ref函数天生一个ref对象
  • 通过ref标识绑定ref对象到标签
  • 通过ref对象.value即可访问到绑定的元素(dom必须渲染完)
默认环境下<script setup>语法糖下组件内部的属性和方法是不开放给父组件访问的,可以通过defineExpose编译宏指定哪些属性和方法允许访问
  1. //App.vue
  2. <script setup>
  3. import TestCom from '@/components/test-com.vue'
  4. import {onMounted,ref} from 'vue'
  5. // 模版引用(可以获取dom也可以获取组件)
  6. // 1.调用ref函数,生成一个ref对象
  7. // 2.通过ref标识,进行绑定
  8. // 3.通过ref对象.value即可访问到绑定的元素(必须渲染)
  9. const inp = ref(null)
  10. //生命周期钩子,作用是确保dom渲染完
  11. onMounted(()=>{
  12.   // console.log(inp.value)
  13.   // inp.value.focus()
  14. })
  15. const clickFn = () => {
  16.   inp.value.focus()
  17. }
  18. const testRef = ref(null)//调用ref函数生成一个ref对象
  19. const getCom = () => {
  20.   console.log(testRef.value.count)
  21.   testRef.value.sayHi()
  22. }
  23. </script>
  24. <template>
  25.   <div>
  26.     <input ref='inp' type="text">
  27.     <button @click="clickFn">点击让输入框聚焦</button>
  28.   </div>
  29.   <!-- 绑定ref对象到标签 -->
  30.   <TestCom ref="testRef"></TestCom>
  31.   <button @click='getCom'>获取组件</button>
  32. </template>
  33. <style scoped>
  34. </style>
  35. //test-com.vue
  36. <script setup>
  37. const count = 999
  38. const sayHi = () => {
  39.   console.log('打招呼')
  40. }
  41. defineExpose({
  42.   count,
  43.   sayHi
  44. })
  45. </script>
  46. <template>
  47.   <div>
  48.     我是用于测试的组件-{{ count }}
  49.   </div>
  50. </template>
  51. <style scoped>
  52. </style>
复制代码
六、provide和inject

作用:顶层组件向恣意的底层组件通报数据和方法,实现跨层组件通讯
顶层组件通过provide提供数据,底层组件通过inject获取数据
传平凡数据步调:

  • 通过provide函数提供数据
  1. provide('key',顶层组件中的函数)
复制代码

  • inject函数获取数据
  1. const message = inject('key')
复制代码
传相应式数据步调:

  • 通过provide函数提供数据
  1. const count = ref(1000)
  2. provide('count',count)
复制代码

  • inject函数获取数据
  1. const count = inject('count')
复制代码
跨层通报方法
顶层组件可以向底层组件通报方法,底层组件调用方法可向顶层组件传参或修改顶层组件中的数据
  1. //App.vue
  2. const setCount=()=>{
  3.         count.value++
  4. }
  5. provide('setCount-key',setCount)
  6. //bottom-com.vue
  7. const setCount=inject('setCount-key')
复制代码
  1. //App.vue
  2. <script setup>
  3. import CenterCom from '@/components/center-com.vue'
  4. import { provide,ref } from 'vue'
  5. //1.跨层传递普通数据
  6. provide('theme-color','pink')
  7. //2.跨层传递响应式数据
  8. const count = ref(100)
  9. provide('count',count)
  10. setTimeout(() => {
  11.   count.value=500
  12. }, 2000)
  13. //3.跨层级传递函数=>给子孙后代传递可以修改数据的方法
  14. provide('changeCount' , (newCount) => {
  15.   count.value = newCount
  16. })
  17. </script>
  18. <template>
  19.   <div>
  20.     <h1>我是顶层组件</h1>
  21.     <CenterCom></CenterCom>
  22.   </div>
  23. </template>
  24. <style scoped>
  25. </style>
  26. //center-com.vue
  27. <script setup>
  28. import BottomCom from './bottom-com.vue'
  29. </script>
  30. <template>
  31.   <div>
  32.     <h2>我是中间层组件</h2>
  33.     <BottomCom></BottomCom>
  34.   </div>
  35. </template>
  36. <style scoped>
  37. </style>
  38. //bottom-com.vue
  39. <script setup>
  40. import {inject} from 'vue'
  41. const themeColor=inject('theme-color')
  42. const count=inject('count')
  43. const changeCount=inject('changeCount')
  44. const clickFn=()=>{
  45.   changeCount(10000)
  46. }
  47. </script>
  48. <template>
  49.   <div>
  50.     <h3>我是底层组件-{{ themeColor }}-{{ count }}</h3>
  51.     <button @click="clickFn">更新count</button>
  52.   </div>
  53. </template>
  54. <style scoped>
  55. </style>
复制代码
七、新特性defineOptions宏

配景:有<script setup>之前,假如要界说props、emits可以添加一个与setup平级的属性,但有了<script setup>之后,setup属性没有了就没法添加与其平行的属性了。为相识决这一题目引入了defineProps和defineEmits两个宏办理了props和emits这两个属性,但是其他的属性并没有办理。
可以界说除props、emits、expose、slots之外的恣意选项(这几个属性已经存在对应的宏函数了)
  1. <script setup>
  2.         defineOptions({
  3.                 name:'xxx',
  4.                 inheritAttrs:false,
  5.                 ...其他更多自定义属性
  6.         })
  7. </script>
复制代码
八、新特性defineModel
  1. <Child v-model=''>
  2. 等于
  3. <Child :modelValue='' @update:modelValue=''>
复制代码
原始写法:
  1. //父
  2. const txt = ref('12345')
  3. <MyInput v-model='txt'></MyInput>
  4. //子
  5. <script setup>
  6.         defineProps({
  7.                 modelValue:String
  8.         })
  9.         const emit = defineEmits(['update:modelValue'])
  10. </script>
  11. <template>
  12.         <input
  13.                 type='text'
  14.                 :value="modelValue"
  15.                 @input="e=>emit('update:modelValue',e.target.value)"
  16.         >
  17. </template>
复制代码
新版本写法:
  1. //父
  2. const txt = ref('12345')
  3. <MyInput v-model='txt'></MyInput>
  4. //子
  5. <script setup>
  6.         import { defineModel } from 'vue'
  7.         const modelValue=defineModel()
  8.         // modelValue.value可以直接修改
  9. </script>
  10.   
  11. <input
  12.         type='text'
  13.         :value="modelValue"
  14.         @input="e => modelValue = e.target.value"
  15. >
复制代码
见效必要设置 vite.config.js
  1. import { fileURLToPath, URL } from 'node:url'
  2. import { defineConfig } from 'vite'
  3. import vue from '@vitejs/plugin-vue'
  4. // https://vitejs.dev/config/
  5. export default defineConfig({
  6.   plugins: [
  7.     vue({
  8.       script: {
  9.         defineModel: true
  10.       }
  11.     }),
  12.   ],
  13.   resolve: {
  14.     alias: {
  15.       '@': fileURLToPath(new URL('./src', import.meta.url))
  16.     }
  17.   }
  18. })
复制代码
九、Pinia

1、先容

Pinia是Vue的最新的状态管理工具,是Vuex的更换品

  • 去掉了mutations(有state、actions(既支持同步也支持异步)、getters)
  • 提供了符合组合式风格的API(和Vue3新语法同一)
  • 去掉了moduls概念,每一个store都是一个独立的模块
  • 共同TypeScript更友好
2、添加Pinia到Vue项目


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

  • 按照官方文档安装pinia到项目中

    • 安装  npm install pinia
    • 导入

  1. import { createApp } from 'vue'
  2. import { createPinia } from 'pinia'
  3. import App from './App.vue'
  4. const pinia = createPinia()
  5. const app = createApp(App)
  6. app.use(pinia)
  7. app.mount('#app')
复制代码
3、Pinia根本语法
  1. //counter.js
  2. import {defineStore} from 'pinia'
  3. //定义store
  4. //defineStore(仓库的唯一标识,()=>{})
  5. export const useCounterStore = defineStore('counter',()=>{    基于useCounterStore函数就可以使用defineStore仓库
  6.         //声明数据 state-count
  7.         const count = ref(0)
  8.         //声明操作数据的方法action(普通函数)
  9.         const addCount = () => count.value++
  10.         //声明基于数据派生的计算属性getters(computed)
  11.         const double = computed(()=>count.value*2)
  12.         //声明数据 state-msg
  13.         const msg = ref('hello pinia')
  14.        
  15.         return {
  16.                 count,
  17.                 addCount,
  18.                 double
  19.                 ...
  20.                 msg,
  21.         }
  22. })
  23. //App.vue
  24. import {useCounterStore} from ''
  25. const counterStore = useCounterStore() //返回一个对象
  26. {{counterStore.count}}-{{counterStore.double}}
  27. <button @click="counterStore.addCount">+</button>
复制代码
4、action异步实现
  1. //channels.js
  2. import {defineStore} from 'pinia'
  3. export const useChannelStore = defineStore('channel',()=>{
  4.         //声明数据
  5.         const channelList = ref([])
  6.         //声明操作数据的方法
  7.         const getList = async=>{
  8.                 //支持异步(直接写异步请求)
  9.                 const {data:{data}}=await axios.get('')
  10.                 channelList.value = data.channels
  11.                 console.log(data.channels)
  12.         }
  13.         //声明getters相关
  14.         return{
  15.                 channelList,
  16.                 getList
  17.         }
  18. })
  19. //App.vue
  20. import {useChannelStore} from ''
  21. const channelStore = useChannelStore()
  22. <button @click='channelStore.getList'>获取频道数据</button>
  23. <ul>
  24.         <li v-for='item in channelStore.channelList' :key='item.id'>{{item.name}}</li>
  25. </ul>
复制代码
5、Pinia-storeToRefs方法

不能直接对store举行解构,会丢失相应式,必要使用storeToRefs方法
  1. import {storeToRefs} from 'Pinia'
  2. const {count,msg}=storeToRefs(counterStore)
  3. action可以直接解构
复制代码
6、Pinia恒久化

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

  • 安装
npm i pinia-plugin-persistedstate

  • 将插件添加到pinia实例中
  1. import { createPinia } from 'pinia'
  2. import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
  3. const pinia = createPinia()
  4. pinia.use(piniaPluginPersistedstate)
复制代码

  • 在必要设置pinia恒久化的组件中设置
  1. import { defineStore } from 'pinia'
  2. import { ref } from 'vue'
  3. export const useStore = defineStore(
  4.   'main',
  5.   () => {
  6.     const someState = ref('hello pinia')
  7.     return { someState }
  8.   },
  9.   //在声明并return完后进行配置
  10.   {
  11.     persist: true,
  12.   },
  13. )
复制代码
指定state中哪些数据必要恒久化
  1. import { defineStore } from 'pinia'
  2. export const useStore = defineStore('store', {
  3.   state: () => ({
  4.     save: {
  5.       me: 'saved',
  6.       notMe: 'not-saved',
  7.     },
  8.     saveMeToo: 'saved',
  9.   }),
  10.   persist: {
  11.     pick: ['save.me', 'saveMeToo'],
  12.   },
  13. })
复制代码
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表