基於VueJS的render渲染函數結合自定義組件打造一款很是強大的IView 的Table

一、render渲染函數的介紹

字符串模板的代替方案,容許你發揮 JavaScript 最大的編程能力。該渲染函數接收一個 createElement 方法做爲第一個參數用來建立 VNode。css

若是組件是一個函數組件,渲染函數還會接收一個額外的 context 參數,爲沒有實例的函數組件提供上下文信息。html

二、如何使用render函數?

下面是vue官網的例子vue

var getChildrenTextContent = function (children) {
  return children.map(function (node) {
    return node.children
      ? getChildrenTextContent(node.children)
      : node.text
  }).join('')
}

Vue.component('anchored-heading', {
  render: function (createElement) {
    // 建立 kebabCase 風格的ID
    var headingId = getChildrenTextContent(this.$slots.default)
      .toLowerCase()
      .replace(/\W+/g, '-')
      .replace(/(^\-|\-$)/g, '')

    return createElement(
      'h' + this.level,
      [
        createElement('a', {
          attrs: {
            name: headingId,
            href: '#' + headingId
          }
        }, this.$slots.default)
      ]
    )
  },
  props: {
    level: {
      type: Number,
      required: true
    }
  }
})

三、iview table組件介紹

主要用於展現大量結構化數據。
支持排序、篩選、分頁、自定義操做、導出 csv 等複雜功能。node

四、iview table組件的使用

<template>
    <Table :columns="columns1" :data="data1"></Table>
</template>
<script>
    export default {
        data () {
            return {
                columns1: [
                    {
                        title: 'Name',
                        key: 'name'
                    },
                    {
                        title: 'Age',
                        key: 'age'
                    },
                    {
                        title: 'Address',
                        key: 'address'
                    }
                ],
                data1: [
                    {
                        name: 'John Brown',
                        age: 18,
                        address: 'New York No. 1 Lake Park',
                        date: '2016-10-03'
                    },
                    {
                        name: 'Jim Green',
                        age: 24,
                        address: 'London No. 1 Lake Park',
                        date: '2016-10-01'
                    },
                    {
                        name: 'Joe Black',
                        age: 30,
                        address: 'Sydney No. 1 Lake Park',
                        date: '2016-10-02'
                    },
                    {
                        name: 'Jon Snow',
                        age: 26,
                        address: 'Ottawa No. 2 Lake Park',
                        date: '2016-10-04'
                    }
                ]
            }
        }
    }
</script>

渲染成以下表格:
clipboard.pngexpress

五、iview table render函數和renderHeader介紹

render:編程

自定義渲染列,使用 Vue 的 Render 函數。傳入兩個參數,第一個是 h,第二個爲對象,包含 row、column 和 index,分別指當前行數據,當前列數據,當前行索引,詳見示例。 學習 Render 函數的內容api

renderHeader:數組

自定義列頭顯示內容,使用 Vue 的 Render 函數。傳入兩個參數,第一個是 h,第二個爲對象,包含 column 和 index,分別爲當前列數據和當前列索引。iview

六、iview table render函數的使用

<template>
    <Table border :columns="columns7" :data="data6"></Table>
