GithubHelp home page GithubHelp logo

gmu's Introduction

Notice

Build State Build Status

GMU

GMU是基于zepto的轻量级mobile UI组件库,符合jquery ui使用规范,提供webapp、pad端简单易用的UI组件。兼容iOS3+ / android2.1+,支持国内主流移动端浏览器,如safari, chrome, UC, qq等。 GMU由百度GMU小组开发,基于开源BSD协议,支持商业和非商业用户的免费使用和任意修改,您可以通过get started快速了解。

Quick Start

命令行工具

命令行工具提供代码打包,规范检测和生成文档功能。

环境依赖

  • git
  • node(包括npm)
  • grunt (npm install -g grunt-cli)

1. 如何跑Demo

如果想要本地跑demo需要做以下几步操作。由于gmu没有直接存放zepto的代码,而是引用了zepto官方仓库。所以需要通过git命令 去zepto官方仓库取代码,然合并成zepto.js。不过这个过程已经写好了脚本,只要按以下步骤操作,脚本能把这个工作完成。

打开命令行工具。

  1. git clone https://github.com/gmuteam/GMU.git 把gmu代码checkout到当前目录下的GMU目录里面
  2. cd GMU 进入GMU目录
  3. npm install 安装node依赖。
  4. grunt dist 生成合并的zepto.js, gmu.js到dist目录。

2. 打包代码

grunt concat

grunt concat_gmu

3. 代码规范检测

gmu所有的代码要求通过此内定代码规范, 通过以下命令可以得到检测结果 grunt jsbint

4. 生成文档

通过以下命令可以在doc目录下生成静态文档,也可以在线查看; grunt doc

关于dist目录

如果不想自己打包也可以直接使用 dist 目录中打包好的资源,其中包括

reset.css
gmu.css
zepto.js
gmu.js

按顺序直接引用即可,此外,dist 中还有压缩版本,可以按需使用。

需要注意的是,GMU中有些插件是无法共存的,因此 dist 目录中的 gmu.js 中并不包含这些插件,如需自定打包规则请参考之前的打包教程。

反馈bug

如果您有任何关于GMU或移动前端开发中的问题,可以在QQ群中讨论,也可以通过git issue给我们反馈bug,我们会尽快解决。 当然,我们更欢迎您的fork,为GMU添砖加瓦。

联系我们

  • QQ:127405799 (已满) 339271891 (群2)305735121 (群3)
  • Email:[email protected]

gmu's People

Contributors

2betop avatar amythos avatar bryant1410 avatar danyan avatar gmuteam avatar miller avatar zhoumm1008 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gmu's Issues

GMU开发规范

概述

本文列出了GMU开发过程中应该遵循的规范,并做出相应的描述;开发过程中应该原则上遵循本文列出的规范。
本规范主要包括如下部分:

  • 文件组织
  • 样式
  • 定义新组件
  • 默认参数
  • 组件模板
  • 必选参数多选值的拆分
  • 组件插件
  • 组件初始化
  • 对事件的处理
  • destroy的处理
  • 其他说明

文件组织

每个组件放在以组件名命名的文件夹内:

  • 组件核心功能以组件名命名比如Panel.js
  • 组件必选参数多选值拆分文件以“参数名.值”命名,比如display.push.js
  • 插件已“$插件名”命名,比如$drag.js

比如:

.
├── widget
    └── Panel Panel组件文件夹
        ├── Panel.js Panel核心功能文件
        ├── display.push.js display参数push选项实现文件
        ├── display.overlay.js display参数overlay选项实现文件
        ├── $drag.js drag插件
    └── Suggestion Suggestion组件文件夹
        ├── Suggestion.js Suggestion核心功能文件
        ├── $iscroll.js iscroll插件

样式

gmu组件的classname使用gmu作为命名空间,组件根元素使用“gmu-组件名”命名,比如Dialog最外层容器的classname为‘gmu-dialog',DOM片段的classname使用“gmu-组件名-片段名”的方式命名,比如Dialog的title命名应该为'gmu-dialog-title'

