vue3学习全部笔记

1. vue3介绍

  • Vue.js 3.0版在2020年9月18日发布
  • Vue3支持vue2的大多数特性
  • Vue3在2022年2月7日成为新的默认版本

性能提升

  • 项目打包体积更小
  • 初次渲染更快, 更新渲染更快
  • 需要的运行内存更小
  • 使用Proxy代替Object.defineProperty实现数据响应式
  • 重写虚拟DOM的实现和Tree-Shaking
  • 更好的支持Typescript

2. 获取vue3.0

1. cdn方式

打开vue3官网->起步->安装->CDN->单击CDN的src->右键另存为(vue.global.js存到自己创建的文件夹

vue3学习全部笔记_第1张图片

DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    
    <script src="./vue.global.js">script>
head>

<body>
    
    <div id="app">
        <h1>{{msg}}h1>
    div>
body>

html>
<script>
    /*
    vue2写法:  
        new Vue({
            // 挂载应用实例
            el:"#app",
            // data可以写成一个对象
            data:{

            },
            methods: {
                
        },}) 
    */
    // 1.创建vue实例对象  
    const app = Vue.createApp({
        // data属性必须采用函数的写法
        data() {
            return {
                msg: 'hello vue3'
            }
        },
    })
    console.log(app);
    // 2.挂载应用实例
    app.mount('#app');
script>

2. vue cli脚手架方式

  • 安装最新版本的vue cli 脚手架

    npm i @vue/cli -g
    
  • 创建项目

    vue create 项目名称
    
  • 选择vue3版本的默认选项

  • 启动项目

    npm run serve
    

3. vite构建工具

vitevue官方发布的一款构建工具

vite底层不是基于webpack

vite底层是基于浏览器对ES模块语法的支持来进行项目构建, 所有构建速度很快

  • 创建项目

    npm init vite 项目名称
    
  • 安装项目依赖

    项目根目录运行初始化命令

    npm install
    // 或者
    npm i
    
  • 启动项目

    项目根目录运行启动命令

    npm run dev
    
  • 默认监听端口号3000

    http://localhost:3000
    
  • (模块化理解):

    tools.js

    export default{
        add(x,y){
            return x+y;
        },
        reduce(x,y){
            return x-y;
        }
    }
    

    index.html

    方法一:

    
     
    

    方法二:

    
    

3. 新增特性

Fragment模板碎片

  • vue2中组件的模板必须有一个唯一的根标签

  • vue3中组件模板可以有多个根标签

    Home.vue

    
    
    
    

    App.vue

    
    
     
    

    页面结果:

vue3学习全部笔记_第2张图片

Composition (组合) API

  • 作用: 将不同组件的相同部分抽离出来, 单独维护, 目的是提高代码复用率

1. setup

  • 用法: 在组件对象中添加setup方法

  • 该方法在组件创建完成之前自动调用, 所用不能在其内部使用this访问组件对象

  • 该方法中返回的数据会自动和组件对象中的data合并

  • 该方法中返回的方法会自动和组件对象中的methods合并

    export default {
        setup(){
    
        }
    }
    

    eg:

    
    
    
    

    页面结果:
    vue3学习全部笔记_第3张图片

2. reactive

  • 作用: 帮助我们创建响应式数据对象

  • 语法

    import {reactive} from 'vue';
    export default {
        setup(){
            // 创建响应式数据对象
            const obj=reactive({
    
            });
            return obj;
        }
    }
    

    eg:

    
    
    
    

3. ref

  • 作用: 基于基本数据类型(字符串, 布尔, 数值) 创建一个响应式的数据对象

  • 语法

    import {ref} from 'vue';
    
    export default {
        setup(){
            // 使用ref基于基本数据类型创建响应式数据对象
            const name=ref('张三');
            const age=ref(20);
            console.log(name);
            console.log(age);
            return {
                name,age
            }
        }
    }
    
  • 视图中引用直接通过数据名称引用即可

    {{name}}
    

    eg:

    
    
    
    

4. toRefs

  • 作用: 让reactvie方法创建的响应式数据对象, 支持ES6的解构赋值操作( reactive创建的响应式数据对象默认不支持ES6解构赋值, 因为会使其失去响应式 )
  • 语法: 参数必须是reactive创建的响应式数据对象
    import {torRefs} from 'vue';
    
    export default {
        setup(){
            // 创建响应式数据对象
            const {name,age}=toRefs(reactive({
              name:'张三',
              age:20
            }));
            return {
                name,age
            };
        }
    }
    
    eg:
    
    
    
    

computed计算属性

  • vue2
    export default {
        computed:{
            // 计算属性方法
        }
    }
    
  • vue3
    • 使用方式1

      export default {
          computed:{
              // 计算属性方法
          }
      }
      
    • 使用方式2

      import {computed} from 'vue';
      
      const computedData=computed(()=>{})
      

      eg:

      
      
      
      

watch侦听器

  • vue2
    export default {
        // 侦听器
        watch:{
    
        }
    }
    
  • vue3
    • 使用方式1

      export default {
           // 侦听器
          watch:{
      
          }
      }
      
    • 使用方式2

      • 通过watch方法创建的普通侦听器无法侦听到数组元素的变化, 必须使用深度侦听器
      • 以下补充:
      • 监听对象的某个属性
        • setup中监听对象的某个属性,监听不到
        • setup中监听对象,监听不到某个属性的新旧值变化
        • watch中监听对象的某个属性,可以监听新旧值变化
      • 监听数组添加属性
        • 能监听,但是监听不到变化
      • 备用解决思路:
        • toRefs解构reactive对象可实现监听某属性新旧值
        • 使用ref,不用reactive
      import {watch} from 'vue';
      export default {
          setup(){
              // 普通侦听器
              watch(被侦听的数据,function(value,oldValue){
      
              });
              // 深度侦听器
              watch(被侦听的数据,function(value,oldValue){
      
              },{deep:true});
          }
      }
      

      eg:

      
      
      
      

组合API中调用生命周期钩子函数

  • 如果要在setup方法中调用组件生命周期钩子函数: 在原来的生命周期钩子函数名称前加on关键, 并且需要保持小驼峰的命名方式

  • 不能在setup方法中调用beforeCreate,created者2个生命周期钩子函数 ( 因为beforeCreate,created这两个生命周期钩子函数的执行时间和setup方法接近 )

  • 注意:

    • 钩子函数:beforeDestory->beforeUnmount
    • 钩子函数:destoryed->unmounted
    • 销毁组件:this.$destory()->app.unmount()

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R6X6Qq2p-1659530104528)(https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a16c02f295714778abcbd52057a3eeee~tplv-k3u1fbpfcp-watermark.image?)]

  • 语法

    // 导入
    import {onMounted,onUpdated,onUnmounted} from 'vue';
    export default {
    setup(){
        onMounted(function(){
            console.log('组件视图挂载完成');
        });
        onUpdated(function(){
            console.log('组件更新完成');
        });
        onUnmounted(function(){
            console.log('组件卸载完成');
        });
    }
    }
    

