当前位置: 首页 > article >正文

认识Vue3

目录

1. Vue3的优势

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

使用create-vue搭建Vue3项目

1. 认识create-vue

2. 使用create-vue创建Vue3项目

熟悉Vue3项目目录和关键文件

组合式API - setup选项

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

2. setup中写代码的特点

组合式API - reactive函数和ref函数

1. reactive

2. ref

3. reactive 对比 ref

组合式API - computed

组合式API - watch

1. 侦听单个数据

2. 侦听多个数据

3. immediate

4. deep

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

组合式API中的生命周期函数写法

1. 选项式对比组合式

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

组合式API - 父子通信

1. 父传子

2. 子传父

组合式API - 模版引用

1. 基本使用

2. defineExpose

组合式API - provide和inject

1. 作用和场景

2. 跨层传递普通数据

3. 跨层传递响应式数据

4. 跨层传递方法

Vue3.3 新特性-defineOptions

Vue3.3新特性-defineModel


1. Vue3的优势

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

选项式API就是在整个配置项中有着一个一个的选项,如下图:data是一个选项、methods是一个选项、computed是一个项目、watch是一个选项。

同功能的数据声明、方法、计算属性都是散落在各个位置的。

在VUE3 组合式API中,提供数据不用在data配置项中提供,而是可以调用方法的时候再提供,它将同功能的数据声明、方法的提供、计算属性全部放到了一起:

而且,因为所有的功能都集中管理,所以到另一个页面中,如果要复用的话,可以把同功能的一整块代码封装成一个函数,在函数中声明数据,在函数中声明方法、在函数中声明计算属性等等。

将来哪个页面要用,在页面中一调函数就可以将这段内容生成

使用create-vue搭建Vue3项目

1. 认识create-vue

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

2. 使用create-vue创建Vue3项目

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

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

npm init vue@latest

熟悉Vue3项目目录和关键文件

vite.config.js

可以放一些和vite相关的配置内容

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))
    }
  }
})

vue3的main.js

//Vue3的main.js中,通过createApp函数去创建vue实例
//包括创建路由实例、仓库实例,都是用createRouter() createStore()函数
// 将创建实例进行了封装,保证每个实例的独立封闭性

import { createApp } from 'vue'
import App from './App.vue'

// mount 设置挂载点 #app (id为app的盒子)(往id为app的盒子上去挂载)
createApp(App).mount('#app')

组合式API - setup选项

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

写法

<script>
  export default {
    //setup写成一个函数,将来里面就可以编写一些组合式API,在里面调各种函数
    setup(){
      
    },
    beforeCreate(){
      
    }
  }
</script>

执行时机

在beforeCreate生命周期钩子之前执行

2. setup中写代码的特点

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

1. setup函数的执行时机,比beforeCreate生命周期函数还要早
2. 在setup函数中,获取不到this (this是undefined)
3. 在setup函数中提供的数据 和 函数,需要在 setup函数 最后 return,才能模板<template></template>中应用!!!!!!
 

<script>
export default {
  setup () {
    // 数据
    const message = 'hello Vue3'
    // 函数
    const logMessage = () => {
      console.log(message)
    }
    return {
      message,
      logMessage
    }
  },
  beforeCreate () {
    console.log('beforeCreate函数')
  }
}
</script>


<template>
  <div>{{ message }}</div>
  <button @click="logMessage">按钮</button>
</template>

 问题:每次都要return,好麻烦?
可以通过 setup 语法糖简化代码 

在script标签上添加 setup标记后,setup函数不用写了,而且也不需要再写导出语句,默认会添加导出语句

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

<template>
  <div>{{ message }}</div>
  <button @click="logMessage">按钮</button>
</template>

组合式API - reactive函数和ref函数

1. reactive

作用:接受 一个对象类型的数据,并返回一个响应式的对象

核心步骤:

1.从vue包中导入reactive函数

2.在<script setup>中调用reactive函数,并传入对象类型的初始值,并使用变量来接收返回值

<script setup>
import { reactive } from 'vue'
const state = reactive({
  count: 100
})
const setCount = () => {
  state.count++
}
</script>

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

2. ref

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

本质:是在原有传入数据的基础上,外层包了一层对象,包成了复杂类型,底层包成复杂类型之后,再借助 reactive 实现的响应式

注意点:

1. 因为在原有数据的基础上包了一层对象,所以脚本中访问数据,需要通过 .value访问

2. 在template中,.value不需要加 (帮我们扒了一层)

3.推荐:以后声明数据,统一用 ref => 统一了编码规范

核心步骤:

1.从vue包中导入reactive函数

2.在<script setup>中调用ref函数,并传入初始值,并使用变量来接收ref函数返回的响应式的对象

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

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

3. reactive 对比 ref

  1. 都是用来生成响应式数据

  2. 不同点

    1. reactive不能处理简单类型的数据

    2. ref参数类型支持更好,但是必须通过.value访问

    3. ref函数内部的实现依赖于reactive函数

  3. 在实际工作中的推荐

    1. 推荐使用ref函数,减少记忆负担,小兔鲜项目都使用ref

