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 打包

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/14327.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

每日一题(1)

在看一本08年出版的书的时候&#xff0c;看到了这样一个问题&#xff0c;感觉答案很奇怪&#xff1a; public class demo_p22 {public static void main(String args[]){int sCook1,sFish2;//各技能标记character ch1new character();if(ch1.haveSkill(sCook))System.out.print…

【CSP CCF记录】202012-2 期末预测之最佳阈值

题目 过程 思路 第一次没用前缀和&#xff0c;暴力求解得50分。 采用前缀和方法。 1. 对原数组stu[i]进行排序。 2. 计算前缀和数组s[]&#xff0c;s[i]表示安全指数的y_i的前缀和&#xff0c;即安全指数小于等于y_i时的实际挂科情况&#xff0c;y_i之前有多少个未挂科&am…

无线领夹麦克风哪个品牌好?无线麦克风品牌排行榜前十名推荐

​在当今的数字化浪潮中&#xff0c;个人声音的传播和记录变得尤为重要。无论是会议中心、教室讲台还是户外探险&#xff0c;无线领夹麦克风以其卓越的便携性和连接稳定性&#xff0c;成为了人们沟通和表达的首选工具。面对市场上琳琅满目的无线麦克风选择&#xff0c;为了帮助…

Python筑基之旅-MySQL数据库(三)

目录 一、数据库操作 1、创建 1-1、用mysql-connector-python库 1-2、用PyMySQL库 1-3、用PeeWee库 1-4、用SQLAlchemy库 2、删除 2-1、用mysql-connector-python库 2-2、用PyMySQL库 2-3、用PeeWee库 2-4、用SQLAlchemy库 二、数据表操作 1、创建 1-1、用mysql-…

记录Python低代码开发框架zdppy_amcrud的开发过程

