这是通过原生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.js
export function home1Page() {
document.querySelector("#app").innerHTML = homePageTemplate;
}
const homePageTemplate = `
<div class="home1">
<div>组件1</div>
</div>`;
//home2.js
export 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() {
//将路径带入方法中得到options
let 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
}