IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> ming_router.js -> 正文阅读

[JavaScript知识库]ming_router.js

介绍

语缺ming_router
ming_router是一个路由库 与 写组件的库,目的是在不使用构建工具的情况下开发单页应用,用ifram是一个很不好的方法,本文介绍两类方案,原生方案,与vue方案。ming_router的组件写法类似react,尽量模拟了react的生命周期函数。
类似的库有 slimjs

安装

项目主页 Gitee
项目地址 Gitee
npm地址 NPM
在线测试

NPM安装

已经说了,不用构建工具,这样安装没意义

npm i ming_router

script引入

   <script src="https://unpkg.com/ming_router/src/index.js"></script>

ming_router的对象和方法

| MingRouter.WebComponent | 应用组件需要继承此类 | ?

mingRouter
mingRouter.mapping(’/b’,"/b.html")
MingRouter.Page()
MingRouter.registWebComponent()
MingRouter.pageRootPath
mingRouter.render([path])
mingRouter.refresh()
MingRouter. replaceHash(hash)
MingRouter.getTemplateByHtmlUrl(htmlUrl)
mingRouter.renderHtml(html)
MingRouter.loadHtml(htmlUrl)
MingRouter.loadCss(cssUrl)
MingRouter.html(htmlUrl)
MingRouter.componentMap.组件类名.组件key

Demo

路由demo

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://unpkg.com/ming_router/src/index.js"></script>
    <title>Document</title>
</head>
<body>
<button id="renderA">renderA</button>
<div id="root">

</div>
<hr/>
<div id="root1">

</div>

<template id="template1">
    <h2>Flower ${M.a}</h2>
</template>
</body>

</html>

<script>
    M={}
    M.a=3;
    //自带一个#root路由实例mingRouter
    mingRouter.mapping('/a', "#template1",()=>{
        console.log("AAAAA")
    });
    mingRouter.mapping('/b', "/b.html")
    mingRouter.mapping('/c', `<div> AAAAAAAAA  </div>`)

    renderA.onclick=function(){
        M.a++;
        mingRouter.render()
    }

//
    //创建新的路由实例mingRouter1
    mingRouter1 = new MingRouter("#root1");
    mingRouter1.mapping('/a', `<div> AAAAAAAAA  </div>`)
    mingRouter1.mapping('/b', `<div> BBBBBBBBBBBBBBBB  </div>`)

</script>

组件demo01

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <script src="https://unpkg.com/ming_router/src/index.js"></script>
    <title>Document</title>
</head>
<body>
<div id="root">
    <user-card1 key="k1" onclick="changeImg()" id="c1Id" src="https://semantic-ui.com/images/avatar2/large/kristy.png"></user-card1>
    <hr/>
    <user-card2 type="1"></user-card2>
    <hr/>
    <user-card3></user-card3>
    <hr/>
    <user-card4/></user-card4>
    <hr/>
    <user-card5></user-card5>
</div>
</body>
</html>


<template id="usercard1Id">
    #usercard1Id ${props.id}
    <img width="100px" src="${props.src}">
</template>


<script>

    //user-card1 用模板创建组件
    MingRouter.registWebComponent(function UserCard1(props) {
        return `#usercard1Id`
    })

    // user-card2 html文件  或字符串做模板
    MingRouter.registWebComponent( function UserCard2(props) {
        if(props.type==1){
            return `<div>用返回做模板</div>`
        }else {
            return `./a.html`
        }
    })

    // user-card3 用html文件做模板
    MingRouter.registWebComponent(function UserCard3(props) {

        return `./a.html`
    })


    // user-card4 类组件
    MingRouter.registWebComponent(
            class UserCard4 extends MingRouter.WebComponent {
                render() {
                    return `<div>我是类组件</div>`;
                }
            });

    // user-card5 类组件
    MingRouter.registWebComponent(
            class UserCard5 extends MingRouter.WebComponent {
                static template= `#usercard1Id`;
            });


    //修改#c1Id的图片
    function changeImg(){
        document.querySelector("#c1Id").setAttribute("src","aa")
    }

</script>

组件demo02

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <script src="https://unpkg.com/ming_router/src/index.js"></script>
    <title>Document</title>
</head>
<body>
<div id="root">
</div>
</body>
</html>