h渲染函数

  • vue2

    系统会自动在render中注入渲染函数

    import App from './App.vue';
    new Vue({
        // h是系统自动注入的渲染函数
        render(h){
           return h(App); 	
        }
    });
    
  • vue3

    vue3中提供了一个h渲染函数, 我们需要手动导入才能使用, 系统不会自动将其注入到render中

    import { createApp,h} from 'vue'
    import App from './App.vue'
    // createApp(App).mount('#app')
    createApp({
        render(){
            // 调用渲染函数h进行组件渲染
            // return h(App);
            // h创建元素对象: h('元素名称',{/*属性集合*/},['子节点'])
            return h('h1',{style:{color:'red'}},'hello vue3');
        }
    }).mount('#app')
    

teleport: 瞬移组件的位置

  • teleport是一个vue3中提供的系统组件

  • 作用: 可以让开发者动态指定组件内的某个视图结构的挂载位置

  • 语法

    
        

函数式组件

  • 通过函数方式定义的组件

  • 特点: 函数组件默认没有状态数据和生命周期

  • 语法

    • 定义

      import { h } from 'vue';
      export default function FunctionComponent(props){
          // console.log(props);
          return h('h1',{style:{color:'red'}},props.msg);
      }
      
    • 调用

      
      

全局属性app.config.globalProperties

  • 作用: 给Vue注册全局功能( 给每一个vue组件提供全局的属性或者方法 )

  • vue2中创建vue应用

    const app=new Vue({
        
    });
    
    • vue2中给Vue注册全局功能: 在Vue的原型对象添加属性或者方法, 这样每一个vue组件都可以访问, 每一个vue组件都是Vue的实例对象( 利用面向对象的继承性 )
  • vue3中创建应用对象

    const app=Vue.createApp({
        
    });
    
    • vue3中给vue注册全局功能: 必须借助全局属性app.config.globalProperties
  • 需求: 希望在每一个vue组件中都可以通过组件对象访问axios

    • 下载安装axios

      npm i axios
      
    • 必须使用app.config.globalProperties全局注册axios

      app.config.globalPropperties.$axios=axios;
      

