magix icon indicating copy to clipboard operation
magix copied to clipboard

Magix is designed to construct large scaled,complex interactions app.

Results 19 magix issues
Sort by recently updated
recently updated
newest added

## 什么是区块 其实html标签就是区块,比如 div span a等标签。前端工程师就是在重复使用、组装这些区块(html标签)形成最终的需求页面。这是最原子的区块,我们要达到想要的页面效果,就得不停的重复嵌套这些区块。 但是呢,通常我们所说的`区块`是这些html标签的组合。比如当我们开发一个页面时,通常都是由多个逻辑关联不强的区块组成的,如常见的页头、页尾、内容区。这些区块通常是由多个html标签组合而成的。 我们可以借签html标签的这种嵌套及DOM Tree思路的,开发一套用于组合嵌套这种大区块的框架。我们把一个复杂的页面拆分成n个区块来开发,再由框架来便利的组合它们。这就是接下来要介绍的magix做的事情 ## 定义区块 在这里我们把区块定义为由一段`html`标签组成的代码片断,区块最小是一个标签,如``。区块可以像`html`标签一样嵌套,即一个区块可以由多个子区块组成 ## 项目中的区块 当我们在开发一个项目时,如前面提到的页头、页尾、内容区等,这些在我们项目里就是一个个区块,当然像内容区我们仍然可以再拆分子区块。像页头、页尾在项目里可以理解为原子区块,没必要再拆分了。这些区块应该很容易被复用。 ## 准备工作 magix适配了不同的加载器与dom操作类库,有amd、cmd及kissy,可[点击这里](https://github.com/thx/magix/tree/master/dist)查看,当然您也可以自己定制,定制方法[点击这里](https://github.com/thx/magix/issues/10) 接下来我们使用cmd版本,即seajs+jq来讲解magix的区块化管理 ## 安装 新建一个magix-test目录,在magix-test目录里放上package.json文件如下: ``` js { "name": "magix-test", "version": "1.0.0", "description":...

> 通过继承Magix.View来实现自己的view ### 通过Magix.View.extend方法来实现 ```js let Magix = require('magix'); module.exports = Magix.View.extend({ tmpl:'@demo.html', render(){ console.log('render ui') } }); ``` ### view的生命周期 #### 显式的init、render方法 >每个view默认都有一个init(初始化时调用,只会调用一次)和render(需要更新界面时被调用,可能会调用多次) ```js let Magix = require('magix'); module.exports...

> 通过继承Magix.View来实现自己的View ### 通过Magix.View.extend方法来实现 ```js import Magix from 'magix'; export default Magix.View.extend({ tmpl:'@demo.html', render(){ console.log('render ui') } }); ``` ### view的关键方法和事件 #### 显式的ctor、init、render方法 >每个view默认都有一个ctor、init(初始化时调用,只会调用一次)和render(需要更新界面时被调用,可能会调用多次) ```js import Magix from 'magix'; export...

