首页 > 网站 > WEB开发 > 正文

Ques前端组件化体系

2024-04-27 14:06:49
字体:
来源:转载
供稿:网友

Ques前端组件化体系

2015-07-19 23:56 by Justany_WhiteSnow, ... 阅读, ... 评论, 收藏, 编辑

Ques是一套组件化系统,解决如何定义、嵌套、扩展、使用组件。

传统开发模式的痛点

  • 无法方便的引用一个组件,需要分别引用其javascriptTemplateCSS文件
  • 我们期望能以MV*的方式去写代码,结果发现只有JavascriptMV*
  • UI库打包成一坨(类似Bootstrap),但是实际上UI库伴随产品迭代在反复变更,每次打开网站,用户依然反复下载UI库
  • CSS没有命名空间导致两个组件容易冲突
  • 组件无法嵌套或者无法扩展,所以实际上组件根本无法复用
  • 组件无法复制后可用,在组件无法嵌套或无法扩展的情况下,连定制一个组件都困难连连
  • 每次性能优化都将代码弄的很恶心,不好维护

UI组件

UI组件使用来专门做UI的组件,其特点为只有模版、样式文件。系统会根据用户在页面已使用的UI组件动态引用其依赖的资源。注意,UI组件的前缀必须是ui-

下面是一个简单的ui-button的例子:

定义
  • CSS文件
