Инкапсулировать форму element-ui, я делаю это

Element Vue.js

Работать сверхурочно каждый день до полуночи, оглядываться и никто не уходит; Выйдите вовремя в 8 часов завтра вечером, кто не успеет, тот собака.

использовалelement-uiУ одноклассников таблицы должен быть такой опыт.Простую таблицу сделать относительно легко, но если таблица включает в себя кнопки вверху, пагинацию и даже редактирование строк, нагрузка на разработку возрастет в геометрической прогрессии., особенно при разработке управления система, развитие форм одну за другой является пустой тратой времени и не улучшает человека. Сегодня редактор принес форму, которую я инкапсулировал, чтобы вы могли использоватьJSONФормы могут быть легко сгенерированы.

В этой статье основное внимание уделяется идее инкапсуляции и описанию основного кода. Полный код можно найти на страницеGitHub.com/snow Zijun/V…, если вы найдете это полезным, пожалуйста, дайте мнеstar, каждый из вашихstarВсе они поддерживают Xiaobian, текущая функция относительно проста, этот склад будет продолжать обновляться. В то же время вы также можете найти официальную учетную запись [Some Plays on the Front End] в WeChat, чтобы связаться с редактором.

Требования к форме

Общая система управления будет иметь следующие требования к форме

  1. Можно разбить на страницы (нужна полоса разбиения на страницы)
  2. Возможен множественный выбор (таблица с флажками)
  3. Некоторые кнопки действий необходимо добавить вверху (добавить, удалить и т. д.)
  4. В конце каждой строки таблицы есть кнопки действий.
  5. Строки таблицы можно редактировать

Ниже пример таблицы

Если мы непосредственно используемelement-uiЕсли компоненты предусмотрены, то для разработки такой формы требуется следующее содержание

  1. Необходимо использовать функцию слота таблицы для разработки кнопок для каждой строки.
  2. Необходимо настроить стиль макета верхней кнопки, таблицы, панели пагинации через стиль
  3. Необходимо прослушивать события пейджинга, а затем обновлять данные таблицы.
  4. Если верхней кнопке или кнопке действия необходимо получить данные таблицы, ей необходимо вызвать API, предоставленный таблицей.
  5. Для необходимости редактирования линии также необходимо сделать содержание линии редактирования в слоте, и в то же время управлять выключателем редактирования линии

Мало того, что разработка формы более хлопотна, но также рассматривается командная работа.Если существуют различия в том, как каждый человек реализует форму, стоимость обслуживания в более поздний период также может стать очень высокой. тогда что нам делать?

Установка проекта

Установить плагин

В использованииelement-ui, вы можете установить его с помощью следующей команды

npm install vue-elementui-table -S

использовать в проекте

существуетmain.jsДобавьте следующий код в

import ZjTable from 'vue-elementui-table'

Vue.use(ZjTable)

Затем вы можете использовать его следующим образом

конфигурация стола

Для того, чтобы удовлетворить потребности быстрой разработки команды, редактор инкапсулирует в себе требования, предложенные выше, а затем при его использовании разработчику нужно лишь настроить некоторыеJSONРазвитие вышеуказанных функций может быть завершено.

Базовая конфигурация

Базовая таблица содержит данные и информацию о столбцах, так как же настроить ее с помощью инкапсулированной таблицы?

<template>
  <zj-table
    :columns="columns"
    :data="data"
    :pagination="false"
  />
</template>
<script>
export default {
  data() {
    return {
      // 表格的列信息, 数组每一项代表一个字段,可以使用element 列属性的所有属性,以下仅为示例
      columns: Object.freeze([
        {
          // 表头显示的文字
          label: '姓名',
          // 对应数据里面的字段
          prop: 'name'
        },
        {
          label: '性别',
          prop: 'sex',
          // 格式化表格,与element-ui 的表格属性相同
          formatter(row, column, cellValue) {
            return cellValue === 1 ? '男' : '女'
          }
        },
        {
          label: '年龄',
          prop: 'age'
        }
      ]),
      data: [
        {
          name: '子君',
          sex: 1,
          age: 18
        }
      ]
    }
  }
}
</script>