</template>
<script>
    export default {
        data () {
            return {
                columns7: [
                    {
                        title: 'Name',
                        key: 'name',
                        render: (h, params) => {
                            return h('div', [
                                h('Icon', {
                                    props: {
                                        type: 'person'
                                    }
                                }),
                                h('strong', params.row.name)
                            ]);
                        }
                    },
                    {
                        title: 'Age',
                        key: 'age'
                    },
                    {
                        title: 'Address',
                        key: 'address'
                    },
                    {
                        title: 'Action',
                        key: 'action',
                        width: 150,
                        align: 'center',
                        render: (h, params) => {
                            return h('div', [
                                h('Button', {
                                    props: {
                                        type: 'primary',
                                        size: 'small'
                                    },
                                    style: {
                                        marginRight: '5px'
                                    },
                                    on: {
                                        click: () => {
                                            this.show(params.index)
                                        }
                                    }
                                }, 'View'),
                                h('Button', {
                                    props: {
                                        type: 'error',
                                        size: 'small'
                                    },
                                    on: {
                                        click: () => {
                                            this.remove(params.index)
                                        }
                                    }
                                }, 'Delete')
                            ]);
                        }
                    }
                ],
                data6: [
                    {
                        name: 'John Brown',
                        age: 18,
                        address: 'New York No. 1 Lake Park'
                    },
                    {
                        name: 'Jim Green',
                        age: 24,
                        address: 'London No. 1 Lake Park'
                    },
                    {
                        name: 'Joe Black',
                        age: 30,
                        address: 'Sydney No. 1 Lake Park'
                    },
                    {
                        name: 'Jon Snow',
                        age: 26,
                        address: 'Ottawa No. 2 Lake Park'
                    }
                ]
            }
        },
        methods: {
            show (index) {
                this.$Modal.info({
                    title: 'User Info',
                    content: `Name:${this.data6[index].name}<br>Age:${this.data6[index].age}<br>Address:${this.data6[index].address}`
                })
            },
            remove (index) {
                this.data6.splice(index, 1);
            }
        }
    }
</script>

渲染成以下tabledom

clipboard.png

七、iview render和renderHeader結合自定義組件,渲染table表格

QiDropdown.vue組件代碼以下:

<style lang="postcss" scoped>
.dd{
    & .ivu-select-dropdown{
        max-height: 100% !important;
    }
    & .ivu-select-dropdown{
        max-height: 100% !important;
    }
    & >.ddm{
        text-align: left;
        font-weight:normal;
        & .active{
            color:#008cee
        }
    }    
}
</style>
<template>
<div class="dd">
    <Dropdown :placement="placement" @on-click="ddClick" transfer >
        <span v-if="content.length > 0" style="cursor:pointer">
            {{content}}            
            <Icon type="arrow-down-b" v-if="showArrow"/>
        </span>
        <Icon type="plus" v-else style="cursor:pointer"></Icon>
        <DropdownMenu slot="list" class="ddm">
            <DropdownItem v-for="(item, index) in data" :key="index" :name="item.value" 
                :style="{color:localChoosedItem == item.value ? activeColor:defaultColor}">{{item.name}}</DropdownItem>
            <slot name="diy"></slot>
        </DropdownMenu>
    </Dropdown>
</div>
</template>
<script>
export default {
    data(){
        return{
            activeColor:'#008cee',
            defaultColor:'#495060',
            localChoosedItem:''
        }
    },
    props:{
        placement:{
            type:String,
            default:'bottom-start'
        },
        showArrow:{
            type:Boolean,
            default:false
        },
        content:{
            type:String,
            default:''
        },
        data:{
            type:Array,
            default:()=>{
                return [];
            }
        },
        choosedItem:{
            type:String,
            default:''
        }
    },
    watch:{
        choosedItem:{
            immediate:true,
            handler(newv,oldv){
                this.localChoosedItem = newv;
            }
        }
    },
    created(){

    },
    methods:{
        ddClick(name){
            this.$emit('on-choosed',name);
            this.localChoosedItem = name;
        }
    }
}
</script>

八、父組件引入QiDropdown組件並應用到table 的render和renderHeader函數中

import QiDropdown from '@/components/QiDropdown'

