vuejs路由和组件系统

2024-05-24 18:52

本文主要是介绍vuejs路由和组件系统,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前端路由原理

  • createRouter

    * hash* window.addEventListener('hashChange')*	两种实现路由切换的模式:UI组件(router-link,router-view),Api(push()方法)
    * history * HTML5新增的API ,可以通过不刷新页面前提下,修改页面路由-history.pushState() 
    
  • useRouter

  • router-link

  • router-view

手写实现一个路由跳转
/*** mini 版本 vue-router*/import { ref, provide, inject } from 'vue';
import RouterLink from './router-link.vue';
import RouterView from './router-view.vue'// 保证全局唯一性,可以用 Symbol 创建
const ROUTER_KEY = '__router__'// 
class Router {constructor(options) {// 记录访问历史this.history = options.history;// 初始化传入路由表this.routes = options.routes;// 当前激活的路由this.current = ref(this.history.url)// hashChange 事件触发把当前激活路由的值记录下来this.history.bindEvents(() => {this.current.value = window.location.hash.slice(1)})}push(to) {location.hash = '#' + to;window.history.pushState({}, '', to)}beforeEach(fn) {this.guards = fn;}// app 插件的注册调用函数// provie/inject,pinia install(app) {app.provide(ROUTER_KEY, this)// 兼容 options APIapp.$router = this;// 注册全局组件app.component('router-link', RouterLink)app.component('router-view', RouterView)}
}// 1. hash
// hashChange -> View 
function createWebHashHistory() {function bindEvents(fn) {window.addEventListener('hashchange', fn)}return {bindEvents,url: window.location.hash.slice(1) || '/'}
}// TODO
function createWebHistory() {}// 组合式 API,获取当前 vue-router 的实例
// options API, this.$router 来获取vue-router 的实例
function useRouter() {return inject(ROUTER_KEY)
}// 暴露一个创建对应类的实例的方法
function createRouter(options) {return new Router(options)
}export { createRouter, useRouter, createWebHashHistory }

router-link

<template><a :href="'#' + props.to"><slot /></a>
</template><script setup>// a -> href
// router-link to
import { defineProps } from 'vue';let props = defineProps({to: { type: String, required: true }
})</script><style lang="css" scoped></style>

router-view

<template><!-- 动态组件 --><component :is="comp"></component>
</template><script setup>import { computed } from 'vue'
import { useRouter } from './mini-router'// 获取到了 Router 的实例
let router = useRouter();console.log('router 实例', router)const comp = computed(() => {// 根据注册的路由表和当前激活的 route 匹配const route = router.routes.find(route => {// 百分百等于,静态路由return route.path === router.current.value})// 路由守卫的激活const ret = route?.guardsreturn route.component;
})</script><style lang="scss" scoped></style>
特性原理解析
  • 路由匹配规则:静态路由、动态路由、正则匹配