С помощью приведенной выше конфигурации можно завершить разработку базовой таблицы Полный код см.GitHub.com/snow Zijun/V…, Результаты, как показано ниже

В таблице будет отображаться флажок по умолчанию, или его можно настроить с помощьюselectableсвойство закрыть

Добавить страницу

После того, как простая форма инкапсулирована или не инкапсулирована, нет большой разницы в рабочей нагрузке разработки.Мы продолжаем добавлять пагинацию в форму.

<template>
	<!--
    current-page.sync 表示页码, 添加上 .sync 在页码发生变化时自动同步页码
    page-size.sync 每页条数
    total  总条数
    height="auto" 配置height:auto, 表格高度会根据内容自动调整,如果不指定,表格将保持充满父容器,同时表头会固定,不跟随滚动条滚动
    @page-change 无论pageSize currentPage 哪一个变化,都会触发这个事件
  -->
  <zj-table
    v-loading="loading"
    :columns="columns"
    :data="data"
    :current-page.sync="currentPage"
    :page-size.sync="pageSize"
    :total="total"
    height="auto"
    @page-change="$_handlePageChange"
  />
</template>
<script>
export default {
  data() {
    return {
      columns: Object.freeze([
        // 列字段与上例一样,此处省略
      ]),
      data: [],
      // 当前页码
      currentPage: 1,
      // 每页条数
      pageSize: 10,
      // 总条数
      total: 0,
      // 是否显示loading
      loading: false
    }
  },
  created() {
    this.loadData()
  },
  methods: {
    // 加载表格数据
    loadData() {
      this.loading = true
      setTimeout(() => {
        // 假设总条数是40条
        this.total = 40
        const { currentPage, pageSize } = this
        // 模拟数据请求获取数据
        this.data = new Array(pageSize).fill({}).map((item, index) => {
          return {
            name: `子君${currentPage + (index + 1) * 10}`,
            sex: Math.random() > 0.5 ? 1 : 0,
            age: Math.floor(Math.random() * 100)
          }
        })
        this.loading = false
      }, 1000)
    },
    $_handlePageChange() {
      // 因为上面设置属性指定了.sync,所以这两个属性会自动变化
      console.log(this.pageSize, this.currentPage)
      // 分页发生变化,重新请求数据
      this.loadData()
    }
  }
}
</script>

Пожалуйста, обратитесь к полному кодуGitHub.com/snow Zijun/V…

Благодаря инкапсуляции таблица будет иметь свою функцию подкачки.Благодаря вышеприведенному коду эффект следующий, это проще? Далее продолжаем добавлять кнопки на форму

Добавить верхнюю кнопку

На столе могут быть кнопки добавления, удаления и т. д. Что делать?Далее продолжим добавлять кнопки через настройку.

<template>
  <zj-table
    :buttons="buttons"
  />
</template>
<script>
export default {
  data() {
    return {
      buttons: Object.freeze([
        {
          // id 必须有而且是在当前按钮数组里面是唯一的
          id: 'add',
          text: '新增',
          type: 'primary',
          icon: 'el-icon-circle-plus',
          click: this.$_handleAdd
        },
        {
          id: 'delete',
          text: '删除',
          // rows 是表格选中的行,如果没有选中行,则禁用删除按钮, disabled可以是一个boolean值或者函数
          disabled: rows => !rows.length,
          click: this.$_handleRemove
        },
        {
          id: 'auth',
          text: '这个按钮根据权限显示',
          // 可以通过返回 true/false来控制按钮是否显示
          before: (/** rows */) => {
            return true
          }
        },
        // 可以配置下拉按钮哦
        {
          id: 'dropdown',
          text: '下拉按钮',
          children: [
            {
              id: 'moveUp',
              text: '上移',
              icon: 'el-icon-arrow-up',
              click: () => {
                console.log('上移')
              }
            },
            {
              id: 'moveDown',
              text: '下移',
              icon: 'el-icon-arrow-down',
              disabled: rows => !rows.length,
              click: () => {
                console.log('下移')
              }
            }
          ]
        }
      ])
    }
  },
  created() {},
  methods: {
    // 新增
    $_handleAdd() {
      this.$alert('点击了新增按钮')
    },
    // 顶部按钮会自动将表格所选的行传出来
    $_handleRemove(rows) {
      const ids = rows.map(({ id }) => id)
      this.$alert(`要删除的行id为${ids.join(',')}`)
    },
    // 关注作者公众号
    $_handleFollowAuthor() {}
  }
}
</script>