<!--mingRouter路由的模板-->
<template id="rootTemplateId">
    <h1>ming_router.js demo</h1>
    <hr/>
    <!--如果组件有多个实例则必须有唯一的属性key-->
    <user-card  id="userCardId" key="name11" image="https://semantic-ui.com/images/avatar2/large/kristy.png" onclick1="MingRouter.Page.user.methods.ok">
        <h2 slot="name">name11</h2>
        <span slot="role">Developer</span>
        <div slot="description" >
            I hate Internet Explorer
            <button onclick="alert(33)">插槽的按钮</button>
        </div>
    </user-card>
    <hr/>
    <user-card  id="userCardId" key="name12" image="https://semantic-ui.com/images/avatar2/large/kristy.png" onclick1="MingRouter.Page.user.methods.ok">
        <h2 slot="name">name12</h2>
    </user-card>
</template>


<!--userCard组件的模板 属性用this.props.age  , 方法用${this.selfName}.addAge  -->
<!--状态用this.state.age -->
<template id="userCardTemplateId">
    AAAAAAAAAAAAAAAAAA
    <button onclick="${this.selfName}.addAge()">组件的按钮</button>
    ${this.state.age}
    <img id="myImgId" src="${this.props.image}">

    <div>
        <slot name="name"></slot>
        <slot name="description"></slot>
        <slot name="role"></slot>
    </div>
</template>



<script>
    //#root 的路由映射,mingRouter默认挂载#root
    //通过 mingRouter1 = new MingRouter("#root1"); 创建新的路由
    mingRouter.mapping("/","#rootTemplateId");
    mingRouter.mapping("/a","#rootTemplateId")
    mingRouter.mapping("/b","<h1>BBBBBBBBBBB<h1/>")
</script>



<script>
    //自定他组件,每个UserCard会根据组件的key,生成唯一一个实例名this.selfName
    //MingRouter.componentMap.UserCard[key]
    class UserCard extends MingRouter.WebComponent {
        //https://www.yuque.com/docs/share/a87701d4-bb25-4d0a-b42d-225f834f9b7c?#C4kMr
        static template="#userCardTemplateId";

        constructor(props) {
            super(props);
            this.props = props;
        }
        //组件私有状态, this.setState({}) 会触发组件重新render
        state = {
            age: 1,
            hobby:"111"
        }
        //组件方法,模板中, 通过${this.selfName}.addAge() 使用
        addAge() {
            //console.log(44);
            let age = this.state.age + 1;
            this.setState({ age })
        }
        //发出ajax
        componentDidMount() {
            console.log("....componentDidMount..selfName==>", this.selfName)
        }

        /**
         * 通过
         * document.querySelector("#userCardId").setAttribute("image","https://sem.png")
         * 将触发此方法
         */
        componentWillReceiveProps(props) {
            console.log("....componentWillReceiveProps",props);
            //属性发生变化,重新渲染
            this.setState({})
        }
        /**
         * 返回组件样式,建议用全局样式,否则有样式重复问题
         */
        renderCss(){
            return `
                img{ width:20vw}
             `
        }

        /**
         * render优先级最低
         */
        // render(props) {
        //     return `
        //        <button οnclick="${this.selfName}.addAge()"> aa </button>
        //        <div> ${props.image}  </div>
        //        <div>age: ${this.state.age}  </div>
        //        <div>hobby: ${this.state.hobby}  </div>
        //    `;
        // }
    }

    // 将UserCard注册为全局组件
    MingRouter.registWebComponent(UserCard)


</script>

pageDemo



<style>
    body{
        color: red;
    }
</style>



<div>
    <h1>
        role    ${pageObj.data.count}
        <button onclick="MingRouter.Page.role.methods.addCount()">+</button>
    </h1>

    <div>
        ${pageObj.data.todos.map(u=>{
        return `<li>AAAAAAAAAAAAAAA==>  ${u.text}</li>`
        }).join("")}
    </div>
</div>


/

const {Page}=MingRouter;
export default await Page({
    name: "role",
    async mounted() {
        console.log(44)
        let list= await MIO.todoList();
        pageObj.data.todos=list;
    },
    data: {
         count:4,
         todos: [{text: '学习 JavaScript'}]
    },
    methods:{
        addCount(){
            pageObj.data.count++;
            mingRouter.render();
        }
    }
})