插件注册

  • vue2中插件注册

    Vue.use();
    
  • vue3中插件注册

    // app: 是通过Vue.createApp()方法创建的应用对象
    app.use();
    
    • 功能: 将axios自动注册成全局对象( 在每一个组件中都可以通过this来访问axios )

    • 开发vue插件

      • 函数方式

        // app: 系统自动注入, 应用对象
        // options: 调用者通过app.use()方法手动传入的配置对象(可选)
        function MyAxios(app,options){
            
        }
        
      • 对象方式

        const MyAxios={
            // app: 系统自动注入的应用对象
            // options: 调用者通过app.use()方法手动传递的配置对象(可选)
            install(app,options){
                
            }
        }
        
        // 导入axios
        import axios from 'axios';
        export default {
            // app: 系统自动注入的应用对象
            install(app){
                // 通过app.config.globalProperties全局注册axios
                app.config.globalProperties.$http=axios;
            }
        }
        

4. 更新特性

生命周期钩子函数

  • 销毁阶段生命周期钩子函数名称发生了变换

  • vue2中

    export default {
        // 销毁前
        beforeDestroy(){
            
        },
        // 销毁后
        destroyed(){
            
        }
    }
    
  • vue3中

    • vue3中从组件对象中移除了销毁组件实例的方法$destroy
    export default {
        // 销毁前
        beforeUnmount(){
            
        },
        // 销毁后
        unmounted(){
            
        }
    }
    

全局组件注册方式

  • vue2中注册全局组件

    Vue.component('组件名称',{
        /* 组件对象 */
    });
    
  • vue3中注册全局组件

    import {createApp} from 'Vue';
    // 创建实例对象
    const app=createApp();
    // 注册全局组件
    app.component('组件名称',{
        // 组件对象
    })
    

异步组件

  • vue2中
const Home=()=>import('./pages/Home.vue');
const asyncModal = {
  // vue2中通过component属性节点指定目标组件
  component: () => import('./Modal.vue'),
  // 延时时长
  delay: 200,
  // 超时时间  
  timeout: 3000,
  // 错误处理组件 
  error: ErrorComponent,
  // 加载中的组件  
  loading: LoadingComponent
}
  • vue3中
import {defineAsyncComponent} from 'vue';
const Home=defineAsyncComponent(()=>import('./pages/Home.vue'));
const asyncModalWithOptions = defineAsyncComponent({
  // vue3中通过loader属性节点指定目标组件  
  loader: () => import('./Modal.vue'),
   // 延时时长
  delay: 200,
  // 超时时间  
  timeout: 3000,
  // 错误处理组件 
  error: ErrorComponent,
  // 加载中的组件  
  loading: LoadingComponent
})

v-for指令中使用ref属性

  • vue2中

    this.$refs.list[0];
    this.$refs.list[1];
    
  • vue3中: 需要手动维护一个数组用来保存每一个子元素对象

    export default {
        data(){
            return {
                // 保存列表元素的元素对象   
                refList:[]     
            }
        },
        methods:{
            // el: 系统自动注入的参数, 子元素的元素对象
            addRef(el){
                this.refList.push(el);
            }
        },
        // 在组件更新之前, 清空数组中的元素, 否则该数组中的元素会越来越多
        beforeUpdate(){
            this.refList=[];
        }
    }
    

