Use o pacote de funções de renderização no arquivo vue para implementar componentes dinâmicos

Recentemente, encontrei uma página de tabela em um projeto vue. Dados e modelos são fortemente acoplados em uma página, o que parece complicado e inconveniente de manter. A página também é altamente repetitiva, então tentei renderizar elementos dom em um loop em vue , longe da configuração da parte comum, infelizmente v-for não suporta inserção dinâmica de elementos dom, então como usar vue para obter renderização dinâmica de nós de elementos dom dinâmicos.

Pense na implementação do react, pense na função render do vue, o render in vue afirma ser capaz de escrever páginas como react e comece a implementar quando tiver uma ideia. A função render é relativamente fácil de entender, mas como implementar slots, cliques de evento e escopos em render  e como usar bibliotecas de código aberto em render ?

Depois de investigar o dom virtual após a compilação do vue, tudo isso é alcançável.

Slot e escopo: podem ser escritos diretamente na forma de (escopo) => {}

Clique no evento: nativeOnClick

Biblioteca de código aberto: o evento se torna 'on-' + ' '    Por exemplo:   on-selection-change

A seguir está uma instância de DynamicTablePage:

<script>
export default {
  name: 'DynamicTablePage',
  props: {
    msg: String,
    tableParams: Array,
    tableData: Array,
    selections: Array,
    layout: String,
    pageSizes: Array,
    handleSizeChange: Function,
    handleCurrentChange: Function,
    total: Number,
    currentPage: Number,
    hasPagination: Boolean,
    handleSelectionChange: {
      type: Function,
      default: () => { }
    },
    paginationFixed: Boolean
  },
  data () {
    return {
    }
  },
  mounted () {
    console.log(this.hasPagination)
  },
  methods: {

  },
  render (h) {
    return <div class="jsx-component">
      <el-table
        data={this.tableData}
        style={
   
   { width: '100%' }}
        class="test"
        on-selection-change={this.handleSelectionChange}
      >
        {
          this.tableParams.map((item, index) => {
            return <el-table-column
              prop={item.param}
              label={item.title}
              width={item.width}
              key={index}
              type={item.type}
              allow-expand={item.allowExpand}
              filters={item.filters}
              align={item.align ? item.align : 'left'}
              selections={this.multipleSelection}
              filter-method={item.filterHandler}
            >
              {
                item.template ? scope => item.template(scope, this, h) : ''
              }
            </el-table-column>
          })
        }
      </el-table>
      {
        this.hasPagination ? <el-pagination
          class={this.paginationFixed ? "fixed" : ''}
          on-size-change={this.handleSizeChange}
          on-current-change={this.handleCurrentChange}
          current-page={this.currentPage}
          page-sizes={this.pageSizes}
          layout={this.layout}
          total={this.total}>
        </el-pagination> : null
      }
    </div >
  }
}
</script>

<style scoped>
.jsx-component {
  background: red;
}
.fixed {
  position: fixed;
  bottom: 0;
}
</style>

Arquivo de configuração correspondente:

let tableParams = [
    {
        title: '',
        param: "",
        width: '30px',
        type: 'selection'
    },
    {
        width: '30px',
        type: 'expand',
        test: {
            name: 1
        },
        allowExpand (_row, index) {
            return index !== 2;
        },
        // eslint-disable-next-line no-unused-vars
        template: (_scope, _self, h) => {
            return <div>测试</div>
        }
    },
    {
        title: '日期',
        param: "date",
        filters: [
            { text: '2018/12/01', value: '2018/12/01' },
            { text: '2018/12/02', value: '2018/12/02' },
            { text: '2018/12/03', value: '2018/12/03' },
            { text: '2018/12/04', value: '2018/12/04' },
            { text: '2018/12/05', value: '2018/12/05' },
            { text: '2018/12/10', value: '2018/12/10' }
        ],
        filterHandler (value, row, column) {
            console.log(value, row, column)
            const property = column['property'];
            return row[property] === value;
        }
    },
    {
        title: '字段2',
        param: "date2",
        template: (scope) => {
            return scope.row.date2.replace(/[1-9]+/g, '000')
        }
    },
    {
        title: '字段3',
        param: "date3",
        // eslint-disable-next-line no-unused-vars
        template: (scope, self, h) => {
            return <div>
                <el-button
                    icon="h-icon-edit"
                    size="mini"
                    nativeOnClick={() => {
                        self.$router.push({ name: 'PageTwo' })
                    }}
                />
            </div>
        }
    }
]

export const tableData = () => {
    return [
        {
            date: '2018/12/01',
            date2: 'dfkjdfjk',
            date3: '测试',
            id: 0
        },
        {
            date: '1221121221',
            date2: 'dfkjdfjk',
            date3: '测试',
            id: 1
        },
        {
            date: '1221121221',
            date2: '1373698562',
            date3: '测试',
            id: 2
        },
        {
            date: '1221121221',
            date2: 'dfkjdfjk',
            date3: '测试',
            id: 3
        }
    ]
}
export default tableParams

Use o componente DynamicTablePage

<template>
  <div class="example">
    <h4>页面一</h4>
    <DynamicTablePage
      :tableParams="tableParams"
      :tableData="tableData"
      :total="total"
      layout="total, sizes, prev, pager, next, jumper"
      :currentPage="currentPage"
      :handleSizeChange="handleSizeChange"
      :handleCurrentChange="handleCurrentChange"
      :pageSizes="[100, 200, 300, 400]"
      hasPagination
      :handleSelectionChange="handleSelectionChange"
      paginationFixed
    ></DynamicTablePage>
  </div>
</template>
<script>
import DynamicTablePage from '../../components/DynamicTablePage'
import tableParams, { tableData } from './pageOne.config'
export default {
  name: 'PageOne',
  components: {
    DynamicTablePage
  },
  data () {
    return {
      tableData: tableData(),
      total: 1000,
      selections: [],
      tableParams: tableParams,
      currentPage: 1
    }
  },
  methods: {
    handleSelectionChange (val) {
      console.log(val)
      this.multipleSelection = val;
    },
    handleSizeChange () {

    },
    handleCurrentChange (val) {
      console.log(val)
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.example {
  width: 800px;
  margin: 0 auto;
  height: auto;
}
</style>

 

Este componente é uma abstração da tabela.Após o encapsulamento, cada coluna e dados da tabela podem ser separados em configuração, a estrutura do código é clara e é propícia para manutenção posterior. Se houver as mesmas páginas, as páginas podem ser geradas rapidamente por meio da configuração.

Para outras funções, como páginas de formulário, páginas de exibição etc., um encapsulamento semelhante pode ser feito para melhorar a eficiência, o desempenho e a manutenção.

Para o empacotamento de componentes mais complexos, também pode ser combinado com extração vuex e plug-in.

 

 

 

 

Acho que você gosta

Origin blog.csdn.net/qdmoment/article/details/106200145
Recomendado
Clasificación