页面模板或组件模板的获取规则

从指定的url中获取
这个url也可以是一个公网地址,前提是支持跨域,并且地址是.html结尾(后面不能含空格)
页面

mingRouter.mapping('/b', "template/b.html")

组件

class UserCard extends WebComponent {
      static template="template/b.html"
 }

从template标签获取

页面

mingRouter.mapping('/a', "#template1",()=>{
     console.log("load success")
});

组件

class UserCard extends WebComponent {
     static template="#template1"
 }

从指定字符串中获取

如果router.mapping第二个参数不是#开头,也不是html结尾,则从传入的字符串中获取
页面

mingRouter.mapping('/c', `<div> AAAAAAAAA  </div>`)

组件

class UserCard extends WebComponent {
         static template=`<div> AAAAAAAAA  </div>`
 }

从render() 方法获取

组件除了上面三种方式获取组件模板外还可以从组件实例的render方法中获取, 从字符串获取模板的缺点是不能带变量,从 render 获取可以像从html获取那样带变量,从render获取的好处是真正实现单文件组件

?

路由映射router.mapping

一个MingRouter实例对应一个挂载节点,可同时创建多个MingRouter实例,有一个默认实例mingRouter挂载在#root上,MingRouter 构造方法有两个参数,第一个参数就是要挂载的节点,第二个参数是改节点是否使用模板字符串处理, 语法参考 ming_node app.use过滤器
默认为false

mingRouter = new MingRouter("#root",true)
mingRouter.mapping(path,模板来源,挂载完成后的钩子)

页面上下文

window.pageObj 存储了页面上下文信息

页面生命周期

页面只有一个mounted 函数,可通过变量配合route.refresh(),route.render()更新页面

