Vue3.0学习md

Vue3学习笔记

1.环境配置

node.js version 21.7.1

nodejs版本更新方式

下载nvm windows系统下载nvm-setup.zip安装包 使用nvm可以管理node版本并切换

nvm off // 禁用node.js版本管理(不卸载任何东西) nvm on // 启用node.js版本管理 nvm install <version> // 安装node.js的命名 version是版本号 例如:nvm install 8.12.0 nvm uninstall <version> // 卸载node.js是的命令,卸载指定版本的nodejs,当安装失败时卸载使用 nvm ls // 显示所有安装的node.js版本 nvm list available // 显示可以安装的所有node.js的版本 nvm use <version> // 切换到使用指定的nodejs版本 nvm v // 显示nvm版本 nvm install stable // 安装最新稳定版

2.创建Vue3工程

(1)基于vue-cli创建

vue-cli——脚手架——基于webpack

在这里插入图片描述

(2)基于vite创建(推荐)

vite——新一代前端构建工具,与webpack一样也是用来构建前端的

在这里插入图片描述

  • vite是先server ready,告诉你我已就位,你从入口文件进来,你看啥,我加载啥

  • webpack是不管你看啥,我先全部加载,然后再server ready

npm类似于maven:执行npm i安装全部依赖,相当于根据Maven的清单安装全部jar包

创建代码

直接 npm create vue@latest

image-20240404113009970

文件解析

image-20240404121118808

  • vite:入口文件是index.html

  • webpack:入口文件是main.js/main.ts

在实践中,main.jsmain.ts 通常被用作入口文件的命名约定,特别是在使用某些框架或构建工具时(如 Vue CLI、Create React App 等),它们默认使用这些文件名作为起点。

src解析

image-20240404121632692

 import './assets/main.css'         样式表
 ​
 import { createApp } from 'vue'    把 写应用 比喻成种花,createAPP就是造花盆,其实是创建应用
                                     从vue这个库中导入一个名为createApp的函数。
 import App from './App.vue'        组件  相当于种花的根  以后你可以创建 A.VUE  B.VUE  C.VUE
                                     这些组件都要安装到APP根上
                        导入一个Vue组件,该组件通常包含HTML模板、JavaScript代码和CSS样式。                          App.vue文件通常是Vue项目的入口组件,包含了整个应用的根组件。
 ​
 createApp(App).mount('#app')        把花插进花盆  app在HTML里
     createApp(App): 使用createApp函数创建一个新的Vue应用,并传入App组件作为这个应用的根组件。  
     .mount('#app'): 将这个Vue应用挂载到HTML文档中的一个元素上。具体来说,它会查找HTML文档中的ID为app的元素,并将Vue应用的内容渲染到这个元素中。这样,当你在浏览器中打开网页时,你就可以看到由Vue应用渲染的内容了。
     
     创建应用    制造组件    把组件放进应用里(createApp)   应用放在哪里(mount)

image-20240404124658138

(3)项目运行与结束

npm run dev 运行

npm run serve---->cli创建的工程

Ctrl + C 退出当前执行

3.vue3核心语法

(1) OptionsAPI 与 CompositionAPI

  • 选项式:Vue2API设计是Options(配置)风格的。

  • 组合式:Vue3API设计是Composition(组合)风格的。

Options API 的弊端

Options类型的 API,数据、方法、计算属性等,是分散在:datamethodscomputed中的,若想新增或者修改一个需求,就需要分别修改:datamethodscomputed,不便于维护和复用。

Composition API 的优势

可以用函数的方式,更加优雅的组织代码,让相关功能的代码更加有序的组织在一起。

(2) setup 与 Options API 的关系

两句话:

  1. vue2里选项式的语法可以和vue3里的setup()语法共存

  2. 旧的语法里边可以读取setup里的东西,但是setup

不可以读出旧写法的东西,且没有this

理解:

  • Vue2 的配置(datamethos…)中可以访问到 setup中的属性、方法。

  • 但在setup不能访问到Vue2的配置(datamethos…)。

    setup执行后会把数据挂到vm上,data里的this指向的就是vm,所以能读到

  • 如果与Vue2冲突,则setup优先。

