render + mixins 寫法,基礎(chǔ)篇

vue中使用 render + mixins 寫法塔逃,極大程度簡化代碼開發(fā)

背景介紹

  • 常規(guī)的列表頁面開發(fā)


    頁面展示

組件

  • page.vue
<template>
  <div class="page-container">
    <!-- 查詢條件 -->
    <header class="page-search">
      <es-row>
        <es-col :span="8" class="form-item">
          <label>查詢條件</label>
          <es-input v-model="searchParams.keyword" placeholder="請輸入查詢關(guān)鍵字" />
        </es-col>
        <es-col :span="8" class="form-item">
          <es-button type="primary" :loading="table.loading" @click="search">查詢</es-button>
          <es-button @click="reset">重置</es-button>
        </es-col>
      </es-row>
    </header>
    <!-- 內(nèi)容區(qū)域 -->
    <main class="page-content">
      <es-table :data="table.data">
          <es-table-column prop="name" label="姓名" />
          <es-table-column prop="phone" label="手機(jī)號" />
          <es-table-column prop="address" label="地址" />
          <es-table-column label="操作" width="140">
            <template v-slot="{ row }">
              <es-button size="mini" type="primary" plain @click="editItem(row)">編輯</es-button>
              <es-button size="mini" type="danger" @click="deleteItem(row)">刪除</es-button>
            </template>
          </es-table-column>
      </es-table>
    </main>
    <!-- 底部分頁 -->
    <FooterPagination :page="pagination.page" :size="pagination.size" :total="pagination.total" @changePage="changePage" @changeSize="changeSize" />
  </div>
</template>

<script>
import FooterPagination from './components/FooterPagination.vue'

export default {
  components: {
    FooterPagination
  },

  data() {
    return {
      // 查詢條件
      searchParams: {
        keyword: ''
      },
      cloneParams: {},
      // 表格
      table: {
        loading: false,
        data: []
      },
      // 分頁
      pagination: {
        page: 1,
        size: 20,
        total: 78
      }
    }
  },

  created() {
    this.cloneParams = JSON.parse(JSON.stringify(this.searchParams))
    this.search()
  },

  methods: {
    /**
     * 查詢
     */
    search() {
      this.pagination.page = 1;
      this.getTableData();
    },

    /**
     * 獲取數(shù)據(jù)
     */
    getTableData() {
      this.table.loading = true;
      this.$axios.get('/data/list.json').then(({ data }) => {
        this.table.loading = false;
        this.table.data = data.list;
        this.pagination.total = data.totalCount;
      }).catch(() => {
        this.table.loading = false;
      })
    },

    /**
     * 重置
     */
    reset() {
      this.searchParams = JSON.parse(JSON.stringify(this.cloneParams))
    },

    /**
     * 改變分頁頁數(shù)
     * @param {Number} page 頁數(shù)
     */
    changePage(page) {
      this.pagination.page = page
      this.getTableData()
    },

    /**
     * 改變每頁條數(shù)
     * @param {Number} size 每頁條數(shù)
     */
    changeSize(size) {
      this.pagination.size = size
      this.changePage(1)
    },

    /**
     * 編輯
     * @param {Object} row 操作的行數(shù)據(jù)
     */
    editItem(row) {
      console.log(row)
    },

    /**
     * 刪除
     * @param {Object} row 操作的行數(shù)據(jù)
     */
    deleteItem(row) {
      console.log(row)
    }
  }
}
</script>
  • FooterPagination.vue
<template>
  <footer class="page-pagination">
    <es-pagination
      @size-change="changeSize"
      @current-change="changePage"
      :current-page="page"
      :page-sizes="[10, 20, 50, 100]"
      :page-size="size"
      layout="total, sizes, prev, pager, next, jumper"
      :total="total"
    />
  </footer>
</template>

<script>
export default {
  props: {
    page: Number,
    size: Number,
    total: Number,
  },

  methods: {
    changePage(page) {
      this.$emit('changePage', page);
    },
    changeSize(size) {
      this.$emit('changeSize', size);
    },
  },
}
</script>

優(yōu)點(diǎn)
  • FooterPagination.vue
