baidu / san

A fast, portable, flexible JavaScript component framework
https://baidu.github.io/san/
MIT License
4.72k stars 549 forks source link

evalExpr 是否可以开放出来? 类似之前的 _onEl #106

Closed leeight closed 6 years ago

leeight commented 6 years ago

RT

errorrik commented 6 years ago

evalExpr不适合开放吧,依赖Data的,Data并没有开放。啥场景呢

leeight commented 6 years ago

<input value="{{value}}" /> 我需要获取{{value}}的值,确切的说,我希望这样子用

attached() {
        const child = this.slotChilds[0].childs[0];
        if (!isComponent(child)
            && /input|select|textarea/.test(child.tagName)) {
            const valueExpr = child.props.get('value');
            if (!valueExpr) {
                return;
            }
            child._onEl(getEventName(child.tagName), () => {
                this.dispatch('form-element-changed', {
                    name: name,
                    value: child.evalExpr(valueExpr.expr)
                });
            });
        }
        else if (isComponent(child)) {
            child.on('input', () => {
                this.dispatch('form-element-changed', {
                    name: name,
                    value: child.data.get('value')
                });
            });
        }
}
errorrik commented 6 years ago

好危险的代码。。。

child是一个内部的对象,你用_onEl来绑定事件,事件fire时期望拿到这个dom上的value。你既然实际上已经care了DOM,那为啥不直接用child.el.value呢,绕一圈没必要啊。

leeight commented 6 years ago

其实我想的是万一以后我获取的是其它属性,不是 value 呢

errorrik commented 6 years ago

无所谓吧,既然依赖dom就从dom上取呗

leeight commented 6 years ago

或者说比如要实现表单验证的话,在 san 里面推荐的做法是什么样的呢?

我现在是实现了两个 Component,一个是 Form,一个是 FormItem。

FormItem 里面主要是一个 <slot/> 和一些 validate error 之类的东西,差不多是这样子

const template = `<div class="{{mainClass}}">
    <div class="${cx('label')}" s-if="label">{{label}}</div>
    <div class="${cx('content')}">
        <slot/>
        <label class="${cx('invalid-label')}" s-if="error">{{error}}</label>
    </div>
</div>`;

然后我需要在 FormItemattached 回掉函数里面得到 slot 的内容,绑定一些事件(主要是输入相关的事件):

  1. input, textarea -> oninput
  2. select -> onchange
  3. 自定义的 Component -> oninput

然后获取数据之后,dispatch 一个消息,Form 会收到这个消息,做出一些反馈。

然后在实现的过程中,就有这样子两个问题:

  1. _onEl 这个加回来了
  2. evalExpr 这个之前有,现在没有了
  3. 获取 slotChilds 的方法:const child = this.slotChilds[0].childs[0] 是推荐的用法吗?还是以后也了能会发生变化
sw811 commented 6 years ago

slotChilds确实发生过变化。以前只有component上有slotChilds的,但是由于component可能包含在for里面,for是具有独立scope的,所以可能存在问题。

我觉得是两点:

  1. 要evalExpr其实是没用的,因为就算有了evalExpr,你还得要绑定关系的表达式信息,所以不如直接从DOM上取
  2. 你需要遍历FormItem,给里面的一些东西绑事件。核心问题是如何遍历(其实你不care这东西是不是slot里来的,虽然这个场景下,它一定从slot里来)。那如何遍历呢,看更新过程就知道了。https://github.com/ecomfe/san/blob/master/src/view/element-update-childs.js
  3. 其实2的开销挺大的,我还是更喜欢dispatch模式。但是你这里涉及到原生的input。不过,如果不是非要实时验证的话,我并不建议这么搞。如果要这么搞,最好也是attached的nextTick
errorrik commented 6 years ago

接下来的话题见 #112 ,这个就关了