0


vue3 看完这就够搬砖了

Ⅰ. vue3 简介

vue3 代号 onepiece 【海贼王】

2022年2月7日 成为默认版本 , 2023年底 vue2将彻底淘汰。

Ⅱ. 优化内容

  • 更新渲染 快了 1 ~ 2 倍之间 ;
  • 首次渲染 快了 50% 左右 ;
  • 运行内存 减少 50% 左右 ;
  • 打包内存 减少 40% 左右 ;
  • 更强的 ts (typescript) 支持 => 引用下作者 ( 尤雨溪 ) 的原话 ;

真的对 类型 特别特别 较真的用 React 也没什么不好,无非就是性能差点。

文章目录

  • 逻辑代码模块化 composition Api => 如图: ( 逻辑变的不再零散 )在这里插入图片描述

Ⅲ. 源码优化

proxy 代理虚拟dom (diff算法 + 静态标记)采用 ES6 proxy对象 去数据监听
实现原理 => 点击学习对可能变化的dom 进行静态标记
只监听标记了的

Ⅳ. 项目创建

  • vue3的项目创建有2种方式 => 更加推荐 Vite
  • 使用脚手架创建要首先安装 vue脚手架 ,项目启动速度没有Vite 快捷
    ① vue 脚手架 创建② Vite 创建#安装或升级 => npm install -g @vue/cli
    #创建项目 => npm create vue_test #创建项目 => npm init vite-app vue-test2

    Ⅴ. 测试你到那个阶段呢 ?

阶段 ① 简单的页面编写 (需要掌握)
1.setup 函数 与 setup单文组件

setup函数setup单文组件1.其中的变量和方法,需要return 才能使用1.单文组件中的 变量不需要 retrun2.不要对响应数据解构,防止响应失效2.只要是reactive和ref 创建的就可以数据响应3.通过函数形参,获取父子组件通信对象 (props 、emit)3.通过内置函数去访问,来组件通信 (defineProps、defineEmits )
Ⅰ.setup 函数 【响应数据写法、父子通信写法】=>
父组件 :

<templete><!-- vue3 可以不用,单个盒子包裹起来 -->
   <Children :fatherName = 'fatherName'  @handle = 'fun' />
</templete><script>exportdefault{setup(){functionfun(num){ console.log('接受子组件传递过来的值'+num );}return{
      fun,
      fatherName:'张xx',}}}</script>

子组件 ( Children ) :