v-if和v-for结合使用

  • vue2中

    v-if和v-for指令同时应用于同一个元素之上, v-for指令优先级会更高, v-if会作用域v-for循环遍历产生的每一个子元素之上

  • vue3中

    v-if指令的优先级高于v-for指令, v-if指令执行, 然后执行v-for指令

自定义指令定义方式

  • vue2中

    Vue.directive('指令名称',function(el, binding, vnode){
        
    });
    
  • vue3中

    然而,在 Vue 3 中,我们为自定义指令创建了一个更具凝聚力的 API。正如你所看到的,它们与我们的组件生命周期方法有很大的不同,即使钩子的目标事件十分相似。我们现在把它们统一起来了:

    • created - 新增!在元素的 attribute 或事件监听器被应用之前调用。
    • bind → beforeMount
    • inserted → mounted
    • beforeUpdate:新增!在元素本身被更新之前调用,与组件的生命周期钩子十分相似。
    • update → 移除!该钩子与 updated 有太多相似之处,因此它是多余的。请改用 updated
    • componentUpdated → updated
    • beforeUnmount:新增!与组件的生命周期钩子类似,它将在元素被卸载之前调用。
    • unbind -> unmounted
    const app=createApp();
    app.directive('指令名称',function(el, binding, vnode){
        
    });
    

$attrs包含class&style

  • vue2中

    • this.$attrs包含调用组件的时候通过自定义属性所传递的数据, 但是不包含class属性和style属性
  • vue3中

    • this.$attrs: 调用组件的时候通过自定义属性所传递的所有数据, 包含class属性和style属性

      • 当子组件只有一个唯一的根元素的时候, 系统会将所有的自定义属性平移到组件视图的根元素上
      • 如果组件视图存在多个根元素, 则不会处理

emits属性节点

  • vue3中针对组件对象新增的属性节点

  • 作用:

    • 告诉系统组件调用标签上添加的事件是一个自定义事件, 需要通过自定义事件的方式进行触发( vue3中默认会将组件调用标签上的事件作为原生事件进行触发)
    • 避免当我们的定义的自定义事件名称和系统事件名称出现冲突的时候, vue3直接把自定义事件当做系统事件来触发
    
    

过渡动画

  1. 过渡动画选择器名称的变化

    • v-enter=>v-enter-from: 元素进入之前的过渡动画选择器名称
    • v-leave=>v-leave-from: 元素离开之前的过渡动画选择器名称
  2. transition组件属性的变化

    • enter-class=>enter-from-class: 指定元素进入之前需要的过渡动画选择器
    • leave-class=>leave-from-class: 指定元素离开之前需要的过渡动画选择器
  3. transition-group组件默认不再自动渲染一个span标签, 但是依然可以通过tag属性指定transition-group渲染的元素名称

v-model实现组件双向数据绑

  • vue2中使用v-model实现组件双向数据绑定

    
    
    1. 在组件的调用标签上添加了一个自定义属性value, 通过value属性向组件内部传递数据

    2. 在组件的调用标签上通过v-on监听了input事件

      
      
    3. 希望对v-model指令背后使用的自定义属性名称和自定义事件名称进行修改

      • 在组件内部通过model属性节点对自定义属性名称和自定义事件名称进行修改
      export default{
          model:{
              prop:'',        // 修改自定义属性名称
              event:''        // 修改自定义事件名称
          }
      }
      
  • vue3中使用v-model指令实现组件双向数据绑定

    
    
    1. 在组件的调用标签上添加了一个自定义属性modelValue, 通过modelValue向组件内部传递数据

    2. 在组件的调用标签上通过v-on监听了update:modelValue

    3. 希望对v-model指令背后的自定义属性名称和自定义事件名称进行修改

      
      
      1. 在组件内部要通过isShow来接收数据
      2. 在组件内部要通过$emit()触发事件update:isShow
    4. vue3中允许在同一个组件的调用标签上多次使用v-model指令

       
      
      1. 相当于在组件的调用标签上添加了自定义属性isShow, msg, 同时监听了两个自定义事件update:isShowupdate:msg