组合式API - computed

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

核心步骤:

1.从vue包中,导入computed函数

2.调用computed函数,里面传入一个箭头函数,在箭头函数中 返回基于响应式数据 计算出来的新值

  • const 计算属性 = computed(() => {
       return 计算返回的结果
    })

案例:

<script setup>
// const 计算属性 = computed(() => {
//    return 计算返回的结果
// })

import { computed, ref } from 'vue'

// 声明数据
const list = ref([1, 2, 3, 4, 5, 6, 7, 8])

// 基于list派生一个计算属性,从list中过滤出 > 2
const computedList = computed(() => {
  return list.value.filter(item => item > 2)
})

// 定义一个修改数组的方法
const addFn = () => {
  list.value.push(666)
}
</script>

<template>
  <div>
    <div>原始数据: {{ list }}</div>
    <div>计算后的数据: {{ computedList }}</div>
    <button @click="addFn" type="button">修改</button>
  </div>
</template>

组合式API - watch

侦听一个或者多个数据的变化,当数据变化时执行回调函数。

俩个额外参数 immediate控制立刻执行,deep开启深度侦听。

1. 侦听单个数据

步骤:

1.从vue包中导入watch函数

2.调用watch函数,传入要侦听的响应式数据和回调函数

  • watch(ref对象, (newValue, oldValue) => { ... })

    newValue是变化后的响应式数据

  • oldValue是变化前的响应式数据

案例:

<script setup>
import { ref, watch } from 'vue'
const count = ref(0)
const nickname = ref('张三')

const changeCount = () => {
  count.value++
}
const changeNickname = () => {
  nickname.value = '李四'
}

// 1. 监视单个数据的变化
//    watch(ref对象, (newValue, oldValue) => { ... })
watch(count, (newValue, oldValue) => {
  console.log(newValue, oldValue)
})
</script>

<template>
  <div>{{ count }}</div>
  <button @click="changeCount">改数字</button>
  <div>{{ nickname }}</div>
  <button @click="changeNickname">改昵称</button>
</template>

2. 侦听多个数据

同时侦听多个响应式数据的变化,就是第一个参数改写成数组的写法,无论哪个数据变了,都会触发回调函数

语法:

watch([ref对象1, ref对象2], (newArr, oldArr) => { ... })
  • newArr是变化后的多个响应式数据组成的数组
  • oldArr是变化前的多个响应式数据组成的数组 
<script setup>
import { ref, watch } from 'vue'
const count = ref(0)
const nickname = ref('张三')

const changeCount = () => {
  count.value++
}
const changeNickname = () => {
  nickname.value = '李四'
}

// 2. 监视多个数据的变化
//    watch([ref对象1, ref对象2], (newArr, oldArr) => { ... })
watch([count, nickname], (newArr, oldArr) => {
  console.log(newArr, oldArr)
})
</script>

<template>
  <div>{{ count }}</div>
  <button @click="changeCount">改数字</button>
  <div>{{ nickname }}</div>
  <button @click="changeNickname">改昵称</button>
</template>

3. immediate

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

语法:在watch函数的第三个形参位置传一个对象进去,然后对象中添加immediate属性。 

// 3. immediate 立刻执行
watch(count, (newValue, oldValue) => {
  console.log(newValue, oldValue)
}, {
  immediate: true
})

4. deep

deep进行深度监视, 默认 watch 进行的是 浅层监视

   const ref1 = ref(简单类型) 可以直接监视

   const ref2 = ref(复杂类型) 监视不到复杂类型内部数据的变化,监视复杂类型时,监视的是其地址值

<script setup>
import { ref, watch } from 'vue'


const userInfo = ref({
  name: 'zs',
  age: 18
})
const setUserInfo = () => {
  // 修改了 userInfo.value 修改了对象的地址,才能监视到
  // userInfo.value = { name: 'ls', age: 50 }
  userInfo.value.age++
}

// deep 深度监视
watch(userInfo, (newValue) => {
  console.log(newValue)
}, {
  deep: true
})
</script>

<template>
  <div>{{ userInfo }}</div>
  <button @click="setUserInfo">修改userInfo</button>
</template>

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

在不开启deep的前提下,侦听age的变化,只有age变化时才会执行回调函数

<script setup>
import { ref, watch } from 'vue'


const userInfo = ref({
  name: 'zs',
  age: 18
})
const setUserInfo = () => {
  userInfo.value.age++
}

// 5. 对于对象中的单个属性,进行监视
watch(() => userInfo.value.age, (newValue, oldValue) => {
  console.log(newValue, oldValue)
})
</script>

<template>
  <div>{{ userInfo }}</div>
  <button @click="setUserInfo">修改userInfo</button>
</template>

组合式API中的生命周期函数写法

1. 选项式对比组合式

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

  1. 从vue包中,导入生命周期函数

  2. 调用生命周期函数,传入回调函数

  3. 注意:生命周期函数可以调用多次,其会按照顺序依次执行

<script setup>
import { onMounted } from 'vue';