实现新增接口 基础代码 import env import mcrud import api import snowflakeenv.load(".env") db mcrud.new_env()table "user" columns ["name", "age"]async def add_user(req):data await api.req.get_json(req)values [d…

SkyEye对接CANoe:助力汽车软件功能验证

01.简介 CANoe&#xff08;CAN open environment&#xff09;是德国Vector公司专为汽车总线设计而开发的一款通用开发环境&#xff0c;作为车载网络和ECU开发、测试和分析的专业工具&#xff0c;支持从需求分析到系统实现的整个系统的开发过程。CANoe丰富的功能和配置选项被OE…

虚拟ECU:彻底改变汽车软件开发与测试

汽车开发领域有着垂直性较强的一系列需求&#xff0c;其中最为瞩目的需求之一就是对安全高效的软件测试方法的需求。传统的汽车开发偏向使用硬件原型与真实ECU进行软件测试&#xff0c;但由于硬件设备往往在开发周期的中后阶段才生产完成&#xff0c;给汽车开发带来了成本与时间…

电商内卷时代,视频号小店凭借一己之力“脱颖而出”

大家好&#xff0c;我是电商笨笨熊 今年618各大电商平台花样百出&#xff1b; 某宝更是直接取消了“预售”&#xff0c;从5月就开始进入618预热期&#xff1b; 不少玩家既开心又难过&#xff0c;市场如此内卷&#xff0c;618确实是个爆发期&#xff0c;但更多的需要不断压低…

Star CCM+分配零部件至区域后交界面丢失-更新找回

前言 在工程应用中&#xff0c;将零部件分配至区域后&#xff0c;一般常规的操作需要对交界面进行检查。偶尔会发现交界面丢失。遇到此类问题&#xff0c;在没有做其他操作前&#xff08;比如画网格&#xff09;&#xff0c;可以选择先删除所有区域在重新分配至区域。若已经进…

基于SSM的大学生兼职管理系统

基于SSM的大学生兼职管理系统的设计与实现~ 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringSpringMVCMyBatis工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 登录界面 企业界面 前台学生界面 管理员界面 摘要 随着大学生兼职市场的日益繁…

K8s 高级调度

文章目录 K8s 高级调度CronJobinitContainerTaint 和 Toleration污点&#xff08;Taint&#xff09;容忍&#xff08;Toleration&#xff09; AffinityNodeAffinityPodAnffinity 和 PodAntiAffinity 总结 K8s 高级调度 CronJob 在 k8s 中周期性运行计划任务&#xff0c;与 li…

【vue echart】完成一个简单echart图表+自适应

实现效果&#xff1a; html&#xff1a; <divref"echartOne"id"echartOne"style"width: 100%; height: 100%" ></div> js: getEchartOne() {let chart this.$echarts.init(this.$refs.echartOne);chart.setOption({title: {text:…

云原生|为什么服务网格能够轻松重塑微服务?一文讲清楚!

目录 一、概述 二、 设计 三、服务网格 四、总结 一、概述 容器化技术与容器编排推动了微服务架构应用的演进&#xff0c;于是应用的扩展与微服务的数量日益增加&#xff0c;新的问题随之而来&#xff0c;监控服务的性能变得越来越困难&#xff0c;微服务与微服务之间相互通…

Kafka-集群管理者(Controller)选举机制、任期(epoch)机制

Kafka概述 Kafka-集群管理者&#xff08;Controller&#xff09;选举机制 Kafka中的Controller是Kafka集群中的一个特殊角色&#xff0c;负责对整个集群进行管理和协调。Controller的主要职责包括分区分配、副本管理、Leader选举等。当当前的Controller节点失效或需要进行重新…

嵌入式实时操作系统笔记1:RTOS入门_理解简单的OS系统

今日开始学习嵌入式实时操作系统RTOS&#xff1a;UCOS-III实时操作系统 本次目标是入门RTOS&#xff0c;理解多任务系统...... 本文只是个人学习笔记&#xff0c;基本都是对网上资料的整合...... 目录 STM32裸机与RTOS区别&#xff1a; 裸机中断示例&#xff1a; RTOS对优先级…

Spring MVC/Web

1.Spring MVC 的介绍 Spring Web MVC是基于Servlet API构建的原始Web框架&#xff0c;也是Spring框架的一部分。它提供了灵活可扩展的MVC架构&#xff0c;方便开发者构建高性能的Web应用程序&#xff0c;并与 Spring 生态系统无缝集成。 2.MVC 设计模式 MVC&#xff08;Model…

设计模式—23种设计模式重点 表格梳理

设计模式的核心在于提供了相关的问题的解决方案&#xff0c;使得人们可以更加简单方便的复用成功的设计和体系结构。 按照设计模式的目的可以分为三大类。创建型模式与对象的创建有关&#xff1b;结构型模式处理类或对象的组合&#xff1b;行为型模式对类或对象怎样交互和怎样…

研发机构大数据迁移如何保障敏感数据不泄露

随着云计算和大数据技术的飞速进步&#xff0c;越来越多的企业正试图通过数据迁移来提升IT基础设施的效率&#xff0c;减少成本&#xff0c;并增强业务的灵活性。但是&#xff0c;这一过程并非没有它的挑战&#xff0c;尤其是在数据安全方面。数据在转移过程中可能会遭遇黑客攻…

解决深度确定问题:使用不相交集合森林

解决深度确定问题&#xff1a;使用不相交集合森林 引言不相交集合森林&#xff08;DSF&#xff09;基础按秩合并与路径压缩深度确定问题的解决方案实现MAKE-TREE修改FIND-SET实现FIND-DEPTH实现GRAFT分析最坏情况运行时间结论参考文献 引言 在计算机科学中&#xff0c;树结构是…

时空扭曲:重温相对论的终极挑战,探寻真理的脚步

大家都知道&#xff0c;相对论是爱因斯坦提出的划时代理论&#xff0c;为人类认知时空和引力做出了革命性贡献。但这个理论真的万无一失吗&#xff1f;近日&#xff0c;一项新研究提出了测试时间扭曲的新方法&#xff0c;或许能让我们重新审视相对论在宇宙大尺度上的适用性。 时…