快速入门vue3

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

这篇文章是我之前学习 Vue3 做的笔记,加上一些官网和其他地方查阅的资料的补充,主要是带领学习了Vue2还未学习Vue3的小伙伴快速入门。通过这篇文章你可以快速的了解Vue3的新特性。

一、Vue3的创建方式

在创建vue3项目之前可以先来了解一下新一代前端构建工具Vite,这里我们只是简单介绍一下
Vite

1. Vite的优势

1.基于ESM的开发服务优势:

  • 无需打包项目源代码
  • 天然的按需加载
  • 可以利用文件级的浏览器缓存

2.基于Esbuild的编译性能优化
请添加图片描述
3.内置的Web构建功能,开箱即用:
请添加图片描述
在了解vite后,我们就使用vite来创建项目,想要深入的去了解vite可以去官网。

2. 创建vue3项目

1.这里我们选择使用Vite搭建项目

// npm
npm create vite@latest
//Yarn
yarn create vite
//PNPM
pnpm create vite

2.创建模板+选择模板(这里我们选择vue + javaScript)
继续操作:

 //进入项目文件夹
 cd vite-project        
 //初始化项目
  npm install             
 //运行项目
 npm run dev           

这时项目就正常运行了
在这里插入图片描述

二、Vue3入门

1. Composition API

Vue3 提出了 Composition API ,它可以把 一个逻辑的代码都收集在一起 单独写个hook,然后再引入,不用再像vue2中把数据,方法拆分开来。

这里引用官网的话来说:

组合式 API (Composition API) 是一系列 API 的集合,使我们可以使用函数而不是声明选项的方式书写 Vue
组件。它是一个概括性的术语,涵盖了以下方面的 API: 响应式 API:例如 ref() 和
reactive(),使我们可以直接创建响应式状态、计算属性和侦听器。

生命周期钩子:例如 onMounted() 和 onUnmounted(),使我们可以在组件各个生命周期阶段添加逻辑。

依赖注入:例如 provide() 和 inject(),使我们可以在使用响应式 API 时,利用 Vue 的依赖注入系统。

2.setup

  1. 理解:Vue3.0中一个新的配置项,值为一个函数。
  2. setup是所有Composition API(组合API)“ 表演的舞台 ”。
  3. 组件中所用到的:数据、方法等等,均要配置在setup中。

(1).setup的执行顺序
setup执行在beforeCreate,created之前,它里面的this打印出来是undefined

(2)setup接受的参数

setup(props, context)

props:它接收父组件传递的值。
context: 上下文对象,用于代替以前的this方法可以访问的属性

attrs: 值为对象,包含:组件外部传递过来,但没有在props配置中声明的属性, 相当于 this.$attrs。

slots: 收到的插槽内容, 相当于 this.$slots。

emit: 分发自定义事件的函数, 相当于 this.$emit。

在这里插入图片描述

(3)setup返回值
setup返回的是一个对象,这个对象中的数据可以直接在模板中使用,在data配置项中也可以通过this.xxx拿到setup中返回的值
在这里插入图片描述

三、ref函数与reactive函数

在之前我们写的数据都不是响应式的数据,我们可以通过ref函数与reactive来定义响应式的数据,在使用前都需要引入函数。

1. ref函数

● 作用: 定义一个响应式的数据
● 语法: const xxx = ref(initValue)
○ 创建一个包含响应式数据的引用对象(reference对象,简称ref对象)。
○ JS中操作数据: xxx.value
○ 模板中读取数据: 不需要.value,直接:<div>{ {xxx}}</div>

备注:

接收的数据可以是:基本类型、也可以是对象类型。
基本类型的数据:响应式依然是靠Object.defineProperty()的get与set完成的。 对象类型的数据:内部 “ 求助 ”
了Vue3.0中新函数—— reactive函数。所以定义响应式数据的时候我们可以直接使用reactive函数

<script lang="js">
//引入ref函数
import {
    
    defineComponent,ref} from "vue";

export default defineComponent({
    
    
  name:'App',
  data(){
    
    
    return{
    
    

    }
  },
  setup(props, context){
    
    
  //定义一个响应式数据
    let num = ref(0)
    //定义方法
    function  add(){
    
    
       console.log(1)
       //在setup中要拿到ref定义的数据需要.value
       num.value++
    }
    //把数据和方法返回出去,模板中才能使用
    return {
    
    num,add}
  }
})
</script>