组件的文件组成

 简单的组件直接写一个js文件即可,结构样式全写在js里,简单组件其实也没必要封装成组件,复杂组件应将将结构样式分离出去,,比如写一个快递组件,需要写两个文件 ming-kuaidi.html(包含结构与样式), ming-kuaidi.js (包含组件状态与方法),在使用时只需引入ming-kuaidi.js即可,无需感知ming-kuaidi.html的存在[https://jsrun.net/AYUKp](https://jsrun.net/AYUKp)

组件tagName生成规则

组件tagName由驼峰类名或函数名转换为中划线而来
UserCard => user-card
MingRouter=> ming-router

获取组件实例与数据方法绑定

MingInput 是一个自定义组件的类,ming-input是对应的tag

对象组件外部组件内部
wrapWebComponent的类MingRouter.componentMap[“MingInput”]


MingInput | 模板中
${CurWebComponent}
类中
MingInput |
| shadowRoot | document.querySelector(“ming-input”).shadowRoot | this.shadowRoot |
| htmlElement实例 | document.querySelector(“ming-input”) | this.htmlElement |
| wrapWebComponent实例 | document.querySelector(“ming-input”).wrapWebComponent | this |
| 组件内部元素 | document.querySelector(“ming-input”).shadowRoot.querySelector(’#tanmuInputId’) | this.shadowRoot.
querySelector(’#tanmuInputId’) |
| wrapWebComponent 的send方法 | document.querySelector(“ming-input”).wrapWebComponent.send() | this.send() |
| 接收外部传入的方法 | ?


?

?
| let value=
this.shadowRoot.
querySelector(’#tanmuInputId’).
value;

eval(${this.props.onsend}(value)); |
| 接收外部参数 | | this.props.onsend |
| 绑定组件内的方法 | | #组件模板中
?

酷金 |
| 绑定组件外的方法 | | #组件模板中
?

酷金 | | 模板渲染 | |

${this.state.selectData}

?

${this.props.name}

| | 组件样式0 | | #组件模板中

#组件类中
renderCss() {
return (div{ color:blue })
}
?
|
| 组件样式1
?

:host 外部传入类名影响组件样式 |

| :host{
color: green;
}

:host(.font-red){
color: red;
} |
| 组件样式2
?

::part 外部定义内部元素样式 | ming-input::part(h1-part){
color: pink;
} |


${this.state.selectData}

| | 组件样式3 ?

通过css变量传入组件 | //全局css变量
:root{
–h1-color: green;
}

//组件局部css变量
ming-input{
–h1-color: green;
} | //不传默认红色
h1{
color: var(–h1-color,red);
}

|
| 组件内部样式获取 | getComputedStyle(
document.querySelector
(“ming-input”).
shadowRoot.querySelector(’#tanmuInputId’)
).backgroundColor | getComputedStyle(
this.shadowRoot.querySelector("#tanmuInputId")
).backgroundColor |

组件属性

组件属性必须全部为小写

组件生命周期方法

mingRouter的组件是react风格的,实现了如下生命周期函数,函数组件无生命周期,只能外部调用dom.
setAttribute后更新,WebComponent生命周期用绿色表示,HTMLElement的生命周期用蓝色表示,
两者有重合的部分,mingRouter自定义组件使用时只能重写绿色部分的部分的方法

render会直接替换整个dom树
componentWillUnmount在组件从 DOM 中移除之前立刻被调用
componentWillReceiveProps外部调用组件的setAttribute()后调用
componentDidMount组件装载完成时调用
setState调用后会重新渲染组件
setAttribute外部手动修改属性,默认调用componentWillReceiveProps
attributeChangedCallbackobservedAttributes的属性发生变化会被调用
static get observedAttributes()声明要监听变化的属性,变化后会调用attributeChangedCallback,默认为[]
constructor构造方法
adoptedCallback被移动到新的文档中时调用
disconnectedCallback元素从文档中被移除调用,默认调用组件的 componentWillUnmount
connectedCallback元素首次被插入文档调用, 不可重写

模板字符串

当 new MingRouter("#root",true) 第二个参数为true时,则使用模板字符串,用的是es6模板字符串
模板字符串可使用当前上下文中的所有变量,参考[各种模板字符串](https://www.yuque.com/docs/share/f6a22b7c-60d1-46b1-9ca4-0193d73ab561?# 《模板字符串》)

<template id="template1">
        <div>
            aaa  ${M.a}
            <button>触发</button>
        </div>
</template>

路由切换与刷新

替换切换

不会修改路由栈,不能返回上一步

MingRouter.replaceHash("/b")

原生切换

相当于压栈操作,可返回上一页

  location.hash="#/b";

路由刷新

在切换新的路由时本身就是刷新,刷新当前路由使用如下方法

 mingRouter.refresh()

不改地址栏的刷新

不传path则刷新当前路由

 mingRouter.render([path])

原生方案

https://gitee.com/minglie/ming_node_router/tree/master/ming_router_nobuild

目录结构

![image.png](https://img-blog.csdnimg.cn/img_convert/edd3d0f68d19ba6b09f4eda0c3dc019d.png#clientId=ufe290e31-d1c1-4&from=paste&height=461&id=u82f5a156&margin=[object Object]&name=image.png&originHeight=922&originWidth=1083&originalType=binary&ratio=1&size=161497&status=done&style=none&taskId=u83694294-92ff-4bc8-ba58-131813f0180&width=541.5)

页面

,与vue类似,页面js导出时要加个name,目的是找对应的模板以及路由配置

export default await Page({
    name: "role",
    async mounted() {
        console.log("userMounted")
    }
})

注意事项
P1: 页面的css.html可写在到html中
P2: 可通过Page.页面名拿到页面实例
P3: 导出实例必须有name属性
P4: 修改data无法刷新需要手动调用操作dom 或 mingRouter.refresh() 刷新页面

组件

组件使用原生的webComponent,我用类似react风格进行了封装,组件应该为单文件

class UserCard extends MingRouter.WebComponent {
  static className = "UserCard";
  static tagName = "user-card";
  constructor(props) {
    super(props);
    this.props = props;
    console.log(this.constructor.name, "eee")
  }

  state = {
    age: 1,
    hobby:"111"
  }

  addCount() {
    console.log(44);
    let age = this.state.age + 1;
    this.setState({ age })
  }


  renderCss() {
    return (`
       div{
          color:blue
       }  
   `)
  }

  componentDidMount() {
    console.log("....componentDidMount")
  }

  render(props) {
    return `
       <button οnclick="${this.selfName}.addCount()"> aa </button>
       <div> ${props.image}  </div>
       <div>age: ${this.state.age}  </div>
       <div>hobby: ${this.state.hobby}  </div>
   `;
  }
}


MingRouter.registWebComponent(UserCard)

P1:组件传入时要加个key

<user-card key="name1" image="https://semantic-ui.com/images/avatar2/large/kristy.png" onclick1="Page.user.methods.ok()"></user-card>

P2: 组件的模板与样式应全部写到组件js中,要保证只需引入组件js就可直接使用
P3: 组件直接注册未全局组件,而不是导出
P4: 组件声明完需要在import.js中显示的导入

接口请求

用浏览器自带的fetch请求,实现的[数据请求规范](https://www.yuque.com/docs/share/a76a0bcf-f204-4d68-8f7d-7db247b5f9a7?#k9C7y),数据请求应该经过[ming_mock_vue](https://gitee.com/minglie/ming_node_router/blob/master/vue_nobuild/lib/ming_mock/ming_mock_vue.js) 周转一下, 用

MIO.userList({})进行调用。

app.get("/userList", async (req, res) => {
    let r= await M.request.get("/api/userList")
    res.send(r)
})

vue方案

https://gitee.com/minglie/ming_node_router/tree/master/vue_nobuild
?

目录结构

![image.png](https://img-blog.csdnimg.cn/img_convert/659eae994c9f02e146f5be70854abf55.png#clientId=u2e4745d2-9b63-4&from=paste&height=404&id=ub2f595e3&margin=[object Object]&name=image.png&originHeight=807&originWidth=1203&originalType=binary&ratio=1&size=157310&status=done&style=none&taskId=u4c8ba059-21f1-4611-a60b-5d194a34aa0&width=601.5)

页面

无法使用vue文件,而是把页面拆为,css,js,html三个文件,注意事项
P1: js中导出vue实例时要加一个name属性,方便ming_mock_vue找到对应的文件
P2:导出的实例需要使用 await Page() 方法包裹
P3: 如果不用html文件模板,则要显示的声明template属性
P4: 如果不用css文件样式,则要显示的声明beforeCreate 方法
?

![image.png](https://img-blog.csdnimg.cn/img_convert/87aa48d6c0e1795a1cc5ebd922db5ef0.png#clientId=u2e4745d2-9b63-4&from=paste&height=264&id=u167b7903&margin=[object Object]&name=image.png&originHeight=464&originWidth=881&originalType=binary&ratio=1&size=51221&status=done&style=none&taskId=uc13c6e17-f374-418e-b986-dd087966d18&width=501.5)

组件

这里组件与页面很类似,但有如下区别
P1: 组件直接注册未全局组件,而不是导出
P2: 组件对象需要用 await WrapComment() 方法包裹
P3: 组件无法导入css样式文件,为了方式组件样式污染重复,应用行内样式与全局样式代替
P4: 组件声明完需要在import.js中显示的导入
import.js

import "../../component/mi-img/mi-img.js"

![image.png](https://img-blog.csdnimg.cn/img_convert/41d52a8602cdc46ca2fa999f5b7a8e37.png#clientId=u2e4745d2-9b63-4&from=paste&height=232&id=ue4a63596&margin=[object Object]&name=image.png&originHeight=463&originWidth=727&originalType=binary&ratio=1&size=35253&status=done&style=none&taskId=u883f409b-9668-4f84-81c6-56a02f0f7da&width=363.5)

接口请求

用浏览器自带的fetch请求,实现的[数据请求规范](https://www.yuque.com/docs/share/a76a0bcf-f204-4d68-8f7d-7db247b5f9a7?#k9C7y),数据请求应该经过[ming_mock_vue](https://gitee.com/minglie/ming_node_router/blob/master/vue_nobuild/lib/ming_mock/ming_mock_vue.js) 周转一下, 用

MIO.userList({})进行调用。

app.get("/userList", async (req, res) => {
    let r= await M.request.get("/api/userList")
    res.send(r)
})

一些ming_router写的移动端组件

输入框

https://jsrun.net/VyUKp

弹幕

https://jsrun.net/3yUKp

ming_router待新增功能

待新增功能
?

参考demo

各种模板字符串
?

https://gitee.com/minglie/ming_node_router
?

ming_mock.js
?

ming_router.js

webcomponent-demo
[

](https://github.com/zxuqian/html-css-examples/tree/master/31-webcomponent-get-started)

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-10-29 12:54:58  更:2021-10-29 12:58:13 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/11 5:12:02-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码