vue3 基础

Vue3 语法

第一步:

/**
* 首先要求引入 defineComponent 和 可选的 ref
* defineComponent 用于解决 Ts 下传统的 Vue.extends 无法对组件给出正确参数类型推断
* 即 在 ts 环境中如果参数类型推断不对, 使用 defineComponent 包装
*/
import { defineComponent, ref } from "vue";
export default defineComponent({
})

Setup & ref 方法

/**
* 有了 Setup 方法
* 无需再写 data methods 等对象
*
* 要在 template 中使用变量 必须先使用 ref 包装变量
* 在 script 中 通过 变量名.value 访问
* 在 template 中 可以直接通过 变量名 访问
*/  
import {defineComponent, ref} from 'vue'

export default defineComponent({
    name: 'app',
    props: {
        name: {
            type: string,
            default: 'abcd'
        }
    },
    /**
    * setup 方法 有两个参数
    * props 和 context 两个参数
    * context 是一个对象
    * 有 attrs、 slots、emit、expose
    * attrs 等于 $attrs
    * slots 等于 $slots
    * emit 等于 $emit
    * expose 暴露公共 property (函数)
    */
    Setup (props, context) {
        const name = ref('名称')
        const click = function () {
            console.log(abcd)
        }
        const abcd = props.name // abcd


        // 只有通过 return 返回的 才能在 外部访问
        // abcd 没有 return 因此在 template 中无法访问
        return {
            name,
            click
        }
    }
})

reactive 方法

/**
* reactive 接收一个对象作为参数
* 无论变量或方法 都可以作为 Object 的属性
*/

import {ref, reactive} from 'vue'
export default {
    name: 'app',
    setup () {
        const obj = reactive({
            name: ['1', '2', '3'],
            click: index => obj.name[index]
        })
        return {
            data
            // name: data.name,
            // click: data.click
        }
    }
}

Vue3 + TypeScript 类型注释

/**
* 先定义一个接口作为规范
*/
interface DataProp {
    name: string
    age: number
    work: string[]
}


export default {
    name: 'app',
    setup () {
        // 使用接口
         const data: DataProp = {
             name: 'a',
             age: 1,
             work: ['2']
         }
    }
}

toRefs 方法

/**
* 输出变量都用 data 会很麻烦
* 但是 使用 ... 运算符会导致变量不再有响应式功能
* toRefs 解决了这个问题
*/
import {reactive, toRefs} from 'vue'

export default {
    setup () {
        const data = reactive({
            name: 'abcd'
        })
        const refData = toRefs(data)
        return {
            // 进行解构
            // 可以在 template 中 直接通过 name 访问 data.name
            ...refData
        }
    }
}

关于 ref 和 reactive

都可以使用,作用都是生成响应式对象,目前只是编写方式不同


Vue3 的生命周期和钩子函数

Vue2 的生命周期方法也可以在 setup() 函数中编写,使用

需要通过 import 从 vue 中导入

都接收一个回调函数作为参数

| 生命周期 | 描述 |
| ——– | ———————————————————— |
| setup() | 在创建组件之前 在 beforeCreate 和 created 前执行 创建 data method |
| onBeforeMount() |组件挂载到节点上之前执行|
| onMounted() |组件挂载完成执行|
| onBeforeUpdate() |组件更新前执行|
| onUpdated() |组件更新后执行|
| onBeforeUmmount() |组件卸载前执行|
| onUmmounted() |组件卸载后执行|
| onActivated() |包含在 `<keep-alive>` 中的组件 会多次两个生命周期钩子函数 被激活执行|
| onDeactivated() |组件切换时,旧组件消失时执行|
| onErrorCaptured() |捕获一个来自子孙组件的异常时执行|
| onRenderTracked |状态跟踪,会跟踪页面上所以响应式变量和方法的状态,也就是 return 的值都会追踪,只要页面有 update 的情况就会跟踪并生成 event 对象 可以通过 event 对象查找问题所在|
| onRenderTriggered |状态触发,不会跟踪值,而是给予变化值的信息,并将新旧值明确列出|

`<keep-alive>` 中的组件会将数据保存在 内存中

Vue3 Watch

/**
* watch 需要导入才能使用
*/
import {..., watch} from 'vue'

export default {
    setup () {
        const data = reactive({
            name: 'wa',
            age: 2
        })

        // 单个值 
        // watch (data.name, (newValue, oldValue) => {})
        // 多个值时 传入数组 而非多写 watch 返回的也是数组 n[index], o[index]
        // 错误 
        // watch ([data.name, data.age], (n, o) => {})
        // vue3 不能监听 reactive 中的值 需要函数返回
        watch(() => ...data, (n, o) => {})

        return {
            data
        }
    }
}

独立模块化

