原生JS实现组件切换(不刷新页面)

        这是通过原生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

        这段代码的目的是创建一个能够观察对象属性变化的代理对象。当使用 reactive 函数创建代理对象后,如果对代理对象进行属性的读取或写入操作,将会触发相应的 getset 操作,从而实现对对象的监听。

        同时,每次属性被写入时,都会调用 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()
};
3、数据变化调用方法
//组件渲染方法
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
        //<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
)

//将得到的hash地址栏内容进行解析拆分,得到自己想要的内容。
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
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宝子向前冲

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值