8000 magix,页面区块化利器 · Issue #11 · thx/magix · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
This repository was archived by the owner on Nov 12, 2024. It is now read-only.

magix,页面区块化利器 #11

Open
xinglie opened this issue Jul 29, 2016 · 12 comments
Open

magix,页面区块化利器 #11

xinglie opened this issue Jul 29, 2016 · 12 comments

Comments

@xinglie
Copy link
Member
xinglie commented Jul 29, 2016

什么是区块

其实html标签就是区块,比如 div span a等标签。前端工程师就是在重复使用、组装这些区块(html标签)形成最终的需求页面。这是最原子的区块,我们要达到想要的页面效果,就得不停的重复嵌套这些区块。

但是呢,通常我们所说的区块是这些html标签的组合。比如当我们开发一个页面时,通常都是由多个逻辑关联不强的区块组成的,如常见的页头、页尾、内容区。这些区块通常是由多个html标签组合而成的。

我们可以借签html标签的这种嵌套及DOM Tree思路的,开发一套用于组合嵌套这种大区块的框架。我们把一个复杂的页面拆分成n个区块来开发,再由框架来便利的组合它们。这就是接下来要介绍的magix做的事情

定义区块

在这里我们把区块定义为由一段html标签组成的代码片断,区块最小是一个标签,如<button>。区块可以像html标签一样嵌套,即一个区块可以由多个子区块组成

项目中的区块

当我们在开发一个项目时,如前面提到的页头、页尾、内容区等,这些在我们项目里就是一个个区块,当然像内容区我们仍然可以再拆分子区块。像页头、页尾在项目里可以理解为原子区块,没必要再拆分了。这些区块应该很容易被复用。

准备工作

magix适配了不同的加载器与dom操作类库,有amd、cmd及kissy,可点击这里查看,当然您也可以自己定制,定制方法点击这里

接下来我们使用cmd版本,即seajs+jq来讲解magix的区块化管理

安装

新建一个magix-test目录,在magix-test目录里放上package.json文件如下:

{
    "name": "magix-test",
    "version": "1.0.0",
    "description": "magix示例项目",
    "keywords": [
        "magix",
        "view"
    ],
    "dependencies": {
        "jquery": "",
        "seajs": "",
        "magix": ""
    },
    "author": "xinglie <xinglie.lkf@taobao.com>",
    "license": "MIT"
}

然后通过npm install把seajs、jquery及magix安装到本机

页面开发

新建index.html如下

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Magix-test</title>
        <script src="node_modules/seajs/dist/sea-debug.js"></script>
        <script src="node_modules/jquery/dist/jquery.js"></script>
    </head>
    <body >
        <div id="header"></div>
        <div id="footer"></div>
        <script type="text/javascript">
        seajs.config({
            debug:true,
            alias:{
                magix:location.href+'./node_modules/magix/dist/cmd/magix-debug'
            },
            paths:{
                views:'./views'//等下我们新建的区块都放到views目录下
            }
        });
        define('$',function(){//shim magix内部在依赖jquery或zepto时,使用的是$符号,即magix并未指定具体的类库。外部需要提供$这个模块,这样可以很方便的在jq或zepto及其它类库中切换
            return jQuery;
        });
        </script>
    </body>
</html>

这样我们的首页就完成了,接下来我们开发header及footer,然后把它们渲染到index.html里相应的位置上。

我们在magix-test目录下新建views目录,我们把新建的header及footer放到该目录里
header.js如下

define('views/header', ['magix'], function(require) {
    var Magix = require('magix');
    return Magix.View.extend({
        render: function() {
            var html = 'I am header';
            this.setHTML(this.id, html);
        }
    });
});

新建footer.js,代码如header
然后我们修改index.html,加载header及footer,修改后的index.html如下

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Magix-test</title>
        <script src="node_modules/seajs/dist/sea-debug.js"></script>
        <script src="node_modules/jquery/dist/jquery.js"></script>
    </head>
    <body >
        <div id="header" mx-view="views/header"></div>
        <div id="footer" mx-view="views/footer"></div>
        <script type="text/javascript">
        seajs.config({
            debug:true,
            alias:{
                magix:location.href+'./node_modules/magix/dist/cmd/magix-debug'
            },
            paths:{
                views:'./views'//等下我们新建的区块都放到views目录下
            }
        });
        define('$',function(){//shim
            return jQuery;
        });
        seajs.use('magix',function(Magix){
            Magix.boot();//处理页面上的mx-view节点
        });
        </script>
    </body>
</html>

然后在web server中查看index.html即可,如果没什么问题应该就能看到header及footer已经渲染到了相应的节点里

事件处理

我们增加一个登录按钮,及点击按钮处理登录相关的事情。事件这块你可以用jquery的事件方法在render中自己绑定,也可以使用magix定义的方法书写事件,推荐使用magix定义的方法来处理事件:高性能,自动解绑

