Ques前端组件化体系

  • 时间:
  • 浏览:1
  • 来源:极速快3_快3官方网_极速快3官方网

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: 500;
    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: 500;
    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: 5000%;
    height: 5000%;
    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: 500%;
    width: 490px;
    margin-left: -245px;
    z-index: 999;
    background: #fff;
    font-size: 14px;
    border-radius: 4px;
    overflow: hidden;
    transition: all 500ms ease-in-out;
}

.$__mask .$__$.show {
    top: 500%;
    opacity: 1;
}

.$__$ .header {
    height: 500px;
    line-height: 500px;
    text-indent: 12px;
    background: #039ae3;
    color: #fff;
    font-size: 14px;
}

.$__$ .body {
    padding: 500px 40px;
    position: relative;
    line-height: 24px;
    max-height: 5000px;
    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: 5000%;
    height: 5000%;
    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: 500%;
    width: 490px;
    margin-left: -245px;
    z-index: 999;
    background: #fff;
    font-size: 14px;
    border-radius: 4px;
    overflow: hidden;
    -webkit-transition: all 500ms ease-in-out;
            transition: all 500ms ease-in-out;
}

.dialog__mask .dialog.show {
    top: 500%;
    opacity: 1;
}

.dialog .header {
    height: 500px;
    line-height: 500px;
    text-indent: 12px;
    background: #039ae3;
    color: #fff;
    font-size: 14px;
}

.dialog .body {
    padding: 500px 40px;
    position: relative;
    line-height: 24px;
    max-height: 5000px;
    overflow-y: auto;
    overflow-x: hidden;
}

.dialog .msg {
    margin-left: 66px;
    position: relative;
    top: 10px;
    word-break: break-all;
}

.dialog .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;
}

可不也能看见$__被转加进了dialog__,而$__$被转加进了dialog

  • 逻辑层亲戚亲戚亲们使用了MVVM库Q.js,这里就不细说了。

  • 这里还用到<content>标签的高级功能,select属性。select属性是用来选着实物符合选着器的节点进行替换。累似 :

<content select="header *"></content>

的意思是选着实物<header>标签内所有东西进行替换,好多好多 “欢迎使用Ques”就被替换进去了。

第三方Component

第三方Component是一套兼容方案,使得业务方不依赖Q.js也能定义一另俩个Component,但会 肯能系统无法控制第三方组件DOM的作用域,以及实现其扩展似乎没啥意思,好多好多 第三方无法嵌套和扩展。总的来说第三方Component本质上却说 系统给第三方一另俩个容器,他在上边干那此,系统就不管了。第三方组件一定以third-为前缀。

下面是一另俩个高亮代码third-code的例子:

定义
  • CSS文件:
.$__pre {
    width: 900px;
    margin: 10px;
}

/**  引入hightlight.js的css库  **/
@import "http://cdnjs.cloudflare.com/ajax/libs/highlight.js/8.6/styles/default.min.css";
  • 模版文件:
<pre class="$__pre">
    <code>
        <content></content>
    </code>
</pre>
  • Javascript文件:
module.exports = {
    bind: function () {
        var el = this.el,
            script = document.createElement('script');
        script.onload = function () {
            hljs.highlightBlock(el);
        }
        script.src = '//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.6/highlight.min.js';
        document.body.appendChild(script);
    },
    unbind: function () {}
};
效果
  • 引入third-code
<third-code>
    &lt;ui-button class=&quot;ui-default&quot;&gt;DEFAULT&lt;/ui-button&gt;
    &lt;ui-button class=&quot;ui-success&quot;&gt;SUCCESS&lt;/ui-button&gt;
    &lt;ui-button class=&quot;ui-info&quot;&gt;INFO&lt;/ui-button&gt;
    &lt;ui-button class=&quot;ui-warning&quot;&gt;WARNING&lt;/ui-button&gt;
    &lt;ui-button class=&quot;ui-danger&quot;&gt;DANGER&lt;/ui-button&gt;
</third-code>
  • 效果:

备注
  • 第三方Component还要实现另俩个接口bindunbind,即在容器创建时还要绑定那此,当容器删除时还要解绑那此。this会带来必要的东西,累似 容器、父级ViewModel等等。

组件嵌套

当组件可不也能嵌套,组件件可不也能拆成较小的颗粒,使得复用性大大提升。

下面亲戚亲戚亲们是一另俩个codeclick组件,其用途是高亮展示代码片段,点击代码弹出dialog,也却说 说亲戚亲戚亲们准备嵌套上边做出来的third-codedialog组件:

定义
  • CSS文件:
/** 可不也能给组件定义许多特殊样式,但为了简单亲戚亲戚亲们那此却说

做 **/
  • 模版文件:
<div>
    <third-code q-ref="code">
        <content></content>
    </third-code>
    <dialog q-ref="dialog">
        <header>欢迎使用Ques</header>
        <article>你点击了代码</article>
    </dialog>
</div>
  • Javascript文件:
var $ = require('jquery');

module.exports = {
    data: {},
    ready: function () {
        var code = this.$.code,
            dialog = this.$.dialog;
        // 点击代码,弹出dialog
        $(code.el).on('click', function () {
            dialog.show();
        });
    }
};
效果
  • 在页面上引用:
