风格指南 - styleguide

与类似文档一样,Regular 将风格指南设置为了多个优先级,分别是

  • 必要的: 程序运行可能会出问题的,强制遵循
  • 建议的: 不遵循程序可以运行,但会引起可维护性或性能的问题
  • 谨慎使用的: 未来可能会废弃的使用方式,谨慎使用

1. 必要的

1.1. 禁止在extend中定义缺省data参数 {}

config 生命周期中处理默认参数,而不是的 extend 时定义

Bad

Regular.extend({
    data: {
        list: [1,2,3]
    }
})

Good

Regular.extend({
    config( data ){
       data.list = data.list || [1,2,3] 
    }
})

Very Good

更好的做法是一个一致的缺省参数逻辑, 比如使用util.extend(会默认添加未定义的值)


const extend = Regular.util.extend;

Regular.extend({
    config( data ){
        extend(data, {
            list: [ 1, 2, 3 ]
        })
    }
})

未来 Regular 会提供统一的 default 书写方式 (会结合入参的检验机制共同设计)。

谨记 extend 是原型继承的语法糖,所以原型上的定义都是实例公用的

参考

1.2. 自定义destroy 必须调用 this.supr()

由于一些历史原因,Regular有一个肮脏的设计:即destory既被定义为生命周期钩子方法,又是一个对外的public API。

为了确保组件回收的统一逻辑,请调用 this.supr() 来引入Regular.prototype.destory 中的回收逻辑

Bad


const Component = Regular.extend({
    destory(){
       window.removeEventListener('scroll', this.onScroll)
    }    
})

Good

const Component = Regular.extend({
    destory(){
        this.supr()
        window.removeEventListener('scroll', this.onScroll)
    }    
})

2. 建议的

2.1. 大

2.2. list渲染尽量加入 by 条件

Good

<tr>
{#list items as item by item_index}
    <td>{item.content}</td>
{/list}
</tr>

Bad

{#list items as item}
    <td>{item.content}</td>
{/list}

但并非所有场景都可以使用 track by 进行控制,请参考 list语句章节

参考

2.3. 组件命名 - 大写驼峰

Regular 本身并无强限制组件的命名方式。

建议以 大写驼峰 的方式进行组件命名,并且 类名和 name 统一

Bad

const ConfirmModal = Regular.extend({
    name: 'confirm-modal'
})

Good


const ConfirmModal = Regular.extend({
    name: 'ConfirmModal',
    // 略
})

3. 谨慎使用的

3.1. 不要用if语句去控制属性的增删

if语句其实可以使用在节点属性上,但已经不建议大家这么做

Bad

<input {#if required} required {/if} />
<div {#if active} on-click={this.clickMe()} {/if} ></div>

Good

相关逻辑迁移到JS

// Regular会自动转义类似required、readonly 等 Boolean 类属性
<input required={required} />

Regular.extend({
    template: `
        <div on-click={this.clickMe()}></div>
    `,
    clickMe(){
        // 在js中控制
        if( !this.data.active ) return;
    }
})

理由

使用if语句去控制属性有几个风险

  • 存在自定义指令未实现 destroy 函数的可能,进而导致 Bug
  • 这种在模板里夹杂大量逻辑的写法会引起可维护性降低
  • 未来可能会移除这个Feature

3.2. 事件与双向绑定

Bad


const Input2 = Regular.extend({
    name: 'Input2',
    template: `<input on-change={this.changeValue($event)} />`
    changeValue(ev){
        this.data.value = ev.target.value;
        this.$emit('change'); // emit change event
    }
})

new Regular({
    template: `
        <Input2 value={value} on-change={this.handleValue()} />
    `,

    handleValue(){
        console.log(this.data.value) // 返回的仍然是上一个值
    }

}).$inject('body')

这里你会发现返回的仍然是上一个值

为什么?

因为触发事件的时候,并没有进入脏检查,外层的数据其实还未被同步。

Not So Bad

const Input2 = Regular.extend({
    name: 'Input2',
    template: `<input on-change={this.changeValue($event)} />`
    changeValue(ev){
        this.data.value = ev.target.value;
        setTimeout(()=>{
            this.$emit('change'); //emit 
        },0)
    }
})

当通过类似setTimeout将其延迟到脏检查之后的时机触发,此时的结果就如预期了。

Good

@TODO: new feature required

results matching ""

    No results matching ""