```js //#exclude = define define('scroll', ['magix', '$'], (require, exports, module) => { let Magix = require('magix'); let $ = require('$'); let { Router, Vframe } = Magix; let checkVframes =...

目前 magix本身已经支持了虚拟dom diff。 但是做的是先`模板编译`,再`运行时字符串转换`到vdom,再去`diff`。 这带来一些问题: * 模板编译这块因为是渲染之后变成,需要处理很多html实体转换的问题,参数透传也很麻烦 * 运行时转换vom性能应该比较差,当然期待后续的具体测试。 另外,项目人员使用magix时经常会纠结语法的问题。 基于这些考虑,我们是否可以直接用jsx去写magix解决这些问题。

在magix项目中,所有事件都是绑定在body上的。利用事件的冒泡,在body上监听到相应的事件后,查找包含mx-eventType的节点与对应的处理事件的view。 > 对于$win与$doc是2个特殊的节点,这2个是直接绑定,其它事件均是代理在body上 对于一些不冒泡的事件,如节点的scroll事件,img的load、error事件等无法通过类似mx-error进行方便的监听

先说普通事件代理,以`jQuery`为例 ``` $(document.body).on('click','p',function(e){ }); ``` 这样其实是为`document.body`上绑定一个`click`事件,当鼠标在页面上点击时,看点击的元素是否是`p`元素,如果是则触发,不是则向从当前节点向上查找到符合的`p`元素,一直查到`body`。这里其实是有性能问题的(jQuery已经弃用的live),稍后我们再讨论并给出解决方案。 事件代理其实就是把事件处理函数绑定在父级,通过事件冒泡的特点,识别触发事件的元素是否是自已期望的元素。对,重点是这个事件冒泡 `Magix`中的事件代理的过程是这样的:把相应的事件绑定在父节点后,当事件发生在父节点里,父节点的事件处理函数被调用后,从触发事件的节点(`target`)开始,判断节点是否有`mx-eventType`属性,如果有则停下来调用相应`view`的事件处理函数,如果没有则向上查找,直到父节点 再来看`Magix1.0`之前的事件代理方案 当前`view`使用的事件都统一绑定到`vframe`根节点上,而`vframe`又可以嵌套,比如嵌套后的结构如下: ![Delegate Event](https://raw.githubusercontent.com/thx/magix/gh-pages-backup/assets/img/article-de-0.png) 我们的事件是绑定在`vframe`上的,当`vframe2`与`vframe1`绑定相同类型的事件时,比如`click`,而`vframe2`的`view`与`vframe1`的`view`具有相同的事件处理函数时,比如`selectAll`,那么问题就来了:鼠标点击在`vframe2`的SelectAll checkbox上时,`vframe2`先处理,而同时事件冒泡,冒泡到`vframe1`上时,`vframe1`的`selectAll`方法同样会被触发。 这里因为`vframe1`节点与`vframe2`节点都绑定了`click`事件,而由于事件冒泡的原因,同时事件类型及方法名又一致,当点击在`vframe2`内部时,`vframe2`处理完事件向上冒泡到`vframe1`,导致`vframe1`又处理了一遍,那或许你会说为什么不取消事件冒泡呢? 因为在我们的项目中,我们有可能引入其它组件,比如弹出日历等,需要鼠标点击在页面其它位置时日历需要隐藏消失。所以我们不能直接就把事件冒泡取消,否则日历也无法隐藏(像日历这种通常是绑定在`document`,需要相关事件冒泡到`document`) 问题出来了总得有个解决办法 第1个解决方案: 明确事件的处理`vframe`,类似上图,当鼠标点击在`vframe2`时,当`vframe2`处理完事件后,给打一个标记,标明当前事件是被处理过的,当`vframe1`收到后,先判断是否是处理过的,如果是处理过则不再理会 说到这里,大家可以想象一下,如果嵌套的`vframe`比较多时,鼠标点击在最内部的`vframe`时,由于事件冒泡,冒泡到每一层的`vframe`时,这一层的`vframe`都需要对事件做一次判断,而这些判断其实是不必要的,因为事件已经被内部`vframe`处理了,为什么还在再次判断?这地方多少会有些性能损耗 第2个解决方案: 把代理节点提高到`body`上,如果事件代理在`body`上而不是`vframe`上,把注册在`vframe`上相同的监听统一合并到`body`上,这样`vframe`节点不需要注册任何事件,对于嵌套的`vframe`,也是统一在`body`上处理事件,不需要每一层`vframe`的判断了。 该方案所有事件在绑定时,不管什么事件类型都绑定的是同一个事件处理函数,在这个事件处理函数内部再决定调用哪一个view的处理函数。内部针对magix的特点,对事件这块再特殊优化,从而提升性能,原理接下来讨论 回到开头我们的那个问题(jQuery live):事件是绑定在`body`上的,每当事件发生时,我们都要从发生事件的节点向上查找带有`mx-eventType`标识的节点,直到`body`。那我们来看一种情况: ![Delegate Event](https://raw.githubusercontent.com/thx/magix/gh-pages-backup/assets/img/article-de-2.png) 假设html结构是这样的: ``` html...

> 在我们做一个复杂的长列表页面时,我们通常要优先加载主功能,或者滚动到可视区域时才加载相应的view,这时候就可以使用该插件。 源码: ```js let Magix = require('magix'); let $ = require('$'); let { Vframe, Event: MEvent, mix } = Magix; let WaitObserver = mix({}, MEvent); let Base = Vframe.prototype;...

> 该插件基本准确反映项目中加载及渲染的进度 **kissy版本只需要把seajs.use改成kissy.use即可** #### 使用方式一 通过script标签的方式直接引入到主页面上,如 ```html ``` #### 使用方式二 通过magix提供的扩展机制加载,如 ```js let Magix = require('magix'); Magix.boot({ exts:['progbressbar'] }); ``` #### 以下是插件源码,保存成progressbar.js ```js seajs.use('magix', Magix => { let ProgressBar =...

在magix项目中我们一直使用hash做为url的记录。 当然我们也支持history.pushState来改变url [magix中的url解析与处理](https://github.com/thx/magix/issues/12) 最终我们的url处理成path与params 两部分,而在magix项目中,通常path与view一一对应。 比如我们做一个展示用户相册的功能,我们可能这样设计url ```bash /photo?userId=xxx&page=1&page_size=20 ``` 因为我们的模块photo是固定的,变化的只是用户id,所以我们把模块photo设计在path中,变化的userId放在参数中。 看过别的前端或后端web框架的,通常它们都有url重写功能,比如我们把这个url重写成 ```bash /xxx/photo?page=1&page_size=20 ``` 把用户id放在path中,对于个人用户会更友好一些 在magix当中该如何做呢? > 考虑到向前兼容,旧的url我们要仍然支持 参考 UrlRewrite的设计 [http://blog.csdn.net/dyllove98/article/details/9281453](http://blog.csdn.net/dyllove98/article/details/9281453) 在magix的配置项中增加rewrites配置,示例如下 ```js Magix.config({ rewrites:[{ from:/$\/(.*)/photo$/, to:'photo?user=$1' }], routes:{ '/photo':'app/views/default'...