我们修改header.js如下

define('views/header', ['magix'], function(require) {
    var Magix = require('magix');
    return Magix.View.extend({
        tmpl:'I am header <div><button mx-click="processLogin()">Login</button></div>',
        render: function() {
            this.setHTML(this.id, this.tmpl);
        },
        'processLogin<click>':function(e){
            console.log(e);
            alert('Login');
        }
    });
});

这样就完成了事件的绑定与处理。注意绑定在button标签上的mx-click="processLogin()",事件采用mx-type的形式,不能是onclick。接收处理写成processLogin<click>,表明processLogin只处理click事件,如果button标签上你写成了mx-mousedown="processLogin()",那么下面的回调将不会执行哦
magix内部也是对接的jquery的事件处理函数,并非自己另外写了一套事件处理,只是在这个过程中magix有优化,所以推荐使用magix的写法。

区块嵌套

实际开发中区块会非常复杂,我们通常把一个复杂的区块再拆分子区块,然后再组装起来。我们这里假设header非常复杂,比如我们新建一个header-login区块用于单独处理登录的事情。

header-login代码如下

define('views/header-login', ['magix'], function(require) {
    var Magix = require('magix');
    return Magix.View.extend({
        tmpl: '<button mx-click="processLogin()">Login</button>',
        render: function() {
            this.setHTML(this.id, this.tmpl);
        },
        'processLogin<click>':function(e){
            console.log(e);
            alert('Login');
        }
    });
});

既然login已经单独成区块了,我们修改header.js,直接引用views/header-login区块

define('views/header', ['magix'], function(require) {
    var Magix = require('magix');
    return Magix.View.extend({
        tmpl: 'I am header <div mx-view="views/header-login"></div>',
        render: function() {
            this.setHTML(this.id, this.tmpl);
        }
    });
});

我们只需要在header.js中通过mx-view标签属性引用另外一个区块即可。这样就完成了子区块的拆分及组装功能。
刷新index.html我们可以看到和之前没拆分时是一样的

区块可视化

我们这样组装出来的页面,看上去和普通页面是一样的,但是我们如何快速知道页面上被拆分了哪些区块,及区块间的关系呢?这时候需要magix的配套工具magix-inspector
这是一个js文件,我们可以通过引入线上链接或npm包,更多引入方式可以查看https://github.com/thx/magix-inspector

我们修改index.html,引入线上链接
在index.html的head中增加如下script标签

<script src="//thx.github.io/magix-inspector/index.js"></script>

刷新index.html就可以看到右上角有一个区块间关系图,鼠标指向各个区块会高亮当前区块的范围及区块的路径地址等信息
调试工具展示的结构如图:
img
可视化工具所展示的区块间关系其实和DOM Tree是非常一致的

区块化的好处

我们可以把一个复杂的页面拆分成n个独立的区块单独维护与处理,方便多人同时开发,同时当一个区块复杂时,我们仍然可以快速的把它进行拆分,然后再组装回来,避免出现一个庞大的js文件。
这种区块可以通过mx-view标签属性被引用在项目中的任何地方,当一个区块被复用在多个地方时非常方便,比如这时候你可以在index.html里再添加上一个<div mx-view="views/header-login"></div>则页面上就会再出现登录按钮,多个同时存在的同一个view之间互相独立不冲突

后续

magix核心功能压缩后仅6kb,gzip后只有3kb,非常小,但功能非常强大,今天介绍的仅仅是冰山一角。
阿里妈妈所有后台产品及营销页面均是用magix开发,这里放几个链接
阿里妈妈帮助中心
afp
智钻

magix的项目地址在这里https://github.com/thx/magix
欢迎试用~

如果你不想按上述教程自己建文件,我把上述示例中的代码放到了附件里,可以点击链接下载

链接是淘云盘的,链接为 http://yunpan.taobao.com/s/2lRwLK22mnX 提取码为:73bzKa

@xinglie
Copy link
Member Author
xinglie commented Aug 4, 2016

其实页面区块化这个思路很早就有了,比如iframe这个标签,我们可以开发一个通用页面,然后在同一个页面上可以用iframe来嵌套显示这个通用页面,并且在url中传递参数,如下

<iframe src="list.html?type=1"></iframe>

<iframe src="list.html?type=2"></iframe>

当然,iframe有它的好处和问题,不过这种思路确实不错。

再比如asp.net,它的组件功能也是这样区块化的。比如<asp:Login>,组件也是可以嵌套形成更大的组件最终组装成页面。

类似这样的思路在服务端还是比较多的,发展到现在前后端分离的时候,magix致力于解决前端的这种嵌套与复用,思路都是类似的。如果你理解这些则上手magix会快速一些

@bigfengyu
Copy link
bigfengyu commented Apr 27, 2017