// 這些代碼可以復(fù)用挖炬,只要在這里改動配置揽浙,可以達(dá)到系統(tǒng)中所有分頁都生效
  <es-pagination
      @size-change="changeSize"
      @current-change="changePage"
      :current-page="page"
      :page-sizes="[10, 20, 50, 100]"
      :page-size="size"
      layout="total, sizes, prev, pager, next, jumper"
      :total="total"
    />
缺點(diǎn)
  • page.vue
// 還是要在父組件繁瑣的寫配置,如果要加一個props或者$emit茅茂,那么還要到每個引用的底部分頁的頁面去加
<template>
  ...
  <!-- 底部分頁 -->
  <FooterPagination :page="pagination.page" :size="pagination.size" :total="pagination.total" @changePage="changePage" @changeSize="changeSize" />
</template>
<script>
import FooterPagination from './components/FooterPagination.vue'

export default {
  components: {
    FooterPagination
  },

  data() {
    return {
      ...
      // 分頁
      pagination: {
        page: 1,
        size: 20,
        total: 78
      }
    }
  },

  methods: {
    ...
    /**
     * 改變分頁頁數(shù)
     * @param {Number} page 頁數(shù)
     */
    changePage(page) {
      this.pagination.page = page
      this.getTableData()
    },

    /**
     * 改變每頁條數(shù)
     * @param {Number} size 每頁條數(shù)
     */
    changeSize(size) {
      this.pagination.size = size
      this.changePage(1)
    },
    ...
  }
}
</script>

mixins

  • 引入 footerPagination.js
import FooterPagination from '@/components/FooterPagination.vue'

export default {
  components: {
    FooterPagination
  },

  data() {
    return {
      // 分頁
      pagination: {
        page: 1,
        size: 20,
        total: 78
      }
    }
  },

  methods: {
    /**
     * 改變分頁頁數(shù)
     * @param {Number} page 頁數(shù)
     */
     changePage(page) {
      this.pagination.page = page
      this.getTableData()
    },

    /**
     * 改變每頁條數(shù)
     * @param {Number} size 每頁條數(shù)
     */
    changeSize(size) {
      this.pagination.size = size
      this.changePage(1)
    },
  }
}
  • 修改 page.vue
<template>
  <div class="page-container">
    <!-- 查詢條件 -->
    <header class="page-search">
      <es-row>
        <es-col :span="8" class="form-item">
          <label>查詢條件</label>
          <es-input v-model="searchParams.keyword" placeholder="請輸入查詢關(guān)鍵字" />
        </es-col>
        <es-col :span="8" class="form-item">
          <es-button type="primary" :loading="table.loading" @click="search">查詢</es-button>
          <es-button @click="reset">重置</es-button>
        </es-col>
      </es-row>
    </header>
    <!-- 內(nèi)容區(qū)域 -->
    <main class="page-content">
      <es-table :data="table.data">
          <es-table-column prop="name" label="姓名" />
          <es-table-column prop="phone" label="手機(jī)號" />
          <es-table-column prop="address" label="地址" />
          <es-table-column label="操作" width="140">
            <template v-slot="{ row }">
              <es-button size="mini" type="primary" plain @click="editItem(row)">編輯</es-button>
              <es-button size="mini" type="danger" @click="deleteItem(row)">刪除</es-button>
            </template>
          </es-table-column>
      </es-table>
    </main>
    <!-- 底部分頁 -->
    <FooterPagination :page="pagination.page" :size="pagination.size" :total="pagination.total" @changePage="changePage" @changeSize="changeSize" />
  </div>
</template>

<script>
import footerPagination from './mixins/footerPagination.js'