<template>
  <div @click="add()">{
    
    {
    
    num}}</div>
</template>

2. reactive函数

● 作用: 定义一个对象类型的响应式数据(基本类型不要用它,要用ref函数)
● 语法:const 代理对象= reactive(源对象)接收一个对象(或数组),返回一个代理对象(Proxy的实例对象,简称proxy对象)
● reactive定义的响应式数据是“深层次的”。
● 内部基于 ES6 的 Proxy 实现,通过代理对象操作源对象内部数据进行操作。

<script lang="js">
//引入reactive
import {
    
    defineComponent,ref,reactive} from "vue";

export default defineComponent({
    
    
  name:'App',
  data(){
    
    
    return{
    
    

    }
  },
  setup(props, context){
    
    
    let objs = reactive({
    
    
       name:'ld',
       age:20
    })
    function  updata(){
    
    
    //读取reactive定义的数据的时候不需要.cvalue
       objs.age = 28
    }
    return {
    
    objs,updata}
  }
})
</script>

<template>
  <div @click="updata()">{
    
    {
    
    objs}}</div>
</template>

3. reactive对比ref

● 从定义数据角度对比:

ref:用来定义基本类型数据。
reactive:用来定义对象(或数组)类型数据。
备注:ref也可以用来定义对象(或数组)类型数据, 它内部会自动通过reactive转为代理对象。

● 从原理角度对比:

ref通过Object.defineProperty()的get与set来实现响应式(数据劫持)。 ○
reactive通过使用Proxy来实现响应式(数据劫持), 并通过Reflect操作源对象内部的数据。

● 从使用角度对比:

ref定义的数据:操作数据需要.value,读取数据时模板中直接读取不需要.value。
reactive定义的数据:操作数据与读取数据:均不需要.value。

4. 扩展:在vue3中使用ref拿到dom

在vue2中我们使用ref可以获取元素,在vue3我们同样可以,只是使用的方式不一样了。

//拿到单个DOM
<script lang="js">
import {
    
    defineComponent,ref,reactive} from "vue";
export default defineComponent({
    
    
  name:'App',
  setup(props, context){
    
    
    let item = ref(null)
    console.log(item)
    return {
    
    item}
  }
})
</script>

<template>
  <div ref="item" id="item">20</div>
</template>

//获取多个DOM

<script lang="js">
import {
    
    defineComponent,ref,nextTick} from "vue";
export default defineComponent({
    
    
  name:'App',
  setup(props, context){
    
    
    // 存储dom数组
    const myRef = ref([]);

    const setRef = (el) => {
    
    
      myRef.value.push(el);
    };
    //下一个DOM 更新周期之后执行
    nextTick(() => {
    
    
      console.dir(myRef.value);
    });

    return {
    
    setRef}
  }
})
</script>

<template>
  <div v-for="(item,index) in 3" :ref="setRef">10</div>
</template>

获得多个ref效果图:
在这里插入图片描述

四、computed与watch

1. computed

与vue2中的配置方法一致

import {
    
    defineComponent,reactive,computed} from "vue";
...
setup(){
    
    
    let pers = reactive({
    
    
        name:'dlh',
        age:38
    })
    //计算属性——简写
    let compName = computed(()=>{
    
    
      return pers.name + '-' + pers.age
    })
    //计算属性——完整
    let compNames = computed({
    
    
      //读取
      get(){
    
    
        return pers.name + '-' + pers.age
      },
      //修改
      set(value){
    
    
        const nameArr = value.split('-')
        pers.name= nameArr[0]
        pers.age = nameArr[1]
      }
    })
    return {
    
    
      compName,compNames
    }
  }

2. watch

与vue2中的配置方法一致

watch(data,handler,object)
data:监视的数据
handler(newValue,oldValue):回调函数(改变后的值,改变前的值)
object:可选配置项 { immediate: true,deep:true }

import {
    
    watch,ref,reactive} from "vue";