5. 移除特性

$children属性

  • vue2中可以通过组件属性$children获取子组件的组件对象
  • vue3中建议使用ref属性来操作子组件

native事件修饰符

  • vue2中可以通过native事件修饰符修饰某个事件, 被修饰的事件将被作为原生事件处理, 可以在子组件的内部使用原生方式对其进行触发

  • vue3中移除了native事件修饰符

  • vue3中如果希望某个事件可以在子组件的内部被当做原生事件来处理?

    • 在vue3中组件调用标签上注册的事件, 默认都会当做原生的事件进行触发

    • 在vue3中如果我们希望组件调用标签上所注册的事件是一个自定义事件, 可以在组件内部通过属性节点emits来进行声明, 在emits属性节点中生命过的事件就不会当做系统事件来处理

      export default {
          // 此处声明过的事件, 会认为是自定义事件, 必须通过自定义事件的方式进行触发, 即使事件明层和系统事件名称冲突, 也不会通过系统事件的触发方式触发该事件
          emits:['click']
      }
      

filter过滤器

  • vue2中过滤器的使用

    • 作用: 对视图中即将输出的数据进行预处理

    • 定义

      • 全局过滤器: 在全局作用域内都可以使用
      // data: 系统自动注入, 待处理的数据
      Vue.filter('过滤器名称',function(data){
         // 必须返回处理结果      
      });
      
      • 私有过滤器: 只能在定义地方使用
      export default {
          filters:{
              // data: 系统自动注入, 待处理的数据
              过滤器名称:function(data){
                  // 必须返回处理结果             
              }
          }
      }
      
    • 使用: 只能在插值表达式和v-bind指令中使用

      {{待处理数据 | 过滤器名称}}
      
  • vue3中建议使用自定义方法或者computed计算属性来代替过滤器

vm.$set(Vue.set)

  • vue2中可以使用vm.$set方法解决通过数组下标方式向数组中添加元素, 视图不更新的问题

    vm.$set(目标数组,数组下标,数组元素);
    
    vm.$set(目标对象,属性名,属性值);
    
  • vue3中移除实例方法vm.$set和静态方法Vue.set

vm.$destroy

  • vue2中, 可以通过实例方法$destroy销毁vue组件
  • vue3中移除实例方法$destroy,

vm.$on

  • vue2中, 可以通过$on方法监听自定义事件
  • vue3中, 移除了 o n 方法 , 但是 on方法, 但是 on方法,但是emit方法没有移除

vm.$once

  • vue2中, 可以通过$once方法监听自定义事件, 但是只能监听一次
  • vue3中, $once方法被移除了

vm.$off

  • vue2中可以通过$off方法注销一个自定义事件
  • vue3中$off方法被移除了

6. vue-router路由模块

vue2中路由的使用流程

  1. 下载安装

    npm i vue-router
    
  2. 导入路由模块

    import Router from 'vue-router';
    
  3. 注册插件

    Vue.use(Router);
    
  4. 创建路由实例对象

    const router=new Router({
        routes:[],  // 引用路由规则数组
        mode:'hash'     // 指定路由模式, 可选值hash(默认路由模式),history
    });
    
  5. 挂载路由实例对象

    new Vue({
        el:'#app',
        router      // 挂载路由实例对象
    });
    
  6. 在根组件中添加路由占位符

    
    

vue3中路由模块的使用流程

  1. 下载安装

    npm i vur-router@next
    
  2. 导入路由模块

    import {createRouter,createWebHashHistory,createWebHistory} from 'vue-router';
    
  3. 创建路由实例

    const router=createRouter({
        routes:[],      // 路由规则
        //必须手动指定路由模式, createWebHashHistory: 提供的是访问地址带#的路由模式
        // createWebHistory: 提供的是访问地址不带#的路由模式
        history:createWebHashHistory()
    });
    
  4. 注册路由实例

     //app: 通过Vue.createApp()创建的应用实例
    app.use(router);
    
  5. 在根组件中添加路由占位符

    
    