export default {
  mixins: [footerPagination],

  data() {
    return {
      // 查詢條件
      searchParams: {
        keyword: ''
      },
      cloneParams: {},
      // 表格
      table: {
        loading: false,
        data: []
      },
    }
  },

  created() {
    this.cloneParams = JSON.parse(JSON.stringify(this.searchParams))
    this.search()
  },

  methods: {
    /**
     * 查詢
     */
    search() {
      this.pagination.page = 1;
      this.getTableData();
    },

    /**
     * 獲取數(shù)據(jù)
     */
    getTableData() {
      this.table.loading = true;
      this.$axios.get('/data/list.json').then(({ data }) => {
        this.table.loading = false;
        this.table.data = data.list;
        this.pagination.total = data.totalCount;
      }).catch(() => {
        this.table.loading = false;
      })
    },

    /**
     * 重置
     */
    reset() {
      this.searchParams = JSON.parse(JSON.stringify(this.cloneParams))
    },

    /**
     * 編輯
     * @param {Object} row 操作的行數(shù)據(jù)
     */
    editItem(row) {
      console.log(row)
    },

    /**
     * 刪除
     * @param {Object} row 操作的行數(shù)據(jù)
     */
    deleteItem(row) {
      console.log(row)
    }
  }
}
</script>
  • FooterPagination.vue 不做改動
優(yōu)點(diǎn)
  1. 把js部分的代碼捏萍,提取到mixins/footerPagination.js中;使得js配置不用在每個頁面重復(fù)的寫
  2. 規(guī)范組件中屬性和方法空闲,強(qiáng)制命名令杈;避免不同頁面,屬性和方法命名不一樣
缺點(diǎn)
  1. template中html部分仍然無法做到復(fù)用
  2. 配置中的屬性和方法碴倾,新手不容易找到逗噩,可能會忽略覆蓋

render

  • 改寫 page.vue
<script>
import footerPagination from './mixins/footerPagination.js'

export default {
  mixins: [footerPagination],

  data() {
    return {
      // 查詢條件
      searchParams: {
        keyword: ''
      },
      cloneParams: {},
      // 表格
      table: {
        loading: false,
        data: []
      },
    }
  },

  created() {
    this.cloneParams = JSON.parse(JSON.stringify(this.searchParams))
    this.search()
  },

  methods: {
    /**
     * 查詢
     */
    search() {
      this.pagination.page = 1;
      this.getTableData();
    },

    /**
     * 獲取數(shù)據(jù)
     */
    getTableData() {
      this.table.loading = true;
      this.$axios.get('/data/list.json').then(({ data }) => {
        this.table.loading = false;
        this.table.data = data.list;
        this.pagination.total = data.totalCount;
      }).catch(() => {
        this.table.loading = false;
      })
    },

    /**
     * 重置
     */
    reset() {
      this.searchParams = JSON.parse(JSON.stringify(this.cloneParams))
    },

    /**
     * 編輯
     * @param {Object} row 操作的行數(shù)據(jù)
     */
    editItem(row) {
      console.log(row)
    },

    /**
     * 刪除
     * @param {Object} row 操作的行數(shù)據(jù)
     */
    deleteItem(row) {
      console.log(row)
    }
  },

  render() {
    return (
      <div class="page-container">
        {/* 查詢條件 */}
        <header class="page-search">
          <es-row>
            <es-col span={8} class="form-item">
              <label>查詢條件</label>
              <es-input vModel={this.searchParams.keyword} placeholder="請輸入查詢關(guān)鍵字" />
            </es-col>
            <es-col span={8} class="form-item">
              <es-button type="primary" loading={this.table.loading} vOn:click={() => this.search()}>查詢</es-button>
              <es-button vOn:click={() => this.reset()}>重置</es-button>
            </es-col>
          </es-row>
        </header>
        {/* 內(nèi)容區(qū)域 */}
        <main class="page-content">
          <es-table data={this.table.data}>
              <es-table-column prop="name" label="姓名" />
              <es-table-column prop="phone" label="手機(jī)號" />
              <es-table-column prop="address" label="地址" />
              <es-table-column label="操作" width="140" 
              scopedSlots={{
                default: ({ row }) => (
                  <div>
                    <es-button size="mini" type="primary" plain vOn:click={() => this.editItem(row)}>編輯</es-button>
                    <es-button size="mini" type="danger" vOn:click={() => this.deleteItem(row)}>刪除</es-button>
                  </div>
                ),
              }} />
          </es-table>
        </main>
        {/* 底部分頁 */}
        {this.genFooterPagination()}
      </div>
    )
  }
}
</script>
  • 改寫 mixins/footerPagination.js
    在methods里,增加genFooterPagination方法