定义一个新组件

gmu.define('Panel', {
    // 默认参数
    defaultOptions: {
        key: value,
        key: value,
        key: value,
        ...
    },

    // 组件模板
    template: '<div><ul>{{#list}}<li>{{item}}</li>{{/list}}</ul></div>',

    // 模板转换成html片段的方法
    tpl2html: function(data){
        // do compile...
        return html;
    },

    // 默认构造函数   
    _init: function(){}
}, gmu.Layer);

定义一个新组件使用gmu.define方法:

  • 第一个参数为组件名,首字母大写;
  • 第二个参数为一个对象字面量,其中包含defaultOptions(组件默认参数)、template(组件模板)、tpl2html(模板转换成html片段的方法)、_init(默认构造函数)以及组件的其他方法或者属性;
  • 第三个参数为可选参数,表示组件从哪个组件继承。

组件模板

组件模板可以使用字符串,也可以是一个对象:

template: '<div><ul>{{#list}}<li>{{item}}</li>{{/list}}</ul></div>'

或者

template: {
    title: '<div class="gmu-dialog-title">{{title}}</div>',
    body: '<div class="gmu-dialog-foot">{{body}}</div>',
    foot: '<div class="gmu-dialog-foot">{{title}}</div>'
},

模板转换成html片段

当组件模板只有一个时,tpl2html为一个方法,接收一个data参数。

tpl2html: function(data){
    // do compile...
    return html;
}

当组件模板是一个map时,tpl2html可以是一个map也可以是一个方法。

// tpl2html用map实现
tpl2html:{
    title: function(data){
        // do compile...
        return titlehtml;
    },
    body: function(data){
        // do compile...
        return bodyhtml;
    }
}

或者

// tpl2html用函数实现
tpl2html: function(name, data){
    if(name === 'title')
        // do titlecompile...
    else if(name === 'body')
        // do bodycompile
    return html;
}

必选参数多选值的拆分

对于组件的必选参数,如果多个可选值是相互独立的,建议采用option的方式拆分。
比如panel里面的display参数,有三个可选值:push、overlay、reveal。
使用option的方式拆分如下:

// display.push.js
gmu.Panel.option(display, 'push', function(){
        var me = this;
        me.on('setDisplay:panel', function(e){
            // do display...
        });
    }
);

// display.overlay.js
gmu.Panel.option(display, 'overlay', function(){
        var me = this;
        me.on('setDisplay:panel', function(e){
            // do display...
        });
    }
);

// display.reveal.js
gmu.Panel.option(display, 'reveal', function(){
        var me = this;
        me.on('setDisplay:panel', function(e){
            // do display...
        });
    }
);

组件的插件

每个组件类都有一个register方法,通过register方法可以扩展出一个插件。
register方法的第一个参数为插件名,第二个参数为一个对象字面量,其中至少包含一个init方法,作为插件的初始化函数,该函数会在组件的构造函数执行完后执行。
插件的文件名使用$+插件名的方式命名,比如Panel的drag插件,文件名为$drag.js

// $drag.js
gmu.Panel.register('drag', {
    init: function(){
        // do something...
    },

    drag: function(){}
});

组件初始化

组件有两种初始化方式:
一种是形如$('#dialog').dialog()的方式;
一种是形如gmu.Dialog('#dialog')的方式。
每个组件需要对这两种初始化方式做抹平处理。
用户使用$('#dialog').dialog()方式调用时,底层会给组件传入setup:true的标识作为参考。
组件内部对初始化方式的判断不应该仅仅依赖setup标识,应该综合用户传入的参数以及DOM节点来判断。

对事件的处理

出于向下兼容的考虑,目前事件(包括浏览器原生事件和自定义事件)全部采用直接在DOM元素上挂载监听的方式。
使用option方式拆分必选参数可选项时,自定义事件采用新的观察者事件机制。