Обычные кнопки могут быть добавлены вверху таблицы, также могут быть добавлены раскрывающиеся кнопки иbeforeнастроить отображение кнопки,disabledЧтобы настроить, отключена ли кнопка, см. полный код выше.GitHub.com/snow Zijun/V…

С помощью приведенного выше кода можно настроить следующую таблицу, не правда ли, это очень просто?

Кнопки могут быть вверху таблицы, а также можно добавить кнопки в конце ряда, давайте посмотрим

кнопка действия строки

Как правило, мы помещаем некоторые однострочные кнопки управления в конец строки, такие как кнопки редактирования, загрузки и другие, так как же настроить кнопки в конце строки?

<template>
  <zj-table
    :columns="columns"
  />
</template>
<script>
export default {
  data() {
    return {
      columns: Object.freeze([
        {
          // 可以指定列的宽度,与element-ui原生用法一致
          width: 220,
          label: '姓名',
          prop: 'name'
        },
        // 行编辑按钮,在表格末尾出现,自动锁定右侧
        {
          width: 180,
          label: '操作',
          // 通过 actions 指定行尾按钮
          actions: [
            {
              id: 'follow',
              text: '关注作者',
              click: this.$_handleFollowAuthor
            },
            {
              id: 'edit',
              text: '编辑',
              // 可以通过before控制按钮是否显示,比如下面年龄四十岁的才会显示编辑按钮
              before(row) {
                return row.age < 40
              },
              click: this.$_handleEdit
            },
            {
              id: 'delete',
              text: '删除',
              icon: 'el-icon-delete',
              disabled(row) {
                return row.sex === 0
              },
              // 为了拿到this,这里需要用箭头函数
              click: () => {
                this.$alert('女生被禁止删除了')
              }
            }
          ]
        }
      ])
    }
  },
  methods: {
    // 关注作者公众号
    $_handleFollowAuthor() {
   console.log('微信搜索【前端有的玩】,这是对小编最大的支持')
    },
    /**
     * row 这一行的数据
     */
    $_handleEdit(row, column) {
      this.$alert(`点击了姓名为【${row.name}】的行上的按钮`)
    }
  }
}
</script>

Кнопка операции со строкой будет зафиксирована в крайнем правом углу таблицы и не будет прокручиваться с помощью полосы прокрутки. См. полный код выше,GitHub.com/snow Zijun/V…

Приведенный выше код может достичь следующих эффектов

Наконец, давайте взглянем на редактирование строки

редактирование строк

Такие, как приведенный выше пример, я хочу редактировать щелчок кнопки, когда конец строки вы можете напрямую редактировать строку над именем пользователя и пола пользователя, как его настроить?

<template>
  <zj-table
    ref="table"
    :columns="columns"
    :data="data"
  />