export default {
  ...
  methods: {
    ...
    /**
     * 渲染 底部分頁
     */
    genFooterPagination() {
      return (
        <footer class="page-pagination">
          <es-pagination
            vOn:size-change={this.changeSize}
            vOn:current-change={this.changePage}
            current-page={this.pagination.page}
            page-sizes={[10, 20, 50, 100]}
            page-size={this.pagination.size}
            layout="total, sizes, prev, pager, next, jumper"
            total={this.pagination.total}
          />
        </footer>
      )
    },
  }
}
優(yōu)點(diǎn)
  1. 可以復(fù)用template中html部分跌榔,把es-pagination組件异雁,真正直接放到頁面里;直接用頁面里的data屬性和methods方法僧须,不需要下發(fā)和上報(bào)
缺點(diǎn)
  1. 寫法復(fù)雜纲刀,但隨著vue-cli3對vue-jsx的支持,讓jsx在vue中開發(fā)使用担平,也變得更加便利示绊;
  2. 官方文檔:https://github.com/vuejs/jsx

render + mixins

  1. 結(jié)合mixins的優(yōu)點(diǎn):復(fù)用js邏輯代碼;
  2. 結(jié)合render的優(yōu)點(diǎn):復(fù)用html結(jié)構(gòu)暂论;
    以上兩者結(jié)合在一起使用面褐,可以做到真正意義上的代碼復(fù)用;而不是組件形式的偽復(fù)用取胎。

源碼鏈接:https://gitee.com/wkp_mayun/render-mixins-esay

下一篇:render + mixins 寫法展哭,進(jìn)階

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市闻蛀,隨后出現(xiàn)的幾起案子匪傍,更是在濱河造成了極大的恐慌,老刑警劉巖觉痛,帶你破解...
    沈念sama閱讀 219,110評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件役衡,死亡現(xiàn)場離奇詭異,居然都是意外死亡秧饮,警方通過查閱死者的電腦和手機(jī)映挂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來盗尸,“玉大人柑船,你說我怎么就攤上這事∑酶鳎” “怎么了鞍时?”我有些...
    開封第一講書人閱讀 165,474評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長扣蜻。 經(jīng)常有香客問我逆巍,道長,這世上最難降的妖魔是什么莽使? 我笑而不...
    開封第一講書人閱讀 58,881評論 1 295
  • 正文 為了忘掉前任锐极,我火速辦了婚禮,結(jié)果婚禮上芳肌,老公的妹妹穿的比我還像新娘灵再。我一直安慰自己,他們只是感情好亿笤,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,902評論 6 392
  • 文/花漫 我一把揭開白布翎迁。 她就那樣靜靜地躺著,像睡著了一般净薛。 火紅的嫁衣襯著肌膚如雪汪榔。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,698評論 1 305
  • 那天肃拜,我揣著相機(jī)與錄音痴腌,去河邊找鬼。 笑死爆班,一個胖子當(dāng)著我的面吹牛衷掷,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播柿菩,決...
    沈念sama閱讀 40,418評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼戚嗅,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了枢舶?” 一聲冷哼從身側(cè)響起懦胞,我...
    開封第一講書人閱讀 39,332評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎凉泄,沒想到半個月后躏尉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,796評論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡后众,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,968評論 3 337
  • 正文 我和宋清朗相戀三年胀糜,在試婚紗的時候發(fā)現(xiàn)自己被綠了颅拦。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,110評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡教藻,死狀恐怖距帅,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情括堤,我是刑警寧澤碌秸,帶...
    沈念sama閱讀 35,792評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站悄窃,受9級特大地震影響讥电,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜轧抗,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,455評論 3 331
  • 文/蒙蒙 一恩敌、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧横媚,春花似錦潮剪、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,003評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至绽乔,卻和暖如春弧蝇,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背折砸。 一陣腳步聲響...
    開封第一講書人閱讀 33,130評論 1 272
  • 我被黑心中介騙來泰國打工看疗, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人睦授。 一個月前我還...
    沈念sama閱讀 48,348評論 3 373
  • 正文 我出身青樓两芳,卻偏偏與公主長得像,于是被迫代替她去往敵國和親去枷。 傳聞我的和親對象是個殘疾皇子怖辆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,047評論 2 355

推薦閱讀更多精彩內(nèi)容