destroy的处理

组件destroy的时候应该移除所有的事件,并且对DOM结构进行还原。
原则上讲,destroy后DOM应该还原到组件初始化之前的状态。

其他说明

  • 组件代码都放在闭包中,undefined从函数的形参中取
  • _init为组件的初始化方法,原则上不建议在_init中进行构造DOM结构的操作
  • 各个组件的zIndex取值,暂时不做统一处理
  • 针对特定浏览器的hack,需要添加注释
  • 浏览器原生事件需要加'.组件名'作为命名空间,自定义事件不需要命名空间

imglazyload是否考虑支持background-image加载

现在是直接设置src,但background-image形式加载图片可以通过cover实现自动缩放。

现在只能手动改源码:
!isImg && $div.replaceWith($img);改为$div.attr('style', 'background-image: url('+url+')');

slider组件的一个bug

$('#slider').slider( { index:2} );
$('#slider').slider( 'getIndex' );
这样执行过之后,会显示第一张图片

出师不利

解决了phantomjs安装问题,npm install后,可惜到grunt dist卡死!
1__grunt_dist__git-remote-http___--

imglazyload在页面动态渲染时图片不加载的问题

使用前端MVC框架,页面出来后初始化imglazyload,但页面跳转,再返回时重新初始化imglazyload,发现图片无法加载。
跟踪调试后发现这段:

if ($.isFunction($.fn.imglazyload.detect)) {    //若是增加图片,则处理placeHolder
  _addPlsHolder();
  return this;
};

会导致页面第二次加载时,后面的逻辑中断。

解决方案:在每次重新渲染页面时先设置$.fn.imglazyload.detect = null;

感觉这个问题对于新手不友好,期待能在源码中解决。

关于入门介绍的问题

由群友 Joel 反馈

我在windows下安装有两个地方被卡住
1:npm install 的时候phantomjs-1.9.7 这个文件是下载不了的 要先翻墙或者手动下载到那个目录才行
2: grunt dist ...这命令要在git bash命令行下面用才行 否则会报 error git Use

npm install安装出错phantomjs

phantomjs需要翻墙下载,我手动下载后放到npm install对应的phantomjs那个目录下(把整个zip文件放过去),再试试,祝你成功

npm install时出错

[email protected] install /root/GMU/node_modules/grunt-lib-phantomjs/node_modules/phantomjs
node install.js

Downloading http://cdn.bitbucket.org/ariya/phantomjs/downloads/phantomjs-1.9.7-linux-x86_64.tar.bz2
Saving to /root/GMU/node_modules/grunt-lib-phantomjs/node_modules/phantomjs/phantomjs/phantomjs-1.9.7-linux-x86_64.tar.bz2

events.js:72
throw er; // Unhandled 'error' event
^
Error: connect ECONNREFUSED
at errnoException (net.js:904:11)
at Object.afterConnect as oncomplete
npm ERR! [email protected] install: node install.js
npm ERR! Exit status 8
npm ERR!
npm ERR! Failed at the [email protected] install script.
npm ERR! This is most likely a problem with the phantomjs package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR! node install.js
npm ERR! You can get their info via:
npm ERR! npm owner ls phantomjs
npm ERR! There is likely additional logging output above.

npm ERR! System Linux 2.6.32-431.11.2.el6.x86_64
npm ERR! command "node" "/opt/npm/global/lib/node_modules/cnpm/node_modules/.bin/npm" "--userconfig=/root/.cnpmrc" "--disturl=http://dist.cnpmjs.org" "--cache=/root/.npm/.cache_cnpm" "--registry=http://r.cnpmjs.org" "install"
npm ERR! cwd /root/GMU
npm ERR! node -v v0.10.26
npm ERR! npm -v 1.4.6
npm ERR! code ELIFECYCLE
npm ERR!
npm ERR! Additional logging details can be found in:
npm ERR! /root/GMU/npm-debug.log
npm ERR! not ok code 0