路由传参

动态路由

  • 定义动态路由规则

    const routes=[
        {
            path:'/goods/:id',
            component:Goods
        }
    ]
    
  • 进行路由传参

    
    
  • 获取动态路由参数

    this.$route.params.id
    

查询字符串方式

  • 在页面访问地址中拼接查询字符串

    新闻详情
    
  • 在目标页面中获取查询字符串参数

    this.$route.query.id
    this.$route.query.title
    

嵌套路由

  • 配置嵌套路由规则

    const routes=[
        {
            path:'/ucenter',
            component:Ucenter,
            // 嵌套路由规则
            children:[
                {
                    name:'order',
                    path:'/order',
                    component:Order
                },
                {
                    name:'address',
                    path:'/Address',
                    component:Address
                }
            ]
        }
    ]
    
  • 父级路由对应的视图中添加二级路由占位符

    
    

7. element-plus组件库

下载安装

npm i element-plus

完整导入

  • 将element-plus组件库中提供的所有组件全部导入我们自己的vue3的项目中

  • 缺点: 导致项目最终构建出来的文件体积过大, 性能不好

    main.js

    // 导入element-plus核心文件
    import Element from 'element-plus';
    // 导入element-plus的样式文件
    import 'element-plus/dist/index.css';
    // 全局注册组件库
    const app=Vue.createApp(App);
    app.use(Element);
    

按需导入(vite)

  1. 安装一个开发依赖

    npm i unplugin-vue-components
    
  2. 在项目配置文件中添加配置项

    vite.config.js

    import { defineConfig } from 'vite'
    import vue from '@vitejs/plugin-vue'
    ​
    +import Components from 'unplugin-vue-components/vite'
    +import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
    ​
    // https://vitejs.dev/config/
    export default defineConfig({
      plugins: [
        vue(),
       + Components({
       +   resolvers: [ElementPlusResolver()],
       + }),
      ]
    })
    ​
    
  3. 重启开发服务器

    npm run dev
    

按需导入(vue-cli)

  • 安装插件

    npm install unplugin-vue-components
    
  • 修改项目配置文件(webpack进行配置)

    vue.config.js

    const Components = require('unplugin-vue-components/webpack')
    const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')
    module.exports={
        // webpack的配置节点
        configureWebpack:{
            plugins: [
                Components({
                  resolvers: [ElementPlusResolver()],
                }),
              ]
        }
    }
    
  • 重启开发服务器

    npm run serve
    

8. vuex状态管理工具

vue2中使用vuex状态管理工具

  1. 下载安装

    npm i vuex
    
  2. 导入

    import Vuex from 'vuex'
    
  3. 注册

    Vue.use(Vuex)
    
  4. 创建数据仓储对象

    const store=new Vuex.Store({
        state:{
            // 状态数据
        },
        mutaionts:{
            // 操作state状态数据的同步方法
        },
        actions:{
            // 发送数据请求的异步方法
        },
        getters:{
            // 计算属性方法
        },
        modules:{
            // 子模块
        }
    })
    
  5. 挂载数据仓储对象

    /mian.js

    new Vue({
        // 注册数据仓储对象
        store
    });
    
  6. 在组件中使用数据仓储对象

    this.$store
    

vue3中使用vuex状态管理工具

  1. 下载安装

    npm i vuex@next
    
  2. 导出

    import {createStore} from 'vuex';
    
  3. 创建数据仓储对象

    const store=createStore({
        state:{
            // 状态数据
        },
        mutations:{
            // 操作state状态数据的同步方法
        },
        actions:{
            // 发送数据请求的异步方法
        },
        getters:{
            // 计算属性方法
        },
        modules:{
            // 子模块
        }
    });
    
  4. 注册仓储对象

    // app:Vue.createApp()创建的应用对象
    app.use(store);
    

9. 案例

留言板案例


参考文档

你可能感兴趣的:(学习,vue,前端)