本质上就是Java中static和非static的原理。setup先执行,这个时候setup中的值初始化完成,但是data还没有初始化,这个时候data里内容一定读不到

(3) setup 语法糖

setup函数有一个语法糖,这个语法糖,可以让我们把setup独立出去,代码如下:

     <template>
       <div class="person">
         <h2>姓名:{{name}}</h2>
         <h2>年龄:{{age}}</h2>
         <button @click="changName">修改名字</button>
         <button @click="changAge">年龄+1</button>
         <button @click="showTel">点我查看联系方式</button>
       </div>
     </template>
 ​
     <script lang="ts">
       export default {
         name:'Person',
       }
     </script>
 ​
     <!-- 下面的写法是setup语法糖 -->
     <script setup lang="ts">
       console.log(this) //undefined
 ​
       // 数据(注意:此时的name、age、tel都不是响应式数据)
       let name = '张三'
       let age = 18
       let tel = '13888888888'
 ​
       // 方法
       function changName(){
         name = '李四'//注意:此时这么修改name页面是不变化的
       }
       function changAge(){
         console.log(age)
         age += 1 //注意:此时这么修改age页面是不变化的
       }
       function showTel(){
         alert(tel)
       }
     </script>
方法一:添加插件

扩展:上述代码,还需要编写一个不写setupscript标签,去指定组件名字,比较麻烦,我们可以借助vite中的插件简化

  1. 第一步:npm i vite-plugin-vue-setup-extend -D

  2. 第二步:vite.config.ts

     import { defineConfig } from 'vite'
     import VueSetupExtend from 'vite-plugin-vue-setup-extend'//加这一行
            这个名字可以随便取
     export default defineConfig({
       plugins: [ VueSetupExtend() ]
     })
  1. 第三步:<script setup lang="ts" >

image-20240405115716458

方法二:直接宏定义
 defineOptions({ name: 'persossn1sss11' })

image-20240405120258868

(4) ref创建

基本类型的响应式数据
  • 作用: 定义响应式变量。

  • 语法:let xxx = ref(初始值)

  • 返回值: 一个RefImpl的实例对象,简称ref对象refref对象的value属性是响应式的

  • 注意点:

    • JS中操作数据需要:xxx.value,但模板中不需要.value,直接使用即可。

    •  // 模版中直接写,不用.value
       <template>
         <div class="person">
           <h2>姓名:{{name}}</h2>
           <h2>年龄:{{age}}</h2>
         </div>
       </template>
    • 对于let name = ref('张三')来说,name不是响应式的,name.value是响应式的。

    •  <script setup lang="ts" >
         import {ref} from 'vue'
           
         // name和age是一个RefImpl的实例对象,简称ref对象,它们的value属性是响应式的。
         let name = ref('张三')
         let age = ref(18)
           
         // tel就是一个普通的字符串,不是响应式的
         let tel = '13888888888'
       ​
         function changeName(){
           // JS中操作ref对象时候需要.value
           name.value = '李四'
           console.log(name.value)
           // 注意:name不是响应式的,name.value是响应式的,所以如下代码并不会引起页面的更新。
           // name = ref('zhang-san')
         }
         function changeAge(){
           // JS中操作ref对象时候需要.value
           age.value += 1 
           console.log(age.value)
         }
         function showTel(){
           alert(tel)
         }
       </script>