export default {
    name: 'email-list',
    components:{
        QiDropdown
    },
...
columns: [
                {
                    title: '標註',
                    key: 'callout',
                    align:'center',
                    renderHeader:(h,params)=>{
                        return h(QiDropdown,{
                            props:{                                
                                placement:'bottom-start',
                                showArrow:true,
                                content:'標註',
                                data:this.flags
                            },
                            on:{
                                'on-choosed':(value)=>{        
                                    this.queryForm.callout = value;                            
                                    this.getResumeFromEmailBy();
                                }
                            }
                        });
                    },
                    render:(h,params)=>{
                        return h(QiDropdown,{
                                props:{
                                    content:params.row.callout||'',
                                    data:this.flags.slice(1)
                                },
                                on:{
                                    'on-choosed':(value)=>{
                                        this.choosedFlag(params.row.id,value);    
                                    }
                                }
                            },[ 
                                h('DropdownItem',
                                {
                                    slot: 'diy',
                                    style:{
                                        color:'#2d8cf0'
                                    },
                                    props:{
                                        name:'add',
                                        divided:true
                                    }
                                }, 
                                '添加並標註'),
                                h('DropdownItem',
                                {
                                    slot: 'diy',
                                    style:{
                                        color:'#2d8cf0'
                                    },
                                    props:{
                                        name:'clear'
                                    }
                                }, 
                                '清除該標註')
                            ]);
                        
                    }
                }, 
                ...

渲染成以下所示:
clipboard.png

clipboard.png

九、總結:

1)有了render函數加上自定義組件,那麼你不再怕iview table組件功能的單調了,一開始我也覺得iview table功能太少,如今有了它,你能夠實現你任何想實現的表格了,很是簡單!

2)iview Dropdown組件上必定要加 transfer 屬性,不然它不能正常顯示出來

3)render函數能夠使用slot,如個人QiDrowdown組件裏面有一個slot name=diy,那它在render函數裏面就是要寫到QiDrowdownr 數組中,如:

h(QiDrowdown,
{//這裏寫QiDrowdown屬性props、事件on、樣式style等等},
[//這裏能夠寫slot組件,也能夠是其它組件,若是是slot你要這樣寫:
    h('DropdownItem',
                                {
                                    slot: 'diy',//記住這裏要寫上QiDrowdown組件slot的name
                                    style:{
                                        color:'#2d8cf0'
                                    },
                                    props:{
                                        name:'add',
                                        divided:true
                                    }
                                }, 
                                '添加並標註'),
                                
這樣渲染就等因而這樣寫:
<QiDrowdown>
    <DropdownItem slot="diy" style="color:#2d8cf0" name="add" divided></DropdownItem>
</QiDrowdown>
])
h('組件名', {組件屬性(包括vue相關的props)}, [子組件或者子節點或者文本])
{
  // 和`v-bind:class`同樣的 API
  'class': {
    foo: true,
    bar: false
  },
  // 和`v-bind:style`同樣的 API
  style: {
    color: 'red',
    fontSize: '14px'
  },
  // 正常的 HTML 特性
  attrs: {
    id: 'foo'
  },
  // 組件 props
  props: {
    myProp: 'bar'
  },
  // DOM 屬性
  domProps: {
    innerHTML: 'baz'
  },
  // 事件監聽器基於 `on`
  // 因此再也不支持如 `v-on:keyup.enter` 修飾器
  // 須要手動匹配 keyCode。
  on: {
    click: this.clickHandler
  },
  // 僅對於組件,用於監聽原生事件,而不是組件內部使用 `vm.$emit` 觸發的事件。
  nativeOn: {
    click: this.nativeClickHandler
  },
  // 自定義指令。注意事項:不能對綁定的舊值設值
  // Vue 會爲您持續追蹤
  directives: [
    {
      name: 'my-custom-directive',
      value: '2',
      expression: '1 + 1',
      arg: 'foo',
      modifiers: {
        bar: true
      }
    }
  ],
  // Scoped slots in the form of
  // { name: props => VNode | Array<VNode> }
  scopedSlots: {
    default: props => createElement('span', props.text)
  },
  // 若是組件是其餘組件的子組件,需爲插槽指定名稱
  slot: 'name-of-slot',
  // 其餘特殊頂層屬性
  key: 'myKey',
  ref: 'myRef'
}

注:若是你使用圖片,src應該以下配置

render: (h, params)=>{
    return h('img', {
        style:{
            width: '100px'
        },
        domProps:{
            src: params.row.material_img,
        }
    })
}

十、引用

1)vue Render中slots的使用
2)渲染函數 & JSX
3)理解Vue中的Render渲染函數

相關文章
相關標籤/搜索