.ui-button {    display: inline-block;    padding: 6px 12px;    margin-bottom: 0;    font-size: 14px;    font-weight: 400;    line-height: 1.42857143;    text-align: center;    white-space: nowrap;    vertical-align: middle;    touch-action: manipulation;    cursor: pointer;    user-select: none;    background-image: none;    border: 1px solid transparent;    border-radius: 4px;    text-transform: none;    -webkit-appearance: button;    overflow: visible;    margin: 0;}.ui-default {    color:#333;    background-color:#fff;    border-color:#ccc}.ui-default.focus,.ui-default:focus {    color:#333;    background-color:#e6e6e6;    border-color:#8c8c8c}.ui-default:hover {    color:#333;    background-color:#e6e6e6;    border-color:#adadad}// 后面可添加更多样式的按钮
  • 模版文件
<button class="ui-button">    <content></content></button>
效果
  • 在页面上直接引用:
<ui-button class="ui-default">DEFAULT</ui-button><ui-button class="ui-success">SUCCESS</ui-button><ui-button class="ui-info">INFO</ui-button><ui-button class="ui-warning">WARNING</ui-button><ui-button class="ui-danger">DANGER</ui-button>
  • 展示

这样我们就实现了一个ui-button组件,其可以在任意其他组件中嵌套使用。其以来的资源会动态引用,也就是说,只有我们使用了ui-button他的模版和样式才会被引入。

备注
  • 由于我们使用了强大的cssnext,所以CSS吐出来的时候会根据配置转换成兼容版本,也就是说我们只需要按照标准去写CSS,系统会自动帮我们适配:
.ui-button {    display: inline-block;    padding: 6px 12px;    margin-bottom: 0;    font-size: 14px;    font-weight: 400;    line-height: 1.42857143;    text-align: center;    white-space: nowrap;    vertical-align: middle;    -ms-touch-action: manipulation;        touch-action: manipulation;    cursor: pointer;    -webkit-user-select: none;       -moz-user-select: none;        -ms-user-select: none;            user-select: none;    background-image: none;    border: 1px solid transparent;    border-radius: 4px;    text-transform: none;    -webkit-appearance: button;    overflow: visible;    margin: 0;}.ui-default {    color:#333;    background-color:#fff;    border-color:#ccc}.ui-default.focus,.ui-default:focus {    color:#333;    background-color:#e6e6e6;    border-color:#8c8c8c}.ui-default:hover {    color:#333;    background-color:#e6e6e6;    border-color:#adadad}
  • 注意到我们引用了Shadow DOM中的<content>标签,<content>标签作为Component内部的插入点(或者可以理解成占位符),当外部引用该Component时可以从外部向内部插入节点,例如:
<ui-button class="ui-default">DEFAULT</ui-button>

则表示向Component的插入点插入DEFAULT这个文字节点。关于<content>标签我们后面还会提到其高级应用。

Component

Component是最常见的组件,其拥有模版、样式以及逻辑文件,使得这种Component更像一个自定义的元素(Custom Element)。体验上像引入一个<input>标签一样,我们可以设置她的值,绑定她的事件,调用她的函数。

下面是一个dialog组件的例子:

定义
  • CSS文件:
.$__mask {    position: fixed;    width: 100%;    height: 100%;    padding: 0px;    margin: 0px;    left: 0px;    top: 0px;    z-index: 999;    background-color: rgba(0,0,0,.6) !important;    display: none;}.$__mask.show {    display: block;}.$__$ {    position: fixed;    top: 10%;    opacity: .5;    left: 50%;    width: 490px;    margin-left: -245px;    z-index: 999;    background: #fff;    font-size: 14px;    border-radius: 4px;    overflow: hidden;    transition: all 200ms ease-in-out;}.$__mask .$__$.show {    top: 50%;    opacity: 1;}.$__$ .header {    height: 30px;    line-height: 30px;    text-indent: 12px;    background: #039ae3;    color: #fff;    font-size: 14px;}.$__$ .body {    padding: 30px 40px;    position: relative;    line-height: 24px;    max-height: 500px;    overflow-y: auto;    overflow-x: hidden;}.$__$ .msg {    margin-left: 66px;    position: relative;    top: 10px;    Word-break: break-all;}.$__$ .bottom {    margin: 20px;    text-align: right;}.icon-info-large {    background: url(http://9.url.cn/edu/img/sPRite/common.a8642.png) -41px -276px no-repeat;    width: 36px;    height: 36px;    display: block;    float: left;    margin-top: 4px;}
  • 模版文件:
<div class="$__mask" q-class="show: isShow">    <div class="$__$">        <div class="header">            <content select="header *"></content>        </div>        <div class="body">            <div class="icon-info-large"></div>            <div class="msg">                <content select="article *"></content>            </div>        </div>        <div class="bottom">            <ui-button class="ui-info" q-on="click: submit">确定</ui-button>            <ui-button class="ui-default" q-on="click: cancel">取消</ui-button>        </div>    </div></div>
  • Javascript文件:
var $ = require('jquery');module.exports = {    data: {        isShow: false    },    methods: {        submit: function () {            this.$emit('submit');        },        cancel: function () {            this.$emit('cancel')                .hide();        },        show: function () {            this.$set('isShow', true);        },        hide: function () {            this.$set('isShow', false);        }    },    ready: function () {        var dialog = $('.$__$', this.$el);        this.$watch('isShow', function (val) {            if (val) {                setTimeout(function () {                    dialog.addClass('show');                }, 20);            } else {                dialog.removeClass(dialog, 'show');            }        }, false, true);    }}
效果
  • 在页面直接引入<dialog>
<dialog id="my-dialog">    <header>        欢迎使用Ques    </header>    <article>        Hello World!    </article></dialog>
  • 则可以在Controller中直接使用,例如拿到其实例,再调用其show方法,将其展示:
var Q = require('Q');Q.get('#my-dialog')    .show();
  • 展示

备注
  • 由于CSS没有命名空间,所以我们引入了两个$__$__$两个占位符来充当命名空间,系统会自动转换成当前Component的名字,所以CSS最终变成:
.dialog__mask {    position: fixed;    width: 100%;    height: 100%;    padding: 0px;    margin: 0px;    left: 0px;    top: 0px;    z-index: 999;    background-color: #000000 !important;    background-color: rgba(0,0,0,.6) !important;    display: none;}.dialog__mask.show {    display: block;}.dialog {    position: fixed;    top: 10%;    opacity: .5;    left: 50%;    width: 490px;    margin-left: -245px;    z-index: 999;    background: #fff;    font-size: 14px;    border-radius: 4px;    overflow: hidden;    -webkit-transition: all 200ms ease-in-out;            transition: all 200ms ease-in-out;}.dialog__mask .dialog.show {    top: 50%;    opacity: 1;}.dialog .header {    height: 30px;    line-height: 30px;    text-indent: 12px;    background: #039ae3;    color: #fff;    font-size: 14px;}.d
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表