router实现原理

编程入门 行业动态 更新时间:2024-10-10 13:18:42

router实现<a href=https://www.elefans.com/category/jswz/34/1770123.html style=原理"/>

router实现原理

目录

  • about.html
  • detail.html
  • home.html
  • index.html
  • router.js
index.html
<!DOCTYPE html>
<html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title></title>
</head><body><div class="product-item">测试的产品</div><div class="flex"><ul class="menu-x"><c-link to="/" class="c-link">首页</c-link><c-link to="/about" class="c-link">关于</c-link></ul></div><div><c-router><c-route path="/" component="home" default></c-route><c-route path="/detail/:id" component="detail"></c-route><c-route path="/about" component="about"></c-route></c-router></div>
</body>
<script src="./router.js"></script></html>
router.js
const oriPushState = history.pushState;// 重写pushState
history.pushState = function (state, title, url) {// 触发原事件oriPushState.apply(history, [state, title, url]);// 自定义事件var event = new CustomEvent("c-popstate", {detail: {state,title,url}});window.dispatchEvent(event);
}// <c-link to="/" class="c-link">首页</c-link>
class CustomLink extends HTMLElement {connectedCallback() {this.addEventListener("click", ev => {ev.preventDefault();const to = this.getAttribute("to");// 更新浏览历史记录history.pushState("", "", to);})}
}
window.customElements.define("c-link", CustomLink);// 优先于c-router注册
// <c-toute path="/" component="home" default></c-toute>
class CustomRoute extends HTMLElement {#data = null;getData() {return {default: this.hasAttribute("default"),path: this.getAttribute("path"),component: this.getAttribute("component")}}
}
window.customElements.define("c-route", CustomRoute);// 容器组件
class CustomComponent extends HTMLElement {async connectedCallback() {// 获取组件的path,即html的路径const strPath = this.getAttribute("path");// 加载htmlconst cInfos = await loadComponent(strPath);const shadow = this.attachShadow({ mode: "closed" });// 添加html对应的内容this.#addElement(shadow, cInfos);}#addElement(shadow, info) {// 添加模板内容if (info.template) {shadow.appendChild(info.template.content.cloneNode(true));}// 添加脚本if (info.script) {// 防止全局污染,并获得根节点var fun = new Function(`${info.script.textContent}`);// 绑定脚本的this为当前的影子根节点fun.bind(shadow)();}// 添加样式if (info.style) {shadow.appendChild(info.style);}}
}
window.customElements.define("c-component", CustomComponent);// <c-router></c-router>
class CustomRouter extends HTMLElement {#routesconnectedCallback() {const routeNodes = this.querySelectorAll("c-route");// 获取子节点的路由信息this.#routes = Array.from(routeNodes).map(node => node.getData());// 查找默认的路由const defaultRoute = this.#routes.find(r => r.default) || this.#routes[0];// 渲染对应的路由this.#onRenderRoute(defaultRoute);// 监听路由变化this.#listenerHistory();}// 渲染路由对应的内容#onRenderRoute(route) {var el = document.createElement("c-component");el.setAttribute("path", `/${routeponent}.html`);el.id = "_route_";this.append(el);}// 卸载路由清理工作#onUploadRoute(route) {this.removeChild(this.querySelector("#_route_"));}// 监听路由变化#listenerHistory() {// 导航的路由切换window.addEventListener("popstate", ev => {const url = location.pathname.endsWith(".html") ? "/" : location.pathname;const route = this.#getRoute(this.#routes, url);console.log(route,'route')this.#onUploadRoute();this.#onRenderRoute(route);});// pushStat或replaceSatewindow.addEventListener("c-popstate", ev => {const detail = ev.detail;console.log(detail,'detai66l')const route = this.#getRoute(this.#routes, detail.url);this.#onUploadRoute();this.#onRenderRoute(route);})}// 路由查找#getRoute(routes, url) {console.log(routes,'routes')return routes.find(function (r) {const path = r.path;const strPaths = path.split('/');const strUrlPaths = url.split("/");let match = true;for (let i = 0; i < strPaths.length; i++) {if (strPaths[i].startsWith(":")) {continue;}match = strPaths[i] === strUrlPaths[i];if (!match) {break;}}console.log(match,'matchmatch')return match;})}
}
window.customElements.define("c-router", CustomRouter);// 动态加载组件并解析
async function loadComponent(path, name) {this.caches = this.caches || {};// 缓存存在,直接返回if (!!this.caches[path]) {return this.caches[path];}const res = await fetch(path).then(res => res.text());// 利用DOMParser校验const parser = new DOMParser();const doc = parser.parseFromString(res, "text/html");// 解析模板,脚本,样式const template = doc.querySelector("template");const script = doc.querySelector("script");const style = doc.querySelector("style");// 缓存内容this.caches[path] = {template,script,style}return this.caches[path];
}
home.html<template><div>商品清单</div><div id="product-list"><div><a data-id="10" class="product-item c-link">香蕉</a></div><div><a data-id="11" class="product-item c-link">苹果</a></div><div><a data-id="12" class="product-item c-link">葡萄</a></div></div>
</template><script>let container = this.querySelector("#product-list");// 触发历史更新// 事件代理container.addEventListener("click", function (ev) {console.log("item clicked");if (ev.target.classList.contains("product-item")) {const id = +ev.target.dataset.id;history.pushState({id}, "", `/detail/${id}`)}})
</script><style>.product-item {cursor: pointer;color: blue;}
</style>
detail.html
<template><div>商品详情</div><div id="detail">商品ID:<span id="product-id" class="product-id"></span></div>
</template><script>this.querySelector("#product-id").textContent=history.state.id;
</script><style>.product-id{color:red;}
</style>
about.html<template>About Me!
</template>

更多推荐

router实现原理

本文发布于:2024-02-07 09:31:12,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1755754.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:原理   router

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!