...
setup(){
    
    
let num=ref(5),num2=ref(10)
let person = reactive({
    
    
       name:'5465',
       age:18
}
//情况一:监视ref定义的响应式数据
watch(num,(newValue,oldValue)=>{
    
    
      console.log('num变化了',newValue,oldValue)
    },{
    
    immediate:true})
}
//情况二:监视多个ref定义的响应式数据[数组方式]
watch([num,num2],(newValue,oldValue)=>{
    
    
      console.log('num或num2变化了',newValue,oldValue)
    })
/* 
情况三:监视reactive定义的响应式数据,无法正确获得oldValue,并且强制开启了深度监视 
*/
watch(person,(newValue,oldValue)=>{
    
    
	console.log('person变化了',newValue,oldValue)
},{
    
    immediate:true)
//情况四:监视reactive定义的响应式数据中的某个属性(参数以函数返回值的形式传递)
watch(()=>person.num,(newValue,oldValue)=>{
    
    
	console.log('person的job变化了',newValue,oldValue)
},{
    
    immediate:true,deep:true}) 

//情况五:监视reactive定义的响应式数据中的多个数据[数组]
watch([()=>person.num,()=>person.age],(newValue,oldValue)=>{
    
    
	console.log('person的job变化了',newValue,oldValue)
},{
    
    immediate:true,deep:true})

3.watchEffect函数

在watch中,要指明监视的属性,并且指明监视的回调,但是在watchEffect中不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性。

//watchEffect所指定的回调中用到的数据只要发生变化,则直接重新执行回调。
watchEffect(()=>{
    
    
    const num1 = sum.value
    const num2 = person.age
    console.log('watchEffect配置的回调执行了')
})

五、生命周期

在这里插入图片描述
生命周期需要 通过 import 导入,在 setup 函数中使用,并且Vue3 的生命周期 比 Vue2.X 的生命周期快。

Vue2.X Vue3
beforeCreate setup()
created setup()
beforeMount onBeforeMount
mounted onMounted
beforeUpdate onBeforeUpdate
updated onUpdated
beforeDestroy onBeforeUnmount
destroyed onUnmounted
errorCaptured onErrorCaptured
onRenderTracked(新增)
onRenderTriggered(新增)

新增加了两个钩子

onRenderTriggered 跟踪虚拟 DOM 重新渲染时调用
onRenderTracked 当虚拟 DOM 重新渲染被触发时调用

在setup中使用生命周期钩子

import {
    
    defineComponent,onMounted} from "vue";
...
setup(){
    
    
    onMounted(()=>{
    
    
      console.log('Mounted !!')
    })
  }

六、自定义hook函数

vue3 中的 hooks 函数相当于 vue2 里面的 mixin 混入,hooks本质是一个函数,
,就是将文件的一些单独功能的js代码进行抽离出来,放到单独的js文件中他的优势就在于, 复用代码, 让setup中的逻辑更清楚易懂。

封装监听鼠标位置的hooks

// src/hooks/useMove.js
import {
    
    ref} from 'vue'
export default function(){
    
    
    //创建2个响应式变量来储存用户鼠标x轴和y轴的位置
    let pageX = ref(0) , pageY = ref(0)
    window.addEventListener('mousemove',(event)=>{
    
    
        pageX.value = event.pageX
        pageY.value = event.pageY
    })
    return {
    
    
        pageX,
        pageY
    }
}
//组件中引入使用

<script setup>
import useMove from "./hooks/useMove"
const {
    
      pageX, pageY} = useMove()
</script>
 
<template>
   <div>
      X: {
    
    {
    
    pageX }} Y:{
    
    {
    
     pageY }}
   </div>
</template>
 
<style scoped>
</style>

八、provide 与 inject

他们实现了祖与后代组件间通信

父组件有一个 provide 选项来提供数据,后代组件有一个 inject 选项来开始使用这些数据

//祖组件
import {
    
    defineComponent, provide, reactive} from "vue";
...
setup(){
    
    
    let hobby = reactive({
    
    name:'爱好',price:'无价'})
    provide('hobby',hobby)
  }
//后代组件
import {
    
    inject, ref} from 'vue'
...
setup(){
    
    
	const hobby = inject('hobby')
	return{
    
    
	   hobby
	}
}

九、Teleport - 任意传送门

可以将特定的html模板传送到Dom的任何位置

Teleport具有一个必填属性- to to 需要 prop,必须是有效的查询选择器或 HTMLElement

 <teleport to='#portal'>
      <div v-if="isShow" class='doms'>
        Hello ! teleport
     </div>
</teleport>

接下来写一个案例就能够清晰的知道它的用法了。
首先找到index.html文件

//在</body>前面添加<div id='portal'></div>
  <body>
    <div id="app"></div>
    <div id='portal'></div>
    <script type="module" src="/src/main.js"></script>
  </body>

在子组件中

<script lang="js">
import {
    
     ref } from 'vue'
export default {
    
    
  setup () {
    
    
    //控制隐藏的变量
    const isShow = ref(false)
    //定时器id
    let closeTime = null;
    //当用户点击弹出
    const showNotification = () => {
    
    
      isShow.value = true
      clearTimeout(closeTime)
      closeTime = setTimeout(() => {
    
    
        isShow.value = false
      }, 2000)
    }
    return {
    
    
      isShow,
      showNotification
    }
  }
}
</script>

<template>
  <div class='portals'>
    <button @click='showNotification'> 显示 </button>
    //需要传送的内容写在teleport里面并且to的地址为前面index文件中的id
 
    <teleport to='#portal'>
      <div v-if="isShow" class='doms'>
        Hello ! teleport
      </div>
    </teleport>
  </div>
</template>

<style scoped>
.doms {
    
    
  position: fixed;
  bottom: 20px;
  left: 20px;
  width: 120px;
  padding: 30px;
  color: #1a1a1a;
  background-color: #fff;
  border-radius: 10px;
}
</style>

最终时间效果:当用户点击后左下方出现提示框,2秒后消失
在这里插入图片描述

十、响应式数据的判断

  1. isRef: 检查一个值是否为一个 ref 对象
  2. isReactive: 检查一个对象是否是由 reactive 创建的响应式代理
  3. isReadonly: 检查一个对象是否是由 readonly 创建的只读代理
  4. isProxy: 检查一个对象是否是由eactive 或者 readonly 方法创建的代理

十一、其他的一些Composition API

1.toRaw 与 markRaw

toRaw:

作用:将一个由reactive生成的响应式对象转为普通对象。
使用场景:用于读取响应式对象对应的普通对象,对这个普通对象的所有操作,不会引起页面更新。


import {
    
    defineComponent,reactive,toRaw} from "vue";
export default defineComponent({
    
    
  setup(){
    
    
    let obj = reactive({
    
    
      name:'段',
      age:20
    })
    let objToRaw =  toRaw(obj)
    console.log(obj,objToRaw)
    return{
    
    
      obj,
      objToRaw
    }
  }
})

这时第二个数据就变成了普通数据了
在这里插入图片描述

markRaw:

作用:标记一个对象,使其永远不会再成为响应式对象。
应用场景:
1.有些值不应被设置为响应式的,例如复杂的第三方类库等。
2.当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能。

2.shallowReactive 与 shallowRef

shallowReactive : 只处理对象内最外层属性的响应式(也就是浅响应式)

使用场景:如果有一个对象结构多层嵌套,我们的需求只是修改最外层的数据,就不用把里面的嵌套结构都转为响应式,只需要把最外层的属性设为响应式这样能够提高性能。

shallowRef : 只处理基本数据类型的响应式, 不进行对象的响应式处理。

使用场景:如果有一个对象数据,后续功能不会修改该对象中的属性,而是生新的对象来替换 那么就可以使用它

3.readonly 和 shallowReadonly

readonly : 让一个响应式数据变为只读的(深只读)。

内层的每一个属性都设置为只读,进行修改操作就会报错。

shallowReadonly: 让一个响应式数据变为只读的(浅只读)。

浅度的话只针对最外面一层,修改内层不会报错

应用场景:当数据不想被修改的时候使用,根据不同的程度来选择api

十二、全局api的变化

Vue 2中有许多全局 API 和配置,Vue3中对这些API做出了一些调整:

2.x 全局 API(Vue) 3.x 实例 API (app)
Vue.config.xxxx app.config.xxxx
Vue.config.productionTip 移除
Vue.component app.component
Vue.directive app.directive
Vue.mixin app.mixin
Vue.use app.use
Vue.prototype app.config.globalProperties

例如挂载$api到原型上

import {
    
     createApp } from 'vue'
import './style.css'
import App from './App.vue'
import API from '@/api/api';

const app =  createApp(App)
app.config.globalProperties.$API = API;
app.mount('#app')

总结

以上就是今天要讲的内容,本文仅仅简单介绍了vue3中的一些特性,更多的知识大家可以去看看官方文档,希望这篇笔记能够帮助到大家。

猜你喜欢

转载自blog.csdn.net/m0_63831957/article/details/129772843