Omi框架学习之旅 - 插件机制之omi-router及原理说明

先来看看官网的介绍吧:https://github.com/AlloyTeam/omi/tree/master/plugins/omi-router

其实我推荐直接看官网的介绍。我所写的,主要给个人做的笔记。也许看的get不到点吧。所以强烈看官网

文档:https://alloyteam.github.io/omi/website/docs-cn.html

github: https://github.com/AlloyTeam/omi

好了,该做笔记了。这次主要记录一下omi-router插件,关于路由,我想不用我多说,因为我也没怎么用其做个项目,实在惭愧。

我的个人理解是:

就是在同一个页面做多个页面的活。
代码量可能多了(基本要用模块化了),但是可以共享一些公用的js代码,或者其他html,css。
不同的组件可以根据hash值插入到指定dom中(omi是不同的组件然后实例化一个,然后omi.render一下就好了)。
hash值可以无刷新前进和后退,这样就做到了页面高速渲染不同的内容,无需等待空白新页面.

单页应用的好处可以直接看第一个链接。用过vue,react的我想都很清楚。只是我。。。

先看下demo吧

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>router2</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0">
    <style type="text/css">
        * {
            margin: 0;
            padding: 0;
        }
    </style>
</head>
<body>
    <div id="app"></div>

    <script type="text/javascript" src="./src/omi11.js"></script>
    <script>
        Omi.OmiFinger.init();

        class Home extends Omi.Component {
            constructor(data) {
                super(data);
            }

            render() {
                return     `
                    <div>
                        Home
                    </div>
                `;
            }
        };

        Omi.tag(‘Home‘, Home);

        class About extends Omi.Component {
            constructor(data) {
                super(data);
            }

            render() {
                return     `
                    <div>
                        About
                    </div>
                `;
            }
        };

        Omi.tag(‘About‘, About);

        class UserList extends Omi.Component {
            constructor(data) {
                super(data);
            }

            render() {

                return `
                    <ul>
                        <li>
                            <a omi-router to="/user/omi/category/html" href="">omi</a>
                        </li>
                        <li>
                            <a omi-router to="/user/dnt/category/css" href="">dnt</a>
                        </li>
                        <li>
                            <a omi-router to="/user/sorrowx/category/js" href="">sorrowx</a>
                        </li>
                    </ul>
                `;
            }
        };

        Omi.tag(‘UserList‘, UserList);

        class User extends Omi.Component {
            constructor(data) {
                super(data);
            }

            beforeRender() {
                this.data.name = this.$store.$route.params.sName;
                this.data.category = this.$store.$route.params.sType;
                var info = this.queryInfo(this.data.name);
                this.data.age = info.age;
                this.data.sex = info.sex;
            }

            queryInfo(name) {
                this.mockData = {
                    omi: {age: 1, sex: ‘女‘},
                    dnt: {age: 12, sex: ‘男‘},
                    sorrowx: {age: 13, sex: ‘男‘},
                };

                return this.mockData[name];
            }

            back() {
                history.back();
            }

            render() {
                return `
                    <div>
                        <button omi-finger tap="back">back</button>
                        <ul>
                            <li>name: {{name}}</li>
                            <li>age: {{age}}</li>
                            <li>sex: {{sex}}</li>
                            <li>category: {{category}}</li>
                        </ul>
                    </div>
                `;
            }
        };

        Omi.tag(‘User‘, User);

        class App extends Omi.Component {
            constructor(data) {
                super(data);
            }

            install() {
                Omi.OmiRouter.init({
                    routes: [
                        { path: ‘/‘, component: Home },
                        { path: ‘/about‘, component: About },
                        { path: ‘/user-list‘, component: UserList },
                        { path: ‘/user/:sName/category/:sType‘, component: User }
                    ],
                    renderTo: "#view",
                    defaultRoute: ‘/about‘,    // 默认
                    root: this
                });
            }

            style() {
                return `
                    ul{
                        border-bottom: 1px solid #ccc;
                        padding-bottom:5px;
                    }
                    li{
                        display:inline-block;
                    }
                    ul li a {
                        text-decoration: none;
                    }
                    #view li{
                        display:block;
                    }
                    #view ul{
                        border-width: 0px;
                    }
                `;
            }

            render() {
                return `
                    <div>
                        <ul>
                            <li>
                                <a omi-router to="/" href="">Home</a>
                            </li>
                            <li>
                                <a omi-router to="/about" href="">About</a>
                            </li>
                            <li>
                                <a omi-router to="/user-list" href="">用戶</a>
                            </li>
                        </ul>
                        <div id="view"></div>
                    </div>
                `;
            }
        };

        var app = new App();
        Omi.render(app, ‘#app‘);

    </script>
</body>
</html>

还是直接运行一把,看下结果吧,

http://wx.indoorun.com/indoorun/wxtest/touch/router3.html#/user-list

在手机上点击,或者浏览器f12进入模拟器查看,因为使用了tap事件。

至于omi怎么实现的?

答:我就大概的说一下其 实现原理吧,快下班了, 源码会贴在下面的。

1. 入口: Omi.OmiRouter.init(option);

option的参数如下: {

routes:[{}, {}, {}...],    // {path:‘路由映射的hash‘, component: ‘组件,需要实例化的组件然后渲染到指定dom‘}

renderTo: ‘#id‘,    // 渲染到哪个dom去啊,对吧

defaultRoute: ‘默认路由hash‘,    // 打开链接时不同的用户看到的结果一样撒

root: this    // 把组件实例顺便传进去

}

2. 当我们点击链接时,我们需要触发了,入口如下

            render() {
                return `
                    <div>
                        <ul>
                            <li>
                                <a omi-router to="/" href="">Home</a>
                            </li>
                            <li>
                                <a omi-router to="/about" href="">About</a>
                            </li>
                            <li>
                                <a omi-router to="/user-list" href="">用戶</a>
                            </li>
                        </ul>
                        <div id="view"></div>
                    </div>
                `;
            }

每个a标签都加了omi-router属性,说明被omi-router插件的一下这个方法注册了事件,代码如下

            Omi.extendPlugin(‘omi-router‘, function (dom, instance) {    // 给Omi.plugins 添加 omi-router 插件
                dom.setAttribute(‘href‘, ‘javascript:void(0)‘);

                dom.addEventListener(‘click‘, function () {
                    hashMapping(dom.getAttribute(‘to‘));
                }, false);
            });

里面的匿名函数,每当点击有omi-router属性的标签便会触发这个匿名函数。调用了这个关键的函数hashMapping(dom.getAttribute(‘to‘));,代码如下

        function hashMapping(to) {    // to: 路径地址
            routerOption.routes.every(function (route) {    // route: 路由对象
                var toArr = to.match(route.reg);    // to匹配route.reg正则返回匹配到的结果数组
                if (toArr) {
                    var pathArr = route.path.match(route.reg);    // route.path匹配route.reg正则返回匹配到的结果数组
                    params = getParams(toArr, pathArr);
                    renderTo = route.renderTo || routerOption.renderTo;    // 渲染到哪去(显然每个路由对象也可以有renderTo属性)
                    store = route.store || routerOption.store;    // 数据存储
                    Component = route.component;    // route的组件
                    pushState(to);
                    return false;    // 只有匹配到结果后到达这里就跳出函数啦
                };
                return true;    // 否则继续遍历
            });
        };

to: 路径地址指的是标签中的to属性的值,然后和配置选项中的routes数组,进行对比。主要获取store,Component,params的数值,然后pushState()方法会改变浏览器

中的url地址,当然也给window注册了一个hashchange事件,所以当url改变时,会触发该事件,如下

        window.addEventListener(‘hashchange‘, function() {    // hashchange事件, url改变就触发
            hashMapping(window.location.hash.replace(‘#‘,‘‘), renderTo);
            render();
        }, false);

这里的render()方法比较重要哦,组件实例化,和渲染都在里面执行,如果已经有了对应的实例,还得从omi的instances删掉,在重新实例化一个,代码如下

        function render(){
            if(store){
                store.$route = { };
                store.$route.params = params;
            }else{
                store = {
                    methods:{
                        install: function() {
                            this.$route = { };
                            this.$route.params = params;
                        }
                    }
                };
            };
            if(preRenderTo === renderTo&&preInstance){
                deleteInstance(preInstance);
            };
            var instance = new Component();    // 组件类
            Omi.render(instance, renderTo, {
                store: store
            });
            preInstance = instance;
            preRenderTo = renderTo;
        };

从omi的instances移除实例的代码如下:

        function deleteInstance(instance) {    // 删除存在的实例
            for (var key in Omi.instances) {
                if(Omi.instances.hasOwnProperty(key)){
                    Omi.instances[key].id = instance.id;
                    delete  Omi.instances[key];
                    instance = null;
                    break;
                };
            };
        };

主要代码基本讲完了。

ps:

路由,感觉还得自己写写小例子,不然玩的不6啊。

时间: 2024-10-14 18:51:46

Omi框架学习之旅 - 插件机制之omi-router及原理说明的相关文章

Omi框架学习之旅 - 组件通讯(data通讯) 及原理说明

接着上一篇的data-*通讯,这篇写data通讯. data通讯主要为了复杂的数据通讯. 老规矩:先上demo代码, 然后提出问题, 之后解答问题, 最后源码说明. class Hello extends Omi.Component { constructor(data) { super(data); } style() { return ` h1 { cursor: pointer; } `; } handleClick(target, click) { console.log(target.

Omi框架学习之旅 - 组件通讯(data-*通讯) 及原理说明

老规矩:先上demo代码, 然后提出问题, 之后解答问题, 最后源码说明. class Hello extends Omi.Component { constructor(data) { super(data); } style() { return ` h1 { cursor: pointer; } `; } handleClick(target, click) { console.log(target.innerHTML); } render() { return ` <div> <

滴滴Booster移动APP质量优化框架 学习之旅 二

推荐阅读: 滴滴Booster移动App质量优化框架-学习之旅 一 Android 模块Api化演练 不一样视角的Glide剖析(一) 续写滴滴Booster移动APP质量优化框架学习之旅,上篇文章分析内置的transform:booster-transform-shrink booster-transform-shared-preferences,今天分析booster-task-compression以及定制task对资源索引文件resource.asrc进行优化(重复资源优化.无用资源优化

WordPress 插件机制的简单用法和原理(Hook 钩子)

WordPress 的插件机制实际上只的就是这个 Hook 了,它中文被翻译成钩子,允许你参与 WordPress 核心的运行,是一个非常棒的东西,下面我们来详细了解一下它. PS:本文只是简单的总结一下,更多用法还是要参考文中给出的函数. 钩子分类 钩子分为两种,一种叫做动作(action),还有一种叫做过滤器(filter).这两种钩子实现原理基本一样,后边会讲到,使用上的区别在于过滤器有返回值,而动作没有. 动作的理念是让你在一种情况或者一个特别的位置执行一些函数,比如发送一封邮件等:过滤

[转]仿World Wind构造自己的C#版插件框架——WW插件机制精简改造

很久没自己写东西啦,早该好好总结一下啦!一个大师说过“一个问题不应该被解决两次!”,除了一个好脑筋,再就是要坚持总结. 最近需要搞个系统的插件式框架,我参照World Wind的插件方式构建了个插件框架,可以参照<WorldWind学习系列五:插件加载过程全解析>,下面与大家分享一下. 初始化时,加载前面两个插件,可以动态加载KeyBoarderLoader,如下图: 该插件框架是WW插件框架的精简改造版,非常适用于插件式系统开发,也希望帮助大家学习一下WW的插件加载机制. 缺陷在于:未实现事

微信开发学习日记(八):7步看懂weiphp插件机制,核心目标是响应微信请求

又经过了几个小时的梳理.回顾,截至目前,终于对weiphp这个框架的机制搞明白了些.想要完全明白,自然还需要大把的时间.第1步:   配置微信公众号,http://weiphp.jiutianniao.com/ ... .html  从上面这个配置可以看出,微信请求呗weiphp的入口文件index.php接收了,可能会被/home/weixin/index/这个action响应.第2步:   index.php入口文件,校验了是否是微信请求.   /** * 微信接入验证 * 在入口进行验证而

winform插件机制学习

这两天在看自定义控件,原来有太多知识没有掌握.今天看到插件机制,心里突然一亮,这个东西听了不少次,就是不知道是啥回事.这次有幸书里包含一个案例,我就跟着它一步步来.终于知道是什么回事了.这个应该在软件开发中非常多见.只是当时不理解罢了. 开始 新建一个winform项目CustomControls在窗体上放一个button按钮 窗体代码 using System;using System.Collections.Generic;using System.ComponentModel;using

SPA学习之 - 路由插件(crossroads.js)

Crossroads.js是一个受Rails, Pyramid, Django, CakePHP等基于路由/分发(Route/Dispatch)方式处理路由的后端MVC框架启发的一套js专业路由库.它能够直接解析传入的字符串并根据相应的规则来过滤和验证路由,然后再执行下一步的操作. A duck can walk, fly and swim, but he can’t do any of these things well… crossroads.js是一个独立的库功能十分强大和灵活,而且职责单

android多媒体框架学习 详解 最新版本

一:多媒体框架概述   jellybean 的多媒体跟以前的版本,通过对比没啥变化,最大的变化是google终于舍得给multimedia建个独立的git了(framework/av),等你好久了!也体现了media 在整个android系统中的重要性!framework/av下都是些C/C++代码(libmedia,libmediaplayerservice,libstagefright),jni和 java api 还是保留在原来的位置,改革还不够彻底,但还是迈出了这一步,以后维护能更好的进