快速入门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.XVue3
beforeCreatesetup()
createdsetup()
beforeMountonBeforeMount
mountedonMounted
beforeUpdateonBeforeUpdate
updatedonUpdated
beforeDestroyonBeforeUnmount
destroyedonUnmounted
errorCapturedonErrorCaptured
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.xxxxapp.config.xxxx
Vue.config.productionTip移除
Vue.componentapp.component
Vue.directiveapp.directive
Vue.mixinapp.mixin
Vue.useapp.use
Vue.prototypeapp.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中的一些特性,更多的知识大家可以去看看官方文档,希望这篇笔记能够帮助到大家。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值