<codeclick>
    &lt;ui-button class=&quot;ui-default&quot;&gt;DEFAULT&lt;/ui-button&gt;
    &lt;ui-button class=&quot;ui-success&quot;&gt;SUCCESS&lt;/ui-button&gt;
    &lt;ui-button class=&quot;ui-info&quot;&gt;INFO&lt;/ui-button&gt;
    &lt;ui-button class=&quot;ui-warning&quot;&gt;WARNING&lt;/ui-button&gt;
    &lt;ui-button class=&quot;ui-danger&quot;&gt;DANGER&lt;/ui-button&gt;
</codeclick>
  • 展示:

备注
  • 亲戚亲戚亲们看多<content>标签却说 神奇的用法是可传递,亲戚亲戚亲们从third-code传递到codeclick,再传递到最实物。使得亲戚亲戚亲们可不也能在最实物改third-code实物的节点。

  • 亲戚亲戚亲们注意到q-ref却说 是Q.js用于组件嵌套从母Component(为了和扩展中的父Component其分开来,这里称之为母Component)拿到子Component的引用,同样可不也能拿到第三方Component的引用。

组件扩展

组件可扩展,则差别不大的组件可不也能继承同一另俩个父组件。

下面dialog组件扩展的例子,效果是弹出一另俩个dialog,要求输入内容:

定义
  • CSS文件:
  • 模版文件:
<dialog extend>
    <header>
        <h2>欢迎使用Ques</h2>
    </header>
    <article>
        <p>请输入要设置的值</p>
        <ui-input value="" q-model="curVal" q-on="keyup: submit | key enter" q-focus="focus"></ui-input>
    </article>
</dialog>
  • Javascript文件:
var filters = require('filters');

module.exports = {
    methods: {
        submit: function () {
            if (!this.curVal) {
                this.$set('focus', true);
            } else {
                this.$emit('submit', this.curVal);
                this.$set('curVal', '');
                this.hide();
            }
        },
        show: function () {
            // call super.show
            this.constructor.super.options.methods.show.call(this);
            this.$set('focus', true);
        }
    },
    directives: {
        focus: function (val) {
            val && this.el.focus();
        }
    },
    filters: {
        key: filters.key
    }
};
效果
  • 在页面上引用inputval
<inputval id="my-dialog"></inputval>
  • 在Controller调用其show最好的方法:
var Q = require('Q');

Q.get('#my-dialog').show();
  • 则页面弹出一另俩个弹出,要求输入值:

备注
  • 这里亲戚亲戚亲们引入extend属性,用于表示该组件继承哪个组件。

  • 亲戚亲戚亲们还复写了dialogsubmitshow最好的方法,但会 可不也能调用其父Componnet的最好的方法,如:

this.constructor.super.options.methods.show.call(this);

嵌套使用扩展组件

亲戚亲戚亲们可不也能嵌套使用扩展后的组件。

下面是一另俩个比较复杂的例子,一另俩个按钮点击后弹出inputval,输入后alert出输入的内容。

定义
  • CSS文件
.$__anchor {
    padding: 13px 35px 17px;
    box-shadow: inset 0 -4px 0 #2a6496;
    border: 0;
    color: #fff;
    transition: all .2s ease-in-out;
    background-color: #337ab7;
    border-color: #2e6da4;
    display: block;
    margin-bottom: 0;
    font-size: 14px;
    font-weight: 500;
    line-height: 1.42857143;
    text-align: center;
    white-space: nowrap;
    vertical-align: middle;
    touch-action: manipulation;
    cursor: pointer;
    user-select: none;
    border-radius: 4px;
    text-decoration: none;
    margin: 0 auto;
}

.$__anchor:hover,
.$__anchor:active
.$__anchor:focus {
    background-color: #2850090;
    border-color: #204d74;
}
  • 模版文件:
<div>
    <a href="javascript:void(0);" class="$__anchor" q-on="click: setMessage">
        <content></content>
    </a>
    <inputval q-ref="input"></inputval>
</div>
  • Javascript文件:
module.exports = {
    data: {},
    methods: {
        setMessage: function (e) {
            var self = this;
            this.$.input.$once('submit', function (value) {
                value && alert('输入了:' + value);
            });
            this.$.input.show();
        }
    }
};
效果
  • 在页面引用:
  • 效果:

DIY组件

DIY组件允许页面通过Markup的最好的方法引用NodeJS组件,却说 亲戚亲戚亲们可不也能使用该NodeJS组件分析亲戚亲戚亲们的代码来做许多神奇的事情。

累似 亲戚亲戚亲们提供的diy-preload组件提供的CGI预加载方案,整个过程这样 改变开发人员的编码体验,却说 简简单单标记一下哪个CGI还要预加载,则系统会自动预加载CGI。

使用
  • 在页面引入diy-preload组件
<diy-preload></diy-preload>
  • 在页面对应的数据层配置文件,这里亲戚亲戚亲们的规范是该文件名为db.*.js,的对应CGI设置成preload = true:
    var DB = require('db');

    DB.extend({
        ke: DB.httpMethod({
            url: 'http://ke.qq.com/cgi-bin/index_json',
            type: 'JSONP',
            preload: true
        })
    })

    module.exports = DB;
  • diy-preload组件会找到db.*.js,但会 分蒸发掉那此CGI还要预加载,在<diy-preload>标签对应的位置插入预加载脚本。整个过程开发人员感知只有,体验上还是调取一另俩个CGI,但会 实际上在页面文档打开后CGI请求立刻发出,而都不 等候Javascript加载前一天才发出。