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

2023-12-20 04:56:15

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

文章来源:https://blog.csdn.net/m0_66570642/article/details/135088914
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。