</template>
<script>
export default {
  data() {
    return {
      columns: Object.freeze([
        {
          label: '姓名',
          prop: 'name',
          editable: true,
          field: {
            componentType: 'input',
            rules: [
              {
                required: true,
                message: '请输入姓名'
              }
            ]
          }
        },
        {
          label: '性别',
          prop: 'sex',
          // 格式化表格,与element-ui 的表格属性相同
          formatter(row, column, cellValue) {
            return cellValue === '1' ? '男' : '女'
          },
          editable: true,
          field: {
            componentType: 'select',
            options: [
              {
                label: '男',
                value: '1'
              },
              {
                label: '女',
                value: '0'
              }
            ]
          }
        },
        {
          label: '年龄',
          prop: 'age',
          editable: true,
          field: {
            componentType: 'number'
          }
        },
        {
          label: '操作',
          actions: [
            {
              id: 'edit',
              text: '编辑',
              // 如果当前行启用了编辑,则不显示编辑按钮
              before: row => {
                return !this.editIds.includes(row.id)
              },
              click: this.$_handleEdit
            },
            {
              id: 'save',
              text: '保存',
              // 如果当前行启用了编辑,则显示保存按钮
              before: row => {
                return this.editIds.includes(row.id)
              },
              click: this.$_handleSave
            }
          ]
        }
      ]),
      data: [
        {
          // 行编辑必须指定rowKey字段,默认是id,如果修改为其他字段,需要给表格指定row-key="字段名"
          id: '0',
          name: '子君',
          sex: '1',
          age: 18
        },
        {
          // 行编辑必须指定rowKey字段,默认是id,如果修改为其他字段,需要给表格指定row-key="字段名"
          id: '1',
          name: '子君1',
          sex: '0',
          age: 18
        }
      ],
      editIds: []
    }
  },
  methods: {
    $_handleEdit(row) {
      // 通过调用 startEditRow 可以开启行编辑
      this.$refs.table.startEditRow(row.id)
      // 记录开启了行编辑的id
      this.editIds.push(row.id)
    },
    $_handleSave(row) {
      // 点击保存的时候,通过endEditRow 结束行编辑
      this.$refs.table.endEditRow(row.id, (valid, result, oldRow) => {
        // 如果有表单验证,则valid会返回是否验证成功
        if (valid) {
          console.log('修改之后的数据', result)
          console.log('原始数据', oldRow)
          const index = this.editIds.findIndex(item => item === row.id)
          this.editIds.splice(index, 1)
        } else {
          // 如果校验失败,则返回校验的第一个输入框的异常信息
          console.log(result)
          this.$message.error(result.message)
        }
      })
    }
  }
}
</script>

Было бы неплохо иметь возможность редактирования строк без использования слотов. См. полный код вышеGitHub.com/snow Zijun/V…

Результаты, как показано ниже:

Другие функции

В дополнение к вышеперечисленным функциям форма также может быть настроена со многими другими функциями, такими как

  1. Вы можете указать поле как столбец ссылки, вам нужно настроить столбецlinkАтрибуты
  2. Верхние кнопки, кнопки действий строки, поля строки и т. д. можно настроить с помощью слотов.
  3. Дополнительный контент можно настроить с помощью слотов в правой части области кнопок.
  4. другое и т.д.

Инструкции по разработке формы

Из приведенного выше примера кода мы уже знаем, что может сделать инкапсулированная форма, давайте посмотрим, как эта форма реализована. Посмотреть полный кодGitHub.com/snow Zijun/V…

макет таблицы

Вся форма черезJSXинкапсулировать, потому чтоJSXБолее гибкий в использовании. Для таблицы, которую мы инкапсулировали, мы можем разделить ее на три части по вертикали, а именно верхнюю область кнопки, среднюю область таблицы и нижнюю область страницы.Как реализовать расположение трех областей?Основной код выглядит следующим образом

render(h) {
    // 按钮区域
    const toolbar = this.$_renderToolbar(h)
    // 表格区域
    const table = this.$_renderTable(h)
    // 分页区域
    const page = this.$_renderPage(h)

    return (
      <div class="zj-table" style={{ height: this.tableContainerHeight }}>
        {toolbar}
        {table}
        {page}
      </div>
    )
  }

через триrenderФункция визуализирует соответствующие регионы по отдельности, а затем объединяет три региона вместе.

Столбцы таблицы рендеринга