/**
* 更新时间模块
* filename: useUpdateTime.ts
* 需要通过 import 导入 ref
* 并通过 export 导出
*/

import { ref } from 'vue'

const getNowTime = () => {
    const now = new Date();
    const hour = now.getHours() < 10 ? "0" + now.getHours() : now.getHours();
    const minu =
        now.getMinutes() < 10 ? "0" + now.getMinutes() : now.getMinutes();
    const sec =
        now.getSeconds() < 10 ? "0" + now.getSeconds() : now.getSeconds();
    nowTime.value = hour + ":" + minu + ":" + sec;

    setTimeout(getNowTime, 1000);
};

export { nowTime, getNowTime }

Teleport 瞬间移动

可以将组件挂载到任何想挂载的 DOM 上 , 而不必嵌套在 #app 中

<!-- DOM-ID 为 需要挂载的 DOM 的 id 值 -->

<template>
    <teleport to="DOM-ID">
        <model/>
    </teleport>
</template>

Suspense 异步请求组件

Suspense 组件提供两个 template 位置 一个是请求没有返回时的内容,一个是请求完成的内容

如果使用 Suspense ,要返回一个 promise 对象 而非 JSON 对象

<template>
    <Suspense>
        <template #default>
            加载完成
        </template>
        <template #fallback>
            加载中...
        </template>
    </Suspense>
</template>

处理异常请求错误

在 vue3 中 可以使用 onErrorCaptured 捕获异常

import { ref, onErrorCaptured } from 'vue'

export default {
    setup(){
        onErrorCaptured(error => console.log(error))
    }
}

使用 Pages 开发多页应用

单页应用和多页应用的区别在于

  • 单页应用只加载一次公共组件资源,仅会刷新局部资源
  • 多页应用每切换一个页面就要重新加载所有资源

| | 单页面应用(SinglePage Web Application,SPA) | 多页面应用(MultiPage Application,MPA) |
| —- | ——————————————— | ————————————— |
| 组成| 一个外壳页面和多个页面片段组成 | 多个完整页面构成 |
| 资源共用(css,js) | 共用,只需在外壳部分加载 | 不共用,每个页面都需要加载 |
| 刷新方式 | 页面局部刷新或更改 | 整页刷新 |
| url模式 | a.com/#/pageone a.com/#/pagetwo | a.com/pageone.html a.com/pagetwo.html |
| 用户体验 | 页面片段间的切换快,用户体验良好 | 页面切换加载缓慢,流畅度不够,用户体验比较差 |
| 转场动画 | 容易实现 | 无法实现 |
| 数据传递 | 容易 | 依赖 url传参、或者cookie 、localStorage等 |
| 搜索引擎优化(SEO) | 需要单独方案、实现较为困难、不利于SEO检索 可利用服务器端渲染(SSR)优化 | 实现方法简易 |
| 试用范围 | 高要求的体验度、追求界面流畅的应用 | 适用于追求高度支持搜索引擎的应用 |
| 开发成本 | 较高,常需借助专业的框架 | 较低 ,但页面重复代码多 |
| 维护成本 | 相对容易 | 相对复杂 |

单页面应用时,vue 项目中会有一个入口文件 main.js

则构建多页应用时,会有多个入口文件

  • 在 src 文件夹下 创建 pages 文件夹存放子页面

  • 在 pages 下新建文件夹 childPages(可自定义的文件夹名称,与页面名称一致) 表示子页面

  • 在 childPages 文件夹下创建文件夹 components、views,根组件 childPages.vue 和 入口文件 childPages.js

  • 然后在 public 文件夹下创建 childPages.html 表示子页面主体

  • 静态资源、路由、store最好通用,静态资源存放在 src/assets/ 下 如果每个子页面创建一个静态资源文件夹,打包时会出问题

  • 修改子页面入口文件夹

    // childPages.js
    import { createApp } from 'vue'
    import childPages from './childPages.vue'
    import router from '@/router'
    import store from '@/store'
    
    createApp(childPages).use(store).use(router).mount('#app')
    
  • 然后配置 vue.config.js

    // vue.config.js
    // 没有则在根目录下创建
    
    module.exports = {
        pages: {
            // 主页
            index: {
                // 入口文件
                entry: './src/main.js',
                // html 文件
                template: './public/index.html',
                // 页面标题
                title: '首页'
            },
            // 其他页面
            childPages: {
                entry: './src/pages/childPages/childPages.js',
                template: './public/childPages.html',
                title: '子页面'
            }
        }
    }
    
  • 设置多页应用时,不能配置 publicPath 为 ./ 否则无法访问其他页面


vue3 基础
http://localhost:8080/archives/561ac5b2-26d5-4df7-8e9e-dd433bd56290
作者
inksha
发布于
2024年09月14日
许可协议