// beforeCreate 和 created 函数中的相关代码一律放在 setup 中执行
const getList = () => {
  setTimeout(() => {
    console.log('发送请求,获取数据')
  }, 2000)
}
// 一进入页面,就直接调用getList函数发送请求
getList()




// 如果有些代码需要在mounted生命周期函数中执行
onMounted(() => {
  console.log('mounted生命周期函数 - 逻辑1')
})

// 写成函数的调用方式,可以调用多次,并不会冲突,而是按照顺序依次执行
onMounted(() => {
  console.log('mounted生命周期函数 - 逻辑2')
})

</script>

<template>
  <div></div>
</template>

组合式API - 父子通信

1. 父传子

基本思想

  1. 父组件中给子组件标签添加属性

  2. 子组件内部通过props选项接收数据

2. 子传父

基本思想

  1. 父组件中给子组件标签通过@绑定一个自定义事件

  2. 子组件内部通过 emit 方法触发自定义事件,传递数据

App.vue

<script setup>
//在vue3中,组件的局部注册,只要导入进来就可以使用
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>
  </h3>
  
  <SonCom car="宝马车"
   :money="money"
   @changeMoney="changeFn"
   >
  </SonCom>
</div>
</template>



son.com.vue

<script setup>
// 注意:由于写了 setup,所以无法直接配置 props 选项
// 所以:此处需要借助于 “编译器宏” 函数提供props选项接收父组件传递的数据
const props = defineProps({
  car: String,
  money: Number
})

const emit = defineEmits(['changeMoney'])
console.log(props.car)
console.log(props.money)

const buy = () => {
  // 需要 emit函数 触发事件
  emit('changeMoney', 5)
}
</script>

<template>
  <!-- 对于props传递过来的数据,模板中可以直接使用 -->
  <div class="son">
    我是子组件 - {{ car }} - {{ money }}
    <button @click="buy">花钱</button>
  </div>
</template>

<style scoped>
.son {
  border: 1px solid #000;
  padding: 30px;
}
</style>

组合式API - 模版引用

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

1. 基本使用

实现步骤:

  1. 调用ref函数创建一个值为null的ref对象

  2. 然后在标签上添加ref标识,绑定创建的ref对象到标签上

  3. 最后使用ref对象.value即可访问到绑定的元素(必须模板渲染完成后,才能拿到绑定的元素)

2. defineExpose

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

vue.app

<script setup>
//在vue3中,组件的局部注册,只要导入进来就可以使用
import TestCom from '@/components/test-com.vue'
import { onMounted, ref } from 'vue'

//---------------获取dom元素--------------
const inp = ref(null)

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>

组合式API - provide和inject

1. 作用和场景

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

2. 跨层传递普通数据

实现步骤

  1. 顶层组件通过 provide 函数提供数据

    1. 第一个形参是数据的key

    2. 第二个形参是真正要传递的数据

  2. 底层组件通过 inject 函数接收数据

    1. 通过数据的key来接收

3. 跨层传递响应式数据

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

4. 跨层传递方法

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

案例:

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>



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')
const count = inject('count')
const changeCount = inject('changeCount')
const clickFn = () => {
  changeCount(1000)
}
</script>

<template>
<div>
  <h3>我是底层组件-{{ themeColor }} - {{ 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 宏。顾名思义,主要是用来让用户可以定义 选项式API中 的选项。可以用 defineOptions 定义任意的选项, props, emits, expose, slots 除外(因为这些可以使用 defineXXX 来做到)

Vue3.3新特性-defineModel

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

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

于是乎 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))
    }
  }
})


http://www.kler.cn/a/551882.html

相关文章:

  • MySQL服务端启动问题
  • 苏剑林“闭门造车”之多模态思路浅谈思考
  • 【好玩的Docker项目】使用Docker轻松搭建游戏化编程学习平台
  • 数智读书笔记系列014 MICK《SQL进阶教程》第一版和第二版对比和总结
  • 轻松搭建本地大语言模型(二)Open-WebUI安装与使用
  • 深入解析504网关超时错误:服务器通信故障的诊断与解决
  • wx064基于ssm+vue+uniapp的医院挂号预约系统小程序
  • SNARKs 和 UTXO链的未来
  • FFmpeg 基本语法全面介绍
  • #渗透测试#批量漏洞挖掘#Apache Log4j反序列化命令执行漏洞
  • 进阶!Vuex 状态管理:从入门到精通,打造高效 Vue.js 应用
  • 如何快速体验springboot 4.0.x最新适配,看看更新啦那些变化。
  • 多表关联查询的优化
  • 使用Java爬虫获取1688按图搜索商品(拍立淘API接口)
  • 嵌入式Linux系统UART驱动移植专题详解(3000+字图文实战指南)
  • SAP F1搜索帮助 添加自定义功能按钮
  • git 学习(基于Ubuntu和gitee)
  • vue + uniapp + 高德地图实现微信小程序地图polyline、marker展示
  • (学习总结25)Linux工具:vim 编辑器 和 gcc/g++ 编译器
  • 2024 年 6 月青少年软编等考 C 语言三级真题解析