    const router = new VueRouter({routes: [// 动态路径参数 以冒号开头{ path: '/user/:id', component: User }]})
    
  • 嵌套路由:

    const router = new VueRouter({routes: [{path: '/user/:id',component: User,children: [{// 当 /user/:id/profile 匹配成功,// UserProfile 会被渲染在 User 的 <router-view> 中path: 'profile',component: UserProfile},{// 当 /user/:id/posts 匹配成功// UserPosts 会被渲染在 User 的 <router-view> 中path: 'posts',component: UserPosts}]}]})
    
  • 路由守卫:
    在这里插入图片描述

  • 路由元信息:路由表中配置meta字段

  • 滚动行为记录:这个功能只在支持 history.pushState 的浏览器中可用。

const router = new VueRouter({routes: [...],scrollBehavior (to, from, savedPosition) {// return 期望滚动到哪个的位置}
})
  • 路由懒加载和异步组件
const Foo = () => import('./Foo.vue')
把组件按组分块
const Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue')
const Bar = () => import(/* webpackChunkName: "group-foo" */ './Bar.vue')
const Baz = () => import(/* webpackChunkName: "group-foo" */ './Baz.vue')
  • 过渡动效
<transition><router-view></router-view>
</transition><!-- 使用动态的 transition name -->
<transition :name="transitionName"><router-view></router-view>
</transition>
内置组件
  • 异步组件 defineAsyncComponent 、 <component :is=“xxx” / >
import { defineAsyncComponent } from 'vue'
const AsyncHelloWorld = defineAsyncComponent({//es6 importloader:()=>import('xxx.vue'),loadingComponent:LoadingComp,delay:100,timeout:300,errorComponent:xxx
})

异步组件的实现

// 异步组件的实现
// options = object {
//  loader: () => Promoise(void)
// }
// options 
function defineAsyncComponent(options) {if (typeof options === 'function') {options = {loader: options,};}const { loader } = options;let InnerComp = null;// 记录重试次数let retries = 0;// 封装 load 函数用来加载异步组件function load() {return (loader()// 捕获加载器的错误.catch((err) => {// 如果用户指定了 onError 回调,则将控制权交给用户if (options.onError) {// 返回一个新的 Promise 实例return new Promise((resolve, reject) => {// 重试方法const retry = () => {resolve(load());retries++;};// 失败const fail = () => reject(err);// 作为 onError 回调函数的参数,让用户来决定下一步怎么做options.onError(retry, fail, retries);});} else {throw error;}}));};// 创建一个 vue 组件return {name: 'AsyncComponentWrapper',setup() {// 标识异步组件是否加载成功const loaded = ref(false);const error = shallowRef(null);const loading = ref(false);// timeout 默认不超时const timeout = ref(false);let loadingTimer = null;if (options.delay) { // 100ms loadingTimer = setTimeout(() => {loading.value = true;}, options.delay);} else {loading.value = true;}let timer = null// 用户配置参数 timeoutif(options.timeout) {timer = setTimeout(() => {timeout.value = true;}, options.timeout);}onUmounted(() => clearTimeout(timer))// 调用 load 函数加载组件// import(), ES6load().then((c) => {InnerComp = c;loaded.value = true;}).catch((err) => {error.value = err;}).finally(() => {loading.value = false;clearTimeout(loadingTimer);});// 占位内容...const Placeholer = { type: Text, children: '' }if(loaded.vlaue) {// 异步组价加载成功,渲染 InnerComp,否则渲染渲染出错组件return {type: InnerComp,}} else if(timeout.value && options.errorComponent) {// 超时,并且设置了 Error 组件return {type: options.errorComponent,}        } else if(error.value && options.errorComponent) {return {type: options.errorComponent,}}return Placeholer},};
}// load 函数接收一个 onError 回调函数
function load(onError) {// 请求接口,得到 Promise 实例const p = fetch(100);// 捕获错误return p.catch((err) => {// 当错误发生时,返回一个新的 Promise 实例,并调用 onError 回调,// 同时将 retry 函数作为 onError 回调的参数return new Promise((resolve, reject) => {// retry 函数,用来执行重试的函数,执行该函数会重新调用 load 函数并发送请求const retry = () => resolve(load(onError));const fail = () => reject(err);onError(retry, fail);});});
}function fetch(ms) {return new Promise((resolve, reject) => {// 请求会在  秒后失败setTimeout(() => {reject('err');}, ms);});
}
  • KeepAlive 组件
  • Teleport 组件
<Teleport to="body"><div v-if="open" class="modal"><p>Hello from the modal!</p><button @click="open = false">Close</button></div>
</Teleport>
  • Transition 组件
    < Transition> 会在一个元素或组件进入和离开 DOM 时应用动画
<Transition name="fade">...
</Transition>
.fade-enter-active,
.fade-leave-active {transition: opacity 0.5s ease;
}.fade-enter-from,
.fade-leave-to {opacity: 0;
}
使用场景
  • keep-alive,多标签页交互,多 tab 切换
  • teleport,全局弹窗,dom 结构脱离组件树渲染
  • transition,实现组件过渡动画
  • defineAsyncComponent,声明一个异步组件,实现性能优化和分 chunk 打包

这篇关于vuejs路由和组件系统的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/999240

相关文章

CSS3 布局样式及其应用举例

《CSS3布局样式及其应用举例》CSS3的布局特性为前端开发者提供了无限可能,无论是Flexbox的一维布局还是Grid的二维布局,它们都能够帮助开发者以更清晰、简洁的方式实现复杂的网页布局,本文给... 目录深入探讨 css3 布局样式及其应用引言一、CSS布局的历史与发展1.1 早期布局的局限性1.2

使用animation.css库快速实现CSS3旋转动画效果

《使用animation.css库快速实现CSS3旋转动画效果》随着Web技术的不断发展,动画效果已经成为了网页设计中不可或缺的一部分,本文将深入探讨animation.css的工作原理,如何使用以及... 目录1. css3动画技术简介2. animation.css库介绍2.1 animation.cs

CSS引入方式和选择符的讲解和运用小结

《CSS引入方式和选择符的讲解和运用小结》CSS即层叠样式表,是一种用于描述网页文档(如HTML或XML)外观和格式的样式表语言,它主要用于将网页内容的呈现(外观)和结构(内容)分离,从而实现... 目录一、前言二、css 是什么三、CSS 引入方式1、行内样式2、内部样式表3、链入外部样式表四、CSS 选

使用雪花算法产生id导致前端精度缺失问题解决方案

《使用雪花算法产生id导致前端精度缺失问题解决方案》雪花算法由Twitter提出,设计目的是生成唯一的、递增的ID,下面:本文主要介绍使用雪花算法产生id导致前端精度缺失问题的解决方案,文中通过代... 目录一、问题根源二、解决方案1. 全局配置Jackson序列化规则2. 实体类必须使用Long封装类3.

PyQt6中QMainWindow组件的使用详解

《PyQt6中QMainWindow组件的使用详解》QMainWindow是PyQt6中用于构建桌面应用程序的基础组件,本文主要介绍了PyQt6中QMainWindow组件的使用,具有一定的参考价值,... 目录1. QMainWindow 组php件概述2. 使用 QMainWindow3. QMainW

ubuntu20.0.4系统中安装Anaconda的超详细图文教程

《ubuntu20.0.4系统中安装Anaconda的超详细图文教程》:本文主要介绍了在Ubuntu系统中如何下载和安装Anaconda,提供了两种方法,详细内容请阅读本文,希望能对你有所帮助... 本文介绍了在Ubuntu系统中如何下载和安装Anaconda。提供了两种方法,包括通过网页手动下载和使用wg

ubuntu系统使用官方操作命令升级Dify指南

《ubuntu系统使用官方操作命令升级Dify指南》Dify支持自动化执行、日志记录和结果管理,适用于数据处理、模型训练和部署等场景,今天我们就来看看ubuntu系统中使用官方操作命令升级Dify的方... Dify 是一个基于 docker 的工作流管理工具,旨在简化机器学习和数据科学领域的多步骤工作流。

Nginx部署React项目时重定向循环问题的解决方案

《Nginx部署React项目时重定向循环问题的解决方案》Nginx在处理React项目请求时出现重定向循环,通常是由于`try_files`配置错误或`root`路径配置不当导致的,本文给大家详细介... 目录问题原因1. try_files 配置错误2. root 路径错误解决方法1. 检查 try_f

使用Python和SQLAlchemy实现高效的邮件发送系统

《使用Python和SQLAlchemy实现高效的邮件发送系统》在现代Web应用中,邮件通知是不可或缺的功能之一,无论是订单确认、文件处理结果通知,还是系统告警,邮件都是最常用的通信方式之一,本文将详... 目录引言1. 需求分析2. 数据库设计2.1 User 表(存储用户信息)2.2 CustomerO

在React聊天应用中实现图片上传功能

《在React聊天应用中实现图片上传功能》在现代聊天应用中,除了文字和表情,图片分享也是一个重要的功能,本文将详细介绍如何在基于React的聊天应用中实现图片上传和预览功能,感兴趣的小伙伴跟着小编一起... 目录技术栈实现步骤1. 消息组件改造2. 图片预览组件3. 聊天输入组件改造功能特点使用说明注意事项