对象类型的响应式数据
  • 其实ref接收的数据可以是:基本类型对象类型

  • ref接收的是对象类型,内部其实也是调用了reactive函数。

 <template>
   <div class="person">
     <h2>汽车信息:一台{{ car.brand }}汽车,价值{{ car.price }}万</h2>
     <h2>游戏列表:</h2>
     <ul>
       <li v-for="g in games" :key="g.id">{{ g.name }}</li>
     </ul>
     <h2>测试:{{obj.a.b.c.d}}</h2>
     <button @click="changeCarPrice">修改汽车价格</button>
     <button @click="changeFirstGame">修改第一游戏</button>
     <button @click="test">测试</button>
   </div>
 </template>
 ​
 <script lang="ts" setup >
 import { ref } from 'vue'
 ​
 // 数据
 let car = ref({ brand: '奔驰', price: 100 })
 let games = ref([
   { id: 'ahsgdyfa01', name: '英雄联盟' },
   { id: 'ahsgdyfa02', name: '王者荣耀' },
   { id: 'ahsgdyfa03', name: '原神' }
 ])
 let obj = ref({
   a:{
     b:{
       c:{
         d:666
       }
     }
   }
 })
 ​
 console.log(car)
 ​
 function changeCarPrice() {
   car.value.price += 10
 }
 function changeFirstGame() {
   games.value[0].name = '流星蝴蝶剑'
 }
 function test(){
   obj.value.a.b.c.d = 999
 }
 </script>

(5) reactive创建

  • 作用:定义一个响应式对象(基本类型不要用它,要用ref,否则报错)

  • 语法:let 响应式对象= reactive(源对象)

  • 返回值: 一个Proxy的实例对象,简称:响应式对象。

  • 注意点:reactive定义的响应式数据是 “深层次” 的。

 <template>
   <div class="person">
     <h2>汽车信息:一台{{ car.brand }}汽车,价值{{ car.price }}万</h2>
     <h2>游戏列表:</h2>
     <ul>
       <li v-for="g in games" :key="g.id">{{ g.name }}</li>
     </ul>
     <h2>测试:{{obj.a.b.c.d}}</h2>
     <button @click="changeCarPrice">修改汽车价格</button>
     <button @click="changeFirstGame">修改第一游戏</button>
     <button @click="test">测试</button>
   </div>
 </template>
 ​
 <script lang="ts" setup >
 import { reactive } from 'vue'
 ​
 // 数据
 let car = reactive({ brand: '奔驰', price: 100 })
 let games = reactive([
   { id: 'ahsgdyfa01', name: '英雄联盟' },
   { id: 'ahsgdyfa02', name: '王者荣耀' },
   { id: 'ahsgdyfa03', name: '原神' }
 ])
 let obj = reactive({
   a:{
     b:{
       c:{
         d:666
       }
     }
   }
 })
 ​
 function changeCarPrice() {
   car.price += 10
 }
 function changeFirstGame() {
   games[0].name = '流星蝴蝶剑'
 }
 function test(){
   obj.a.b.c.d = 999
 }
 </script>

image-20240406113312484

(6) ref 对比 reactive】

宏观角度看:

  1. ref用来定义:基本类型数据对象类型数据

  2. reactive用来定义:对象类型数据

  • 区别:

  1. ref创建的变量必须使用.value(可以使用volar插件自动添加.value,这样就不用一直想着哪个是ref创建的变量,要加.value)。

  1. reactive重新分配一个新对象,会失去响应式(可以使用Object.assign去整体替换)。

     <template>
       <div class="car">
         <h2>汽车信息:一台{{ car.brand }}汽车,价值{{ car.price }}万</h2>
         <button @click="changeCar">修改汽车</button>
       </div>
     </template>
     ​
     <script>
         import {reactive} from 'vue'
         let car=reactive({brand:'奔驰',price:100})
     ​
         // 以下为reactive重新分配一个新对象,使之失去了响应式
         function changeCar(){
             car={brand:'cc',price:90}
         }
     ​
         //应该这么写  下面写法 页面可以更新
         function changeCar(){
             Object.assign(car,{brand:'奥拓',price:90})
         }
     </script>    

  • 使用原则:

  1. 若需要一个基本类型的响应式数据,必须使用ref

  2. 若需要一个响应式对象,层级不深,refreactive都可以。

  3. 若需要一个响应式对象,且层级较深,推荐使用reactive

