这是通过原生Es6实现的组件切换,代码很简单,原理和各种框架原理大致相同。
创建文件
├── component:存放组件
│ ├── home1.js:组件1
│ ├── home2.js:组件2
├── index.html
├── index.js
初始化html文件
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title><style>.home1 {background-color: #e33a3a;width: 200px;height: 200px;}.home2 {background-color: #6ce11e;width: 200px;height: 200px;}</style></head><body><div id="app"></div><a href="#/home1">组件1</a><a href="#/home2">组件2</a><!-- type="module",必须带这个,因为后面会使用部分的ES6(模块化) --><script src="./index.js" type="module"></script></body>
</html>
初始化hom1和home2
//home1.jsexport function home1Page() {document.querySelector("#app").innerHTML = homePageTemplate;
}
const homePageTemplate = `
<div class="home1"><div>组件1</div>
</div>`;//home2.jsexport function home2Page() {document.querySelector("#app").innerHTML = componentPageTemplate;
}
const componentPageTemplate = `
<div class="home2"><div>组件2</div>
</div>`;
创建index.js
index.js我们一步一步刨析
1、创建路由表
首页先创建一个路由表,在不同的路由下执行不同的方法。
import { home1Page } from "./component/home1.js";
import { home2Page } from "./component/home2.js";
//路由表
const routers = [{name: "home1",path: "/home1",component: home1Page},{name: "home2",path: "/home2",component: home2Page,}
];
2、监听hash
// 监听页面 load和hashchange 事件,事件触发后对代理对象赋值//hash变化
window.addEventListener("hashchange", () => {hashProxy.hash = window.location.hash;
});
//页面初始化
window.addEventListener("load", () => {hashProxy.hash = window.location.hash;
})// 数据响应式处理
const hashProxy = reactive({hash: ""},effective
)// obj是要变成响应式的对象,effective是一个回调函数,在对象属性发生变化时会被调用
function reactive(obj, effective) {return new Proxy(obj, {get(obj, key) {return Reflect.get(obj, key);},set(obj, key, value) {let set = Reflect.set(obj, key, value);effective();return set;},});
}//数据响应式执行函数
let effective = () => {consoel.log("hash变化了");changeComponent()
};
3、数据变化调用方法
//组件渲染方法
function changeComponent() {//将路径带入方法中得到optionslet options = getRouteroptions(hashProxy.hash);//过滤路由表,得到对应组件的方法const [{ component }] = routers.filter((router) => router.name == options.name);//调用组件对应的方法,实现页面切换component();
}function getRouteroptions(hash) {const options = {//路由配置选项name: "",params: "",query: ""}//hash不存在时if (!hash || hash == "#home1") {options.name = "home1";} else {//提取name params query信息// 0 1 2//<a href='#/name/:params?query1=value1?query2=value2'></a>try {const routerArr = hash.slice(1).split("/");options.name = routerArr[1];// const paramsArr = routerArr[2].split("?");// options.params = paramsArr[0].slice(1);// options.query = paramsArr.slice(1);} catch (error) {options.name = "404";}}return options
}
至此功能就实现了
index.js完整代码
import { home1Page } from "./component/home1.js";
import { home2Page } from "./component/home2.js";
//路由表
const routers = [{name: "home1",path: "/home1",component: home1Page},{name: "home2",path: "/home2",component: home2Page,}
];// 监听页面 load和hashchange 事件,事件触发后对代理对象赋值
window.addEventListener("hashchange", () => {hashProxy.hash = window.location.hash;
});window.addEventListener("load", () => {hashProxy.hash = window.location.hash;
})function changeComponent() {let options = getRouteroptions(hashProxy.hash);const [{ component }] = routers.filter((router) => router.name == options.name);component();
}function reactive(obj, effective) {return new Proxy(obj, {get(obj, key) {return Reflect.get(obj, key);},set(obj, key, value) {let set = Reflect.set(obj, key, value);effective();return set;},});
}//数据响应式执行函数
let effective = () => changeComponent();// 数据响应式处理
const hashProxy = reactive({hash: ""},effective
)function getRouteroptions(hash) {const options = {//路由配置选项name: "",params: "",query: ""}if (!hash || hash == "#home1") {options.name = "home1";} else {//提取name params query信息// 0 1 2//<a href='#/name/:params?query1=value1?query2=value2'></a>try {const routerArr = hash.slice(1).split("/");options.name = routerArr[1];// const paramsArr = routerArr[2].split("?");// options.params = paramsArr[0].slice(1);// options.query = paramsArr.slice(1);} catch (error) {options.name = "404";}}return options
}