Hi,不知道是不是代码更新(Magix 3.2.3)的缘故,上面的代码已经跑不通了~经过尝试,有一些地方需要修改。

  1. index.html 中,原来对于 magix 路径的设置方式会获取失败,修改如下:
seajs.config({
    debug: true,
    alias: {
       //此处路径进行调整
        magix: location.href + '/../node_modules/magix/dist/cmd/magix-debug'
    },
    paths: {
        views: './views'
    }
});
  1. header.js 文件中,通过 var html = 'I am header <div><button mx-click="processLogin()">Login</button></div>'; 设置的绑定点击事件被触发时会报错,进行如下修改得以解决:
define('views/header', ['magix'], function (require) {
    var Magix = require('magix');
    return Magix.View.extend({
        tmpl:'i am header <button mx-click="processLogin()">Login</button>',
        render: function () {
            this.setHTML(this.id, this.tmpl);
        },
        'processLogin<click>': function (e) {
            console.log(e);
            alert('Login');
        }
    });
});

@xinglie
Copy link
Member Author
xinglie commented Apr 28, 2017

@bigfengyu 非常感谢反馈,这个说明里确实用新版本有点问题,路径引用问题我已修改。
另外事件那块我暂不确定这样改了之后是否就正常了,模板这块推荐使用magix-combine工具进行打包到js中,http://thx.github.io/magix/#!/tutorial?s=intro
这里有完善的教程。

@bigfengyu
Copy link

@xinglie 今早又看了一下,路径引用问题是这样的:

您访问的可能是 localhost:8080/ 而我访问的是 localhost:8080/index.html,所以导致引用不正确,为了保证通用性,可以写成 location.origin + '/node_modules/magix/dist/cmd/magix-debug'

@xinglie
Copy link
Member Author
xinglie commented Apr 28, 2017

@bigfengyu 感谢提醒,我回头把教程之类的再认真过一遍,减少这样的问题发生。你在使用时,有任何问题都欢迎留言交流哦。

@bigfengyu
Copy link

找到了一个文档中的 typo~

地址:

https://thx.github.io/magix/#!/guide?s=view-ehandling

位置:

我们可以调用e.stopPropagation()来阻止冒泡,如下

// app/views/index.js
var Magix = require('magix');
module.exports = Magix.View.extend({
    render:function(){
        this.setHTML(this.id,'app/views/index rendered');
    },
    'outer<click>':function(e){
        console.log('outer clicked');
    },
    'inner<click>':function(e){
        console.log('inner clicked');
        e.stiopPropagation();   // typo
    }
});
8000

@xinglie
Copy link
Member Author
xinglie commented May 5, 2017

@bigfengyu 非常感谢,下周就处理

@bigfengyu
Copy link

您好,我尝试使用 gulp doc 命令构建 doc 失败,可能是前些时候对于 ./tool/gulpfile.js 中 type 变量的改动影响了构建过程。

bogon:tool fengyu$ gulp doc
[17:20:38] Starting 'combine'...
[17:20:38] Finished 'combine' after 45 ms
[17:20:38] Starting 'doc'...
[17:20:38] 'doc' errored after 239 μs
[17:20:38] Error: ENOENT: no such file or directory, open '../dist/cmd,amd,kissy,webpack/magix-debug.js'

@xinglie
Copy link
Member Author
xinglie commented May 9, 2017

@bigfengyu 我修复了。之前变量type并不是逗号分割的字符串,后来我修改了type但未修改doc,导致不能构建doc,另外构建出来的doc数据并不在magix目录下,而是和magix同级的magix-doc3目录。https://github.com/thx/magix-doc3 你需要把这个克隆到与magix平级的目录下。

@ShiveringPan
Copy link

你好,我按照教程学习magix时遇到问题. Magix 3.2.0版本
教程内有的例子代码缺少了一些$符号. 在局部刷新的例子代码中
render: function() {
this.$updater.set({
a: 10,
b: 20
}).digest();
}
使用这个引起报错,不知道如何解决,请指教
(index):90 Uncaught TypeError: Cannot read property 'replace' of undefined
at Updater_UpdateDOM (magix-debug.js:2027)
at Updater.digest (magix-debug.js:2162)
at NView.tes (list.js:208)
at G_ToTry (magix-debug.js:136)
at HTMLBodyElement.Body_DOMEventProcessor (magix-debug.js:1793)
at HTMLBodyElement.dispatch (jquery.js:5201)
at HTMLBodyElement.elemData.handle (jquery.js:5009)

@zwjat
Copy link
zwjat commented Jan 21, 2022

magix 区块化 和 vue 的区块化 有什么 本质的区别吗

@xinglie
Copy link
Member Author
xinglie commented Jan 21, 2022

@zwjat 请使用cli工具https://github.com/thx/thx-cli 进行新版本的尝试。
同样的问题不同的解法而已,可以尝试体会下

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants
0