gmu 里面的demo 使用了settime out 我尝试做单元测试 但是

new iScroll('S_widgets');//ps 这里为啥会在单元测试时候报错呢?
iScroll 报错
function pageend(func){
function mp(fn){
return function(){

        try{
            new iScroll('S_widgets');//ps 这里为啥会在单元测试时候报错呢?
        }
        catch(e)
        {

        }

        $(window).trigger('resize');
        fn();
    }
}
var  pagefun=mp(func);
setTimeout(pagefun, 200);

}

有谁针对页面使用 做这个的单元测试吗?
PS 正常运行时候没问题

GMU测试标准(初稿)

GMU测试标准根据百度全网的移动设备和浏览器统计数据制定,每一个月更新一次。
测试标准包括如下部分:

  • 移动设备(操作系统)
  • 浏览器
  • 分辨率
  • webview
  • 性能
  • 低网速

其中,设备、浏览器、分辨率按照占比分为A级和B级两部分,A级原则上需要全部测试通过,B级保证不影响页面功能的使用。

移动设备(操作系统)

A级:IOS6.、IOS5.、IOS4.3、Android2.3、Android4.0、Android4.1、Android2.2
B级:IOS4.1、IOS4.2、Android2.1、Android3.2

浏览器

A级:UC8.*以上版本、Android默认浏览器、ISO默认浏览器、QQ浏览器、百度浏览器、360浏览器、Chrome浏览器
B级:其他浏览器

分辨率

A级:320x480、480x800、800x1280、360x640
B级:其他分辨率

webview

待补充

性能

待补充

百度全网移动设备(操作系统)、浏览器、分辨率占有率

注:基于贴吧无线5月22日数据
移动设备(操作系统):

浏览器:

分辨率:

压缩后代码失效

下载框架的时候如果选了“是否合并(合并后共317.81K,不包含zepto部分的体积)” 之后会得到两个文件,一个zepto.js 一个 gmu.js 引入这两个文件运行的代码得不到预期的效果,比如navigator那里的实例代码,必须下载那个分散的包,然后单独引入组件,实例才能显示出预期的效果。

而GMU本身又拆散成了很多小文件,每次都要单独引入很麻烦,更重要的是在生产环境里会导致性能过差,希望能够解决一下该问题。

refresh bug

Uncaught TypeError: Object # has no method 'refresh'
我在使用refresh的时候找不到这个方法!
如何设置点击才加载,现在默认是上拉就加载更多

var currentPage = 1;
var totalPage = "{{data_result.totalpage}}";
(function () {
    $('.ui-refresh').css('height', window.innerHeight - ($('header').height() || 42)).refresh({
        ready : function(dir, type) {
            var me = this;


            if (currentPage >= parseInt(totalPage)) {
                me.disable('down');
                me.afterDataLoading();
                return;
            }

            currentPage += 1;
            $.getJSON('{{base_url}}/custom2?CategoryID={{Category._id}}&isAjax=1&Page=' + currentPage, function(data) {
                if (data.error_code == 0) {
                    var $list = $('.data-list');
                    html = (function(data) {//数据渲染
                        var liArr = [];
                        $.each(data.data.rows, function() {
                            this['base_url'] = "{{base_url}}";
                            this['AddTime'] = (new Date(this['AddTime'] * 1000)).format('yyyy-mm-dd');
                            this['Extend']['Content'] = strip_tags(this['Extend']['Content']).substring(0, 50);
                            this['Extend']['Images'] = this['Extend']['Images'].length > 0 ? this['Extend']['Images'][0] : '';
                            liArr.push(ich.item(this, true));
                        });
                        return liArr.join('');
                    })(data);

                }
                $list[dir == 'up' ? 'prepend' : 'append'](html);
                me.afterDataLoading();
                //数据加载完成后改变状态
            });
        }
    });
})();

修复Zepto中offset setter bug。

