这是通过原生Es6实现的组件切换,代码很简单,原理和各种框架原理大致相同。
├── component:存放组件
│ ├── home1.js:组件1
│ ├── home2.js:组件2
├── index.html
├── index.js
Document
组件1
组件2
//home1.js
export function home1Page() {
document.querySelector("#app").innerHTML = homePageTemplate;
}
const homePageTemplate = `
组件1
`;
//home2.js
export function home2Page() {
document.querySelector("#app").innerHTML = componentPageTemplate;
}
const componentPageTemplate = `
组件2
`;
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,
}
];
这段代码的目的是创建一个能够观察对象属性变化的代理对象。当使用
reactive
函数创建代理对象后,如果对代理对象进行属性的读取或写入操作,将会触发相应的get
和set
操作,从而实现对对象的监听。同时,每次属性被写入时,都会调用
effective
回调函数
// 监听页面 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()
};
//组件渲染方法
function changeComponent() {
//将路径带入方法中得到options
let options = getRouteroptions(hashProxy.hash);
//过滤路由表,得到对应组件的方法
const [{ component }] = routers.filter(
(router) => router.name == options.name
);
//调用组件对应的方法,实现页面切换
component();
}
//将得到的hash地址栏内容进行解析拆分,得到自己想要的内容。
function getRouteroptions(hash) {
const options = {
//路由配置选项
name: "",
params: "",
query: ""
}
//hash不存在时
if (!hash || hash == "#home1") {
options.name = "home1";
} else {
//提取name params query信息
// 0 1 2
//
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
)
//将得到的hash地址栏内容进行解析拆分,得到自己想要的内容。
function getRouteroptions(hash) {
const options = {
//路由配置选项
name: "",
params: "",
query: ""
}
if (!hash || hash == "#home1") {
options.name = "home1";
} else {
//提取name params query信息
// 0 1 2
//
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
}