<templete><!-- vue3 可以不用,单个盒子包裹起来 --><span> {{ name }} </span><span> {{ age  }} </span><span> {{ fatherName }} </span></templete><script>import{ reactive , toRefs }from'vue';exportdefault{
    props:{
         fatherName:{ type:String }},setup(props,{ emit }){
        console.log( props.fatherName );// => 获取父组件  传递  子组件的参数emit('handle',123);// => 子组件 委托 父组件 调用方法接受参数const state =reactive({ name:'张三', age:18})return{//...state   => 会失去响应...toRefs(state)// => 正确写法...toRefs(props)}}}</script>

setup 单文组件 【响应数据写法、父子通信写法】=>
父组件 :

<templete>
   <Children :fatherName = 'fatherName'  @handle = 'fun' />
</templete><scriptsetup>exportdefault{constfun=(num)=>{ console.log('接受子组件传递过来的值'+num );}const fatherName ='李xx',}</script>

子组件 ( Children ) :

<templete><span> {{ state.name }} </span><span> {{ state.age  }} </span><span> {{ fatherName }} </span></templete><scriptsetup>import{ reactive }from'vue';const state =reactive({name:'李四', age:20});const{ fatherName }=defineProps({     fatherName :{ type : String },});// => 获取父组件  传递  子组件的参数const emit =defineEmit(['handle']);emit('handle',123)// => 子组件 委托 父组件 调用方法接受参数</script>

2.组件通信
  1. 除了 【1】中 提到的嵌入 setup 形参 的 props 和 emit 还有 :
  2. proxy.$parent【直接获取,或调用父组件方法】和 ref 【直接获取、或调用子组件方法】;

注意事项 : proxy.$parentref****只能 获取和调用 子或父 setup函数 return 中的 。

<templete>
    <Children  ref = 'children' />
</templete><script>import{ getCurrentInstance , ref }from'vue';exportdefault{setup(){const{ proxy }=getCurrentInstance();
        console.log( proxy.$parent );// => 获取父组件的 return 中的所有对象 .const children =ref(null);// 变量名要和组件的ref值 对应  , 赋值必须为 ref(null) .
        console.log(children.value);//=> 获取父组件的 return 中的所有对象 .}}</script>

3 . 也可以通过 provide 、inject 传递方法和变量 ;

注意事项:provide 、inject 一个接收一个传递 ,只能从 父 => 子 => 孙 => … ( 从上往下单向传递

①父组件:import{ provide }from'vue'exportdefault{setup(){const name ='张三'provide('name ', name )//向下传递return{ name }}}-------------------------------------------------------------
②子组件:
    import{ inject }from'vue'exportdefault{setup(){const getName =inject('name');//接收父传递下来的return{ getName }}}
  • 组后也可以通过 全局状态管理库 ( vuex 和 pinia ) ,组件都可以同时使用其中的属性和方法 ,阶段③中会讲到 。

3.生命周期

vue3与vue2相比较3处修改

  • beforcreate 和 create 直接写到 setup 函数中
  • 所有钩子函数前加 ‘on’ 如 :mounted => onMounted
  • destory 更名为 onUnmounted
  • 引入方式 (vue3 都是模块化) 如 : import { onMounted } from ‘vue’
    vue2vue3详情beforcreate

*create*setup( )new Vue (开始→结束)beforeMounted
Mounted
onBeforeMounted
*
onMounted
模板、DOM渲染* (开始→结束)beforeUpdate
update****onBeforeUpdate
onUpdate****数据发生更新 (开始→结束)beforeDestory
destory****onBeforeUnmount
onUnmounted****离开当前组件 (开始→结束)


4.数据响应 (ref 、reactive)

ref 对象 (一般用于基本数据类型 )

  • js中 修改和获取 ref 对象的值 需要加 value属性 ,在html中则不需要
  • html 中 是通过判断ref 对象的 __V_isRef 是否需要加 .value的 。
......<template><p> 姓名 :{{ name }}</p></template>......setup(){const name =ref('张三')
     name.value ='李四';return{name}}
  • ref若是基本类型 是通过 vue2 同样的 Object.defineProperty 对象进行数据响应 。
  • ref若是应用类型 则 “求助” => 内部转换为 reactive 采用 proxy 对象进行数据响应。
-ref('123')=>     采用 Object.defineProperty() 进行响应 

 -ref({name:'123'})=>reactive( value:{ name :123})=> 采用 proxy 进行响应 

reactive 对象 (一般用于引用数据类型 )

  • reactive 采用 proxy 对象,省却了 Object.defineProperty 的 key 的遍历 ,从而有于 应引用数据类型 有更快的响应速度 ;
  • reactive 在监听数组时不要直接创建数组就行修改

错误写法:点击按钮,执行方法后 ,页面数据无法响应

let  arr =reactive([1,2]);functionchangeArr(){
     arr =['3','4','5'];}

正确写法:

let  arr =reactive({ val:[1,2]});functionchangeArr(){
     arr.val =['3','4','5'];}
  • reactive 的 proxy原理 :
const proxyObj =newProxy({ name:'123'},{get:(obj,key,receiver)=>{return Reflect.get(obj, key,receiver)},set:(obj,key,value,receiver)=>{return Reflect.set(obj, key, value, receiver)}})

详细了解vue2和vue3数据响应的区别 => 点击这里

  • reactive 大多是和 toRefs 配合使用 从而让模板中变量的,更加简便。

5.监听与计算属性 (watch、watchEffct… )
  • watch 和 computed区别
    区别watch (监听)computed(计算属性)资源消耗不走缓存 (消耗资源)默认走缓存 (消耗资源)异步支持异步****不支持异步监听一对多 (或一对一)多对一 (或一对一)

    import{watch, computed, ref}from'vue'......setup(){const num =ref(1);watch(num,(newValue,oldValue)=>{  console.log(newValue);});//num 改变就会执行//-------------------------------------------------------------------------const  a =ref(2);const  b =ref(2);letS=computed(()=>{return a.value * b.value }});//a,b 一个改变就 重新计算 S}
    
  • vue3 新增了 watchEffect , 它会监听 出现在 回调函数中 ref 和reactive对象,中有一个变化就会执行

...watchEffect(()=>{  console.log(a,b));})// 只监听ref 和 reactive 且出现在回调函数中的对象...

6.Api 模块化
  • 需要什么导入什么 ,更加节约内存 如:
import{ onMounted , reactive}from'vue';

阶段 ② 特殊组件的封装 (需要掌握)
1. 组件递归 的应用
  • 组件递归 说到底就是 组件 import 组件本身 ,通过不断向下传参, 最后控制结束,达到组件封装的目的,
  • vue3 本组件 导入本组件 ,只需要添加个 name 属性 ,而 vue2 需要 多写一步 import 该组件

实用场景 => 树形菜单 、流程图 、层级类组件 …
以树形组件为例 :
在这里插入图片描述

  • 首先要给该对象传递一个 具有层级关系对象 ,如: 我们需要根据 (是否有 children 去判断是否要在 递归 import 下去) 1、使用这个treeList 组件:
<tree-list :Arr="Arr"/>...const Arr =[{
          text:"菜单1",
          children:[{
              text:"菜单1-1",
              children:[{ text:"菜单1-1-1"},{ text:"菜单1-1-2"}],},],},{ id:"2", text:"菜单2"},];

2、编辑这个组件 => ( 通过 )

<div v-for="item in Arr"><p>{{ item.text }}</p><tree-list
       v-if="item.children":Arr="item.children":index="index":key="item.id"/></div>...exportdefault{
    name:"tree-list",
    props:{
       Arr:{ type: Array }},}

详细的样式、代码 请参考 => 点击这里


2.插槽 的应用
  • 插槽的作用 主要就是将组件中间的内容,插入到组件对应的位置 ,让组件更灵活。

  • 插槽分为 三种 (普通插槽, 具名插槽 , 作用域插槽)
    普通插槽具名插槽作用域插槽在这里插入图片描述在这里插入图片描述在这里插入图片描述slot 标签接收,默认插入的内容
    多写该标签只会重复插入v-slot =‘aa’ 可简写为 #aa
    插入位置和slot的name一 一对应通过props 传入 参数达到控制模板的目的

    3.标签传送 的使用
  • Teleport 标签主要是将 一块html 内容 传送到 对应的 标签内部 ;

  • Teleport和 dom 的 ** appendChild** 方法的区别,主要是操作的是虚拟dom( 主要在性能方面 ) 。

  • 参数 to对应插入的位置填写对于css选择器

  • 参数 disabled****是否插入 该位置 ,true => 已插入、false => 未插入

<template><divid="box"><p> 标题 </p><button@click='appendContent'> 插入内容 </button><p> 内容:<spanid='content'></span><p/></div>
    
    <Teleport to="#content"  :disabled = "bool">
        teleport 插入到 改标签 中.
    </Teleport></template><script>...const bool =ref(false);constappendContent=()=>{ bool.value =true}return{ bool, appendContent }</script>
阶段 ③ 全局状态管理 (需要掌握)
1.vuex 4.0

①.下载和导入

 npm  i  vuex   --save
 ---------------------------import  Vuex  from'vuex'
 Vue.use(Vuex);

②.创建store仓库: /store/index.js

import{ createStore }from'vuex';exportdefaultcreateStore({
state:{name:123},
mutations:{getname(state,newVal){this.state.name=newVal;}},//同步方法:(只有mutations才能改state的值)
actions:{getnameAsync(){...}},//异步方法
geeter:{},//相当于计算属性
modules:{}//将vuex分块})

③.简单使用

import{useStore}from'vuex'exportdefault{setup(){const store  =useStore();
        console.log(store.state.name);//获取
        store.commit("getname",12345);//修改
        store.dispatch("getnameAsync",12345);//修改}}

④.需要了解与 vue2 的差别 => 点击这里

2.pinia (基于vuex5.0 理念)
  • 相比vuex ,pinia 更具有优势
    pinavuexpinia 同时支持vue2和vue3vue2要用vuex 3 版本
    vue3要用vuex 4 版本不分同步异步,更好的ts支持分同步异步,不太兼容ts享受自动补全
    …需要注入,导入函数,调用他们

① 安装

npm install pinia

在 main.js 中 加入

import{ createApp }from'vue'import App from'./App.vue'import{ createPinia }from'pinia'//导入piniaconst  pinia =createPinia();//调用创建piniacreateApp(App).use(pinia).mount('#app')

③去创建 pinia 仓库
一般选在 /src下的 store 文件夹下 例:创建为 pinia.js

import{ defineStore }from'pinia'exportconst PiniaStore =defineStore('main',{//导出 pinia仓库
    state:()=>{//相当于全局的 data()return{
            name:'张三',
            age:18}},
    getters:{},//相当于全局的computed
    actions:{}//相当于全局methods})

③使用 (非常容易)
以/src/view/index.vue 为例:

<template><h3>{{pinia.name}}</h3><!--使用--><h3>{{pinia.age}}</h3><button @click="pinia.age++">修改pinia数据</button><!--修改--></template><script setup>import{ PiniaStore }from'../../store/pinia'const pinia =PiniaStore();</script>
阶段 ④ 框架的搭建 (需要掌握)
1.vue3路由、及与vue2的区别

创建路由

import{ createRouter, createWebHistory }from'vue-router'const routerHistory =createWebHistory()const router =createRouter({
    history: routerHistory,
    routes:[]})exportdefault router
2.全局组件 批量导入
  • 批量导入
  • 主文件Main.js
 import toMore from './components/toMore '
 createApp(App)
             .use(toMore)
             .mount('#app')
  • components 文件夹下创建 导入文件 如 : toMore.js
 let toMore=  () => {
      install(app) {
           const com = import.meta.globEager("./*.vue");
            for (const path in com ) {
                app.component( com[path].name, com[path].default);
            }}
     };
 export default toMore;
阶段 ⑤ 3.x性能优化
非递归监听 (优化reactive 、ref)
  • 当数据量非常大时,可以考虑用 shallowRefshallowReactive去替代 reactive 、ref
  • shallowRef 只监听 .value的变化 ,如果value 是对象下面还有层数则不监听;
  • shallowReactive 只 监听 第一层的变化。
  • 可以多次修改 通过 triggerRef方法 去多次修改后去更新一次页面 如 triggerRe(obj)

本文转载自: https://blog.csdn.net/weixin_42232622/article/details/125961836
版权归原作者 别拿bug搞偷袭 所有, 如有侵权,请联系我们删除。

“vue3 看完这就够搬砖了”的评论:

还没有评论