(7) toRefs 与 toRef

  • 作用:将一个响应式对象中的每一个属性,转换为ref对象。

  • 备注:toRefstoRef功能一致,但toRefs可以批量转换。

  • 语法如下:

 <template>
   <div class="person">
     <h2>姓名:{{person.name}}</h2>
     <h2>年龄:{{person.age}}</h2>
     <h2>性别:{{person.gender}}</h2>
     <button @click="changeName">修改名字</button>
     <button @click="changeAge">修改年龄</button>
     <button @click="changeGender">修改性别</button>
   </div>
 </template>
 ​
 <script lang="ts" setup >
   import {ref,reactive,toRefs,toRef} from 'vue'
 ​
   // 数据
   let person = reactive({name:'张三', age:18, gender:'男'})
     
   // 通过toRefs将person对象中的n个属性批量取出,且依然保持响应式的能力
   let {name,gender} =  toRefs(person)
     
   // 通过toRef将person对象中的gender属性取出,且依然保持响应式的能力
   let age = toRef(person,'age')
 ​
   // 方法
   function changeName(){
     name.value += '~'
   }
   function changeAge(){
     age.value += 1
   }
   function changeGender(){
     gender.value = '女'
   }
 </script>

(8) computed

computed属性是 Vue3 中的一个响应式计算属性

作用
  • 可以根据其他响应式数据的变化而自动更新其自身的值。

  • 可以接收一个计算函数,在计算函数中使用其他响应式数据的值进行计算,并返回一个响应式的ref对象。

当任何一个参与计算的响应式数据发生变化时,computed属性会自动重新计算其值,并触发相应的依赖更新。

原理

在 Vue3 中,computed属性的原理是使用了一个getter函数和一个setter函数来实现。

  • getter:当我们访问计算属性的值时,会调用getter函数进行计算,并将计算结果缓存起来。当参与计算的响应式数据发生变化时,会触发依赖更新,并自动调用getter函数重新计算计算属性的值。

  • setter:当我们修改计算属性的值时,会调用setter函数进行更新。

:value单向绑定; v-model双向绑定

 <template>
   <div class="person">
     姓:<input type="text" v-model="firstName"> <br>
     名:<input type="text" v-model="lastName"> <br>
     全名:<span>{{fullName}}</span> <br>
     <button @click="changeFullName">全名改为:li-si</button>
   </div>
 </template>
 ​
 <script setup lang="ts" >
   import {ref,computed} from 'vue'
 ​
   let firstName = ref('zhang')
   let lastName = ref('san')
 ​
   // 计算属性——只读取,不修改
   /* let fullName = computed(()=>{
     return firstName.value + '-' + lastName.value
   }) */
 ​
 ​
   // 计算属性——既读取又修改
   let fullName = computed({
     // 读取
     get(){
       return firstName.value + '-' + lastName.value
     },
     // 修改
     set(val){
       console.log('有人修改了fullName',val)
         // split函数,根据-进行分割,形成字符串数组
       firstName.value = val.split('-')[0]
       lastName.value = val.split('-')[1]
     }
   })
 ​
   function changeFullName(){
     fullName.value = 'li-si'
   } 
 </script>

(9) watch

  • 作用:监视数据的变化(和Vue2中的watch作用一致)

  • 特点:Vue3中的watch只能监视以下四种数据

  1. ref定义的数据。

  2. reactive定义的数据。

  3. 函数返回一个值(getter函数)。

  4. 一个包含上述内容的数组。

我们在Vue3中使用watch的时候,通常会遇到以下几种情况:

情况一
 <template>
   <div class="person">
     <h2>第一种情况</h2>
     <h2>sum:{{ sum }}</h2>
     <button @click="add">加一</button>
   </div>
 </template>
 ​
 <script setup lang="ts" >
  import {ref,watch} from 'vue'
 ​
  let sum=ref(0)
 ​
  function add(){
   sum.value++
  }
 ​
  let stopWatch=watch(sum,(newValue,oldValue)=>{
   console.log('sum变化了',newValue,oldValue)
   console.log(stopWatch)
   if(newValue>=10){
     stopWatch()
   }
  })
 </script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值