Благодаря предыдущему объяснению мы можем разделить столбцы таблицы на следующие типы.

  1. обычная колонка
  2. столбец редактирования строки
  3. Столбец кнопки действия
  4. слот столбец
  5. Колонка ссылок (документы будут улучшены позже)
  6. Вложенные столбцы (документация будет улучшена позже)
    $_renderColumns(h, columns) {
      // 整体是否排序
      let sortable = this.sortable ? 'custom' : false
      return columns
        .filter(column => {
          const { hidden } = column
          if (hidden !== undefined) {
            if (typeof hidden === 'function') {
              return hidden({
                columns,
                column
              })
            }
            return hidden
          }
          return true
        })
        .map(column => {
          const {
            useSlot = false,
            // 如果存在操作按钮,则actions为非空数组
            actions = [],
            // 是否可编辑列, 对于可编辑列需要动态启用编辑
            editable = false,
            // 是否有嵌套列
            nests,
            // 是否可点击
            link = false
          } = column
          let newSortable = sortable
          if (column.sortable !== undefined) {
            newSortable = column.sortable ? 'custom' : false
          }
          column = {
            ...column,
            sortable: newSortable
          }
          if (nests && nests.length) {
            // 使用嵌套列
            return this.$_renderNestColumn(h, column)
          } else if (editable) {
            // 使用编辑列
            return this.$_renderEditColumn(h, column)
          } else if (useSlot) {
            // 使用插槽列
            return this.$_renderSlotColumn(h, column)
          } else if (actions && actions.length > 0) {
            // 使用操作列
            column.sortable = false
            return this.$_renderActionColumn(h, column)
          } else if (link) {
            // 使用链接列
            return this.$_renderLinkColumn(h, column)
          } else {
            // 使用默认列
            return this.$_renderDefaultColumn(h, column)
          }
        })
    },

столбец редактирования строки

Поддержка редактирования текущей строки таблицыinput,select,datepicker,TimeSelect,InputNumberи другие компоненты, конкретный код рендеринга выглядит следующим образом

// 编辑单元格
    $_renderEditCell(h, field) {
      const components = {
        input: Input,
        select: ZjSelect,
        date: DatePicker,
        time: TimeSelect,
        number: InputNumber
      }
      const componentType = field.componentType
      const component = components[componentType]
      if (component) {
        return this.$_renderField(h, field, component)
      } else if (componentType === 'custom') {
        // 如果自定义,可以通过component指定组件
        return this.$_renderField(h, field, field.component)
      }
      return this.$_renderField(h, field, Input)
    },
    $_renderField(h, field, Component) {
      // 编辑行的id字段
      const { rowId, events = {}, nativeEvents = {} } = field

      const getEvents = events => {
        const newEvents = {}
        Object.keys(events).forEach(key => {
          const event = events[key]
          newEvents[key] = (...rest) => {
            const args = [
              ...rest,
              {
                rowId,
                row: this.editRowsData[rowId],
                value: this.editRowsData[rowId][field.prop]
              }
            ]
            return event(...args)
          }
        })
        return newEvents
      }
      // 事件改写
      const newEvents = getEvents(events)
      const newNativeEvents = getEvents(nativeEvents)
      return (
        <Component
          size="small"
          on={newEvents}
          nativeOn={newNativeEvents}
          v-model={this.editRowsData[rowId][field.prop]}
          {...{
            attrs: field,
            props: field
          }}
        />
      )
    }

Суммировать

Эта форма содержит множество функций, предпочтительна длина статьи, если вы сочтете ее полезной, вы можете получить к ней доступ, посетивGitHub.com/snow Zijun/V…Просмотрите полный код, код и документация этого хранилища будут продолжать улучшаться, добро пожаловать в звезду. Начало накопления, обратите внимание на публичный номер, редакция тянет вас в группу фронтального общения

Прочитайте наши последние хитыVueСтатьи по теме, я Zijun, увидимся каждый понедельник

Практические навыки, Vue тоже умеет так писать2700+ лайков

Абсолютно сухой материал~! Изучите эти советы Vue, вы сможете уйти с работы пораньше и встречаться с богиней1200+ лайков

Впереди высокая энергия, это последняя волна боевых навыков Vue, это бесполезно и потрясающе.Похвала 1000+

Я настраиваю Vue в проекте так1000+ лайков

Научись пользоваться Vue JSX, машина старых крестных твоя700+ лайков

Несколько советов, как сделать проекты Vue более плавными300+ лайков

Увидимся!重读vue2.0风格指南,我整理了这些关键规则150+ лайков

Эпилог

Не истощайте свое вдохновение и воображение, не будьте рабом своих моделей. - Винсент Ван Гог

В этой статье используетсяmdniceнабор текста