修复Zepto中offset setter bug。
比如 被定位元素满足以下条件时,会定位不正确

  1. 被定位元素不是第一个节点,且prev兄弟节点中有非absolute或者fixed定位的元素
  2. 被定位元素为非absolute或者fixed定位。

用refresh.iscroll时没有打包refresh.default.css文件

根据demo中,refresh+iscroll是带refresh.default样式的。
但实际Grunt打包时,只包含了refresh.iscroll.default.css,而refresh.default.css并未被引入。

m && ~opts.availableThemes.indexOf(m[1]) && (css[m[1]] = item );

这里循环时m[1]的值一直为default,refresh.iscroll.default.cssrefresh.default.css复写了。

或者是我理解错误,需要另行其他设置?

gmu脚本引入顺序不同影响正常效果

运行grunt concat_gmu打包生成整体文件,和示例中单个文件引入运行效果完全不一样。以dropmenu为例,示例中有一个dropmenu_arrow.html文件,如果我引入'<script type="text/javascript" src="../../../src/widget/popover/placement.js"></script>'放置在dropmenu.js引入之前,则效果有误。可以说这和文件的加载顺序有关,感觉是覆盖了,难道文件之间有互斥有加载顺序依赖吗?

iOS7下matchMedia导致监听横竖屏切换不响应

定位在matchMedia.js中如下代码

$style.append('@media ' + query + ' { #' + id + ' { width: 1px; } }\n') ;

这句代码原本在iOS6/Android中是用于触发mediaMatch的,但是在iOS7中则会导致原生的mediaMatch不触发。

升级之前的解决方案可以适配iOS7直接使用原生mediaMatch即可。

GMU目前还不在bower里

Dialog 组件不支持第二种写法,传入的第一次参数,没用。

    $( el ).dialog( options )  zepto
    new gmu.Dialog( el, options )  instance

slider multiview下有bug

请复制以下代码,当选择一屏2个,loop为true时,点的个数会显示实际数量的2倍

$('#slider').slider({loop:true,viewNum:2,dots:true});

2.1.0版本 imglazyload.js 图片加载错误时候 报Uncaught RangeError: Maximum call stack size exceeded 错误

2.1.0版本 imglazyload.js 第88行,在图片加载失败时候控制台中会报
Uncaught RangeError: Maximum call stack size exceeded 错误

      on('error',function () {     //图片加载失败处理
            var errorEvent = $.Event('error');       //派生错误处理的事件
            $div.trigger(errorEvent);
            errorEvent.defaultPrevented || pedding.push(div);
            $img.off('error').remove();
        }).attr('src', $div.attr(opts.urlName));

refresh 可以实现仅click时加载数据吗?

我表述不行,贴代码。
$ele.refresh({
load:function(dir,type){
if(type=="click"){
$.ajax
}else{
//不加载,此时应该写什么。如果写me.afterDataLoading(dir)的话,控件就不能在当前的dir方向上进行加载了
}
}
});

$.location(fn, fn, options) 错误

$.location(function(rs){
console.log(rs)
})

google提示:
Uncaught TypeError: Object function (a,b){return A.init(a,b)} has no method 'location'

imglazyload

imglazyload 是否可以设置默认加载前的图片?
placeHolder 只能是纯文本

dialog组件性能问题

有用户在群里反应dialog在低端机有严重的性能问题,初步怀疑是mask问题,而且用户使用jqmobi的dialog同样带mask却不卡。

    杨:  10:36:05
    在安卓手机上用浏览器看dialog的演示页面就很卡,不知道大家有没有遇到这个问题。用的手机是配置比较低端的。但是用 弹出框定位 就比较顺畅

http://gmu.baidu.com/demo/widget/dialog/dialog_position.html

    GMU_2betop:  10:37:37
    那个mask性能开销大,不知道为什么
    GMU_2betop:  10:38:02
    可能是大面积的opacity的原因

    杨:  10:52:34
    其实我觉得不是mask的问题,因为用jqmobi也用mask的,但是反应仍然很顺畅

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.