iView table 的双向绑定

Posted sp42a

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iView table 的双向绑定相关的知识,希望对你有一定的参考价值。

某些需求需要包含大量编辑控件的 table 列表界面,如下所示。

默认下 table 包含 input 虽然有 v-model 但不是双向绑定的,不会同步到 list 数组的中的数据。需要自己通过事件同步修改。有两种方式实现,基于 render 渲染函数和 template slot 标签。

/**
 * 列配置内容较多,故单独设一个类
 */
export default 
    data() 
        return 
            columns1: [
                 title: '显示', width: 60, align: 'center', render: higherOrderFnCheckbox('isShow').bind(this) ,
                 title: '字段名', key: 'key', align: 'center', width: 200 ,
                
                    title: '表格标题', align: 'center', render: (h: Function, params: any) => 
                        return h('Input', 
                            props: 
                                class: "center",
                                type: 'text', placeholder: '表格标题,必填',
                                value: this.cfg.fields[params.index].title,
                            ,
                            on: 
                                'on-blur': (event: any) => 
                                    if (event.target.value)
                                        this.cfg.fields[params.index].title = event.target.value;
                                ,
                            ,
                        );
                    ,
                ,
                
                    title: '渲染器', width: 120, align: 'center', render: (h: Function, params: any) => 
                        return h('Select',
                            
                                props:  transfer: true, value: params.row.render || 'raw' ,
                                on: 
                                    'on-select': (event: any) => 
                                        if (event && event.value)
                                            this.cfg.fields[params.index].render = event.value;
                                    
                                
                            , [
                            h('Option',  props:  value: 'raw'  , '原文输出'),
                            h('Option',  props:  value: 'link'  , '链接'),
                            h('Option',  props:  value: 'link_http'  , '显示地址的链接'),
                            h('Option',  props:  value: 'thumb'  , '缩略图'),
                            h('Option',  props:  value: 'email'  , '电子邮件'),
                            h('Option',  props:  value: 'long_date'  , '长日期'),
                            h('Option',  props:  value: 'short_date'  , '短日期'),
                            h('Option',  props:  value: 'sex'  , '性别'),
                        ]);
                    
                ,
                
                    title: '对齐方式', width: 100, align: 'center', render: (h: Function, params: any) => 
                        return h('Select', 
                            props: 
                                transfer: true, value: params.row.align
                            ,
                            on: 
                                'on-select': (event: any) => 
                                    if (event && event.value)
                                        this.cfg.fields[params.index].align = event.value;
                                
                            
                        , [
                            h('Option',  props:  value: 'left'  , '居左'),
                            h('Option',  props:  value: 'center'  , '居中'),
                            h('Option',  props:  value: 'right'  , '居右'),
                        ]);
                    
                ,
                 title: '最小列宽', width: 80, align: 'center', render: higherOrderFnNumber('minWidth').bind(this) ,
                 title: '列宽', width: 80, align: 'center', render: higherOrderFnNumber('width').bind(this) ,
                 title: '最大列宽', width: 80, align: 'center', render: higherOrderFnNumber('maxWidth').bind(this) ,
                 title: '不换行', width: 60, align: 'center', render: higherOrderFnCheckbox('isOneLine').bind(this) ,
                 title: '可排序', width: 70, align: 'center', render: higherOrderFnCheckbox('sortable').bind(this) ,
                 title: '可搜索', width: 60, align: 'center', render: higherOrderFnCheckbox('canSearch').bind(this) ,
                 title: '日期搜索', width: 80, align: 'center', render: higherOrderFnCheckbox('canDateSearch').bind(this) ,
                
                    title: '操作', width: 60, align: 'center', render: (h: Function, params: any) => 
                        return h('a', 
                            attrs: 
                                href: '#'
                            ,
                            on: 
                                'click': (event: any) => 
                                    this.cfg.fields.splice(params.index, 1);
                                
                            
                        , '删除');
                    
                ,
            ],
        
    



function higherOrderFnCheckbox(field: string): Function 
    return function (h: Function, params: any) 

        return h('Checkbox', 
            props: 
                value: !!this.cfg.fields[params.index][field],
            ,
            on: 
                'on-change': (v: boolean) => this.cfg.fields[params.index][field] = v
            ,
        );
    


function higherOrderFnNumber(field: string): Function 
    return function (h: Function, params: any) 
        return h('Input', 
            class: "center",
            props: 
                type: 'number',
                value: this.cfg.fields[params.index][field],
            ,
            on: 
                'on-blur': (event: any) => 
                    if (event.target.value)
                        this.cfg.fields[params.index][field] = Number(event.target.value);
                ,
            ,
        );
    

注意 input 的事件是 on-blur。这种基于 vue 的 render 比较繁琐,推荐模板中给出标签的方式。另外说一句,界面开发还是推崇描述式的语言,即标签、xml、html 这类的。

<Table :data="cfg.fields" :columns="list.columns" max-height="500">
      <template slot-scope=" row, index " slot="isShow">
        <Checkbox v-model="row.isShow" @on-change="cfg.fields[index].isShow = $event" />
      </template>
      <template slot-scope=" row, index " slot="name">
        <Input type="text" v-model="row.name" placeholder="指定表单控件 name 属性" @on-blur="cfg.fields[index].name = $event.target.value" />
      </template>

      <template slot-scope=" row, index " slot="uiLabel">
        <Input type="text" v-model="row.uiLabel" placeholder="指定表单控件 label 名称" @on-blur="cfg.fields[index].uiLabel = $event.target.value" />
      </template>

      <template slot-scope=" row, index " slot="uiType">
        <Select v-model="row.uiType" :transfer="true" title="表单控件类型" @on-change="cfg.fields[index].uiType = $event">
          <OptionGroup label="常用表单组件">
            <Option :value="1">文本输入框 Input</Option>
            <Option :value="18">密码输入框 Password</Option>
            <Option :value="11">数字输入框 Number</Option>
            <Option :value="6">多行文本框 Textarea</Option>
            <Option :value="2">下拉列表 Select</Option>
            <Option :value="3">单选框 Radio</Option>
            <Option :value="4">多选框 Checkbox</Option>
            <Option :value="7">开关 Switch</Option>
            <Option :value="10"> 滑块 Slider</Option>
            <Option :value="5">日期选择器 DatePicker</Option>
            <Option :value="8">富文本编辑器 HTML Editor</Option>
            <Option :value="17">图片上传器 Img Uploader</Option>
            <Option :value="9">文件上传器 File Uploader</Option>
            <Option :value="18">附件上传器 Attment Uploader</Option>
          </OptionGroup>
          <OptionGroup label="业务组件">
            <Option :value="16">手机输入框</Option>
            <Option :value="12">电邮输入框</Option>
            <Option :value="15">性别选择</Option>
            <Option :value="13">身份证输入框</Option>
            <Option :value="14">省市区联动</Option>
          </OptionGroup>
        </Select>
      </template>

      <template slot-scope=" row, index " slot="uiLayout">
        <Select v-model="row.uiLayout" :transfer="true" @on-change="cfg.fields[index].uiLayout = $event">
          <Option :value="1">单列</Option>
          <Option :value="2">双列</Option>
          <Option :value="3">三列</Option>
        </Select>
      </template>

      <template slot-scope=" row, index " slot="dataType">
        <Select v-model="row.dataType" :transfer="true" @on-change="cfg.fields[index].dataType = $event">
          <Option value="string">文本</Option>
          <Option value="long_string">长文本</<

以上是关于iView table 的双向绑定的主要内容,如果未能解决你的问题,请参考以下文章

iView table 的双向绑定

关于vue的jsx语法

iview的table中嵌套input,select等

如何初始化片段中的绑定属性以使双向数据绑定工作

iview 踩坑v-model value区别

如何给iview的Select控件优雅的设置默认值的问题