最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

vue3新擬態(tài)組件庫開發(fā)流程之table組件源碼分析

 更新時間:2023年04月29日 08:55:49   作者:SanOrintea  
這篇文章主要介紹了vue3新擬態(tài)組件庫開發(fā)流程——table組件源碼,本文通過示例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下

基礎(chǔ)表格

首先開發(fā)table組件之前,先想好要用什么樣式的api,因為筆者在生產(chǎn)工作中用的都是element,所以前面幾個組件風格和element類似,但是這次不打算用element的風格了,打算換一種,直接展示:
我們期望用戶這樣使用:

<script setup>
const dataList = [
  {
    id: 1,
    name: '《JavaEE企業(yè)應用實戰(zhàn)》',
    author: 'dev1ce',
    price: '10.22',
    desc: '書中最后講解的項目案例,涵蓋從前期設(shè)計到最終實施的整個過程,對全書知識點進行串聯(lián)和鞏固,使讀者融會貫通,掌握Java Web開發(fā)的精髓。'
  },
  {
    id: 2,
    name: '《代碼整潔之道》',
    author: 'R0bert',
    price: '10.22',
    desc: '整潔代碼并非遵循一組規(guī)則編寫的。不可能因為學習一套金規(guī)玉律就成為軟件大師。專業(yè)精神和手工藝來自于推動規(guī)則形成的價值。'
  },
  {
    id: 3,
    name: '《ECMAScript 6 入門教程》',
    author: 'y1feng',
    price: '10.22',
    desc: '本書是一本開源的 JavaScript 語言教程,全面介紹 ECMAScript 6 新引入的語法特性。'
  },
]
const columnsList = [
  {
    title: '書名',
    key: 'name'
  },
  {
    title: '作者',
    key: 'author'
  },
  {
    title: '價格',
    key: 'price'
  },
  {
    title: '簡介',
    key: 'desc'
  }
]
</script>
<template>
    <sanorin-table :columns="columnsList" :data="dataList"/>
</template>

依照這個寫出以下代碼

<script setup>
  import { ref, computed } from 'vue'
  import { useProp, useNeumorphism } from '../mixin/neumorphism'
  const props = defineProps({
      ...useProp,
      ...{
        data: { // dataList
            type: Array,
            default: () => [],
        },
        columns: { // columnsList
            type: Array,
            default: () => [],
        },
      }
  })
  const { baseStyleObject } = useNeumorphism(props)
  let styleObject =  computed(() => ({ 
    // '--font-size': `${props.size-26}px`, '--line-height': `${props.size-20}px`, '--limit-size': `${props.size-28}px`
  }))
</script>
<template>
    <div :style="{...baseStyleObject,...styleObject}">
      <table style="">
        <thead>
          <tr class="neumorphism">
            <!-- 表頭循環(huán) -->
            <th v-for="col in columns" :key="col.key">{{col.title}}</th>
          </tr>
        </thead>
        <tbody>
          <!-- 表體循環(huán) -->
          <tr class="neumorphism" v-for="row in data" :key="row.id">
            <td v-for="col in columns" :key="col.key">
              <span>
                {{row[col.key]}}
              </span>
            </td>
          </tr>
        </tbody>
      </table>
    </div>
</template>
<script>
  export default {
    name: 'sanorin-table',
  }
</script>
<style scoped>
  @import "../../style/index.css";
  @import "../../style/neumorphism.css";
  table {
    width: 100%;
    /* border-collapse: collapse; */
    empty-cells: show;
    border-collapse:separate;
    border-spacing:0px 10px;
  }
  table td,
  table th {
    color: var(--text-color);
    padding: 8px 16px 8px 16px;
    text-align: left;
  }
  table th {
    color: var(--text-back-color) !important;
    font-weight: 600;
    white-space: nowrap;
  }
  table tr{
    margin-top: 20px;
  }
</style>

最后出來的效果就是:

在這里插入圖片描述

然后實現(xiàn)了這個后我們開始做后面的,先從固定表頭開始。

固定表頭

固定表頭有三種方法,詳見我的另一篇文章http://m.fzitv.net/article/91143.htm
這里先采用第一種,以后不能滿足需求了再改成后面的方法。
效果和代碼如下:

請?zhí)砑訄D片描述

<script setup>
  import { ref, computed } from 'vue'
  import { useProp, useNeumorphism } from '../mixin/neumorphism'
  const props = defineProps({
      ...useProp,
      ...{
        data: { // dataList
            type: Array,
            default: () => [],
        },
        columns: { // columnsList
            type: Array,
            default: () => [],
        },
      }
  })
  const { baseStyleObject } = useNeumorphism(props)
  let styleObject =  computed(() => ({ 
  }))
</script>
<template>
    <div class="san-table scrollbar" :style="{...baseStyleObject,...styleObject}">
      <table>
        <thead>
            <tr class="neumorphism">
              <!-- 表頭循環(huán) -->
              <th v-for="col in columns" :key="col.key">{{col.title}}</th>
            </tr>
        </thead>
        <tbody>
          <!-- 表體循環(huán) -->
          <tr class="neumorphism" v-for="row in data" :key="row.id">
            <td v-for="col in columns" :key="col.key">
              <span>
                {{row[col.key]}}
              </span>
            </td>
          </tr>
        </tbody>
      </table>
    </div>
</template>
<script>
  export default {
    name: 'sanorin-table',
  }
</script>
<style scoped>
  @import "../../style/index.css";
  @import "../../style/neumorphism.css";
  .san-table{
    padding: 0px 20px 20px 20px;
    height: 200px;
    position: relative;
    width: 700px;
    overflow: auto;
  }
  table {
    width: 100%;
    table-layout: fixed;
    empty-cells: show;
    border-collapse:separate;
    border-spacing:0px 10px;
  }
  thead {
    position: sticky;
    top: 10px;
  }
  thead:before{
    position: absolute;
    content: '';
    width: calc(100% + var(--shadow-blur) * 2);
    transform: translate(calc(var(--shadow-blur) * -1) , -10px);
    height: 20px;
    background-color: var(--main-color);
    z-index: -1;
  }
  table td,
  table th {
    color: var(--text-color);
    padding: 8px 16px 8px 16px;
    text-align: left;
  }
  table th {
    color: var(--text-back-color) !important;
    font-weight: 600;
    white-space: nowrap;
  }
</style>

高度/流體高度

可以為 Table 設(shè)置一個高度。(height)
當數(shù)據(jù)量動態(tài)變化時,可以為 Table 設(shè)置一個最大高度。(maxHeight) 通過設(shè)置max-height屬性為 Table 指定最大高度。此時若表格所需的高度大于最大高度,則會顯示一個滾動條。
只要在sanorin-table元素中定義了height或者maxHeight屬性,即可實現(xiàn)固定表頭的表格,而不需要額外的代碼。
代碼如下:

<script setup>
  import { ref, computed, reactive } from 'vue'
  import { useProp, useNeumorphism } from '../mixin/neumorphism'
  const props = defineProps({
      ...useProp,
      ...{
        data: { // dataList
            type: Array,
            default: () => [],
        },
        columns: { // columnsList
            type: Array,
            default: () => [],
        },
        height: {
          type: Number,
        },
        maxHeight: {
          type: Number,
        }
      }
  })
  // 高度設(shè)置
  let tableHeightStyleObj = computed(() => { 
    let styleObj = ((e) => {
      if (e.maxHeight) return { maxHeight: e.maxHeight + 'px' }
      if (e.height) return { height: e.height + 'px' }
      return {}
    })({...props})
    return styleObj
  })
  const { baseStyleObject } = useNeumorphism(props)
  let styleObject =  computed(() => ({ 
    ...tableHeightStyleObj.value
  }))
</script>
<template>
    <div class="san-table scrollbar" :style="{...baseStyleObject,...styleObject}">
      <table>
        <colgroup>
            <col v-for="(col, index) in columns" :key="index">
        </colgroup>
        <thead>
            <tr class="neumorphism">
              <th v-for="col in columns" :key="col.key"> {{col.title}} </th>
            </tr>
        </thead>
        <tbody>
          <tr class="neumorphism" v-for="row in data" :key="row.id">
            <td v-for="col in columns" :key="col.key"> {{row[col.key]}} </td>
          </tr>
        </tbody>
      </table>
    </div>
</template>
<script>
  export default {
    name: 'sanorin-table',
  }
</script>
<style scoped>
  @import "../../style/index.css";
  @import "../../style/neumorphism.css";
  .san-table{
    padding: 0px 20px 20px 20px;
    position: relative;
    width: 700px;
    overflow: auto;
  }
  table {
    width: 100%;
    table-layout: fixed;
    empty-cells: show;
    border-collapse:separate;
    border-spacing:0px 10px;
  }
  thead {
    position: sticky;
    top: 10px;
  }
  thead:before{
    position: absolute;
    content: '';
    width: calc(100% + var(--shadow-blur) * 2);
    transform: translate(calc(var(--shadow-blur) * -1) , -10px);
    height: 20px;
    background-color: var(--main-color);
    z-index: -1;
  }
  table td,
  table th {
    color: var(--text-color);
    padding: 8px 16px 8px 16px;
    text-align: left;
  }
  table th {
    color: var(--text-back-color) !important;
    font-weight: 600;
    white-space: nowrap;
  }
</style>

自定義列寬

接下來加入寬度控制,希望在columns 傳入的數(shù)組對象內(nèi)加入寬度,示例如下:

const columnsList = [
  {
    title: '書名',
    key: 'name',
    width: 100,
  },
  {
    title: '作者',
    key: 'author',
    width: 100,
  },
  {
    title: '價格',
    key: 'price',
    width: 100,
  },
  {
    title: '簡介',
    key: 'desc',
    minWidth: 350,
  }
]

希望達到以下效果
1、含有width的列,寬度固定,不隨瀏覽器寬度變化而變化
2、含有minWidth的列,在大于設(shè)定值時,自動填充 table 剩余寬度,小于設(shè)定值時,固定該寬度
3、不包含width和minWidth的列,自動填充 table 剩余寬度
根據(jù)我們的需求,我們需要單獨控制每一列的寬度展示,并在瀏覽器寬度變化時實時的重新計算并且重新渲染列。
首先定義出一個方法,用來計算每一列在當前情況下所要的寬度,再綁定要dom上。然后,每次表格變化/瀏覽器寬度變化時候就能實時響應改變Table的寬度了。

  const initColumns = () => {
    // 計算每一列在當前情況下所要的寬度
  }
  watch(() => props.columns, () => { initColumns() });
  onMounted(() => {
    nextTick(() => {
      initColumns();
      on(window, 'resize', throttle(() => initColumns(), 400));
    });
  });
  onBeforeUnmount(() => off(window, 'resize', () => initColumns()));

全部代碼:

<script setup>
  import { ref, computed, watch, onMounted, onBeforeUnmount, nextTick } from 'vue'
  import { on, off } from '../../utils/listener'
  import { throttle } from "../../utils/debounce&throttle"
  import { useProp, useNeumorphism } from '../mixin/neumorphism'
  const table = ref() // 與html中ref=""對應,定位dom元素
  const props = defineProps({
      ...useProp,
      ...{
        data: { // dataList
            type: Array,
            default: () => [],
        },
        columns: { // columnsList
            type: Array,
            default: () => [],
        },
        height: { // height
          type: Number,
        },
        maxHeight: { // 流體高度
          type: Number,
        },
        minUnsetWidth: {  // 未設(shè)置寬度時最小寬度
          type: Number,
          default: 80
        }
      }
  })
  // 高度設(shè)置
  let tableHeightStyleObj = computed(() => { 
    let styleObj = ((e) => {
      if (e.maxHeight) return { maxHeight: e.maxHeight + 'px' }
      if (e.height) return { height: e.height + 'px' }
      return {}
    })({...props})
    return styleObj
  })
  // 列寬設(shè)置
  let col = ref([])
  const { columns, minUnsetWidth } = props
  const _min_column_width = minUnsetWidth // 未設(shè)置寬度時最小寬度
  const initColumns = () => {
    col.value = (() => {
      let _total_width = table.value.offsetWidth  // 表格dom元素總寬度
      let _needed_minWidth = columns.reduce((t, v) => { // 需要的最小寬度
        t += v.width || v.minWidth || _min_column_width
        return t
      }, 0)
      // 需要的最小寬度比總寬度大,則取minWidth即可
      if (_needed_minWidth >= _total_width) return columns.reduce((t, v) => {
        let n = v.width || v.minWidth || _min_column_width
        t = [...t, n]
        return t
      }, [])
      // 需要的最小寬度比總寬度大,則要把minWidth加權(quán),權(quán)重為(未分配的寬度 / minWidth之和)
      let _unassigned_width = columns.reduce((t, v) => {
        t += v.minWidth || 0
        return t
      }, 0)
      let _assigned_width = _needed_minWidth - _unassigned_width
      let _width_power = (_total_width - _assigned_width) / _unassigned_width
      return columns.reduce((t, v) => {
        let n = v.width || (v.minWidth ? (_width_power * v.minWidth).toFixed(2) : _min_column_width)
        t = [...t, n]
        return t
      }, [])
    })()
  }
  watch(() => props.columns, () => { initColumns() })
  const throttleInitColumns = () => throttle(() => initColumns(), 400)
  onMounted(() => {
    nextTick(() => {
      initColumns()
      on(window, 'resize', throttleInitColumns)
    })
  })
  onBeforeUnmount(() => off(window, 'resize', throttleInitColumns))
  const { baseStyleObject } = useNeumorphism(props)
  let styleObject =  computed(() => ({ 
    ...tableHeightStyleObj.value
  }))
</script>
<template>
    <div class="san-table scrollbar" :style="{...baseStyleObject,...styleObject}">
      <table ref="table">
        <colgroup>
            <col v-for="(item, index) in col" :key="index" :width="`${item}px`">
        </colgroup>
        <thead>
            <tr class="neumorphism">
              <th v-for="col in columns" :key="col.key"> {{col.title}} </th>
            </tr>
        </thead>
        <tbody>
          <tr class="neumorphism" v-for="row in data" :key="row.id">
            <td v-for="col in columns" :key="col.key"> {{row[col.key]}} </td>
          </tr>
        </tbody>
      </table>
    </div>
</template>
<script>
  export default {
    name: 'sanorin-table',
  }
</script>
<style scoped>
  @import "../../style/index.css";
  @import "../../style/neumorphism.css";
  .san-table{
    padding: 0px 20px 20px 20px;
    position: relative;
    overflow: auto;
  }
  table {
    width: 100%;
    table-layout: fixed;
    empty-cells: show;
    border-collapse:separate;
    border-spacing:0px 10px;
  }
  thead {
    position: sticky;
    top: 10px;
  }
  thead:before{
    position: absolute;
    content: '';
    width: calc(100% + var(--shadow-blur) * 2);
    transform: translate(calc(var(--shadow-blur) * -1) , -10px);
    height: 20px;
    background-color: var(--main-color);
    z-index: -1;
  }
  table td,
  table th {
    color: var(--text-color);
    padding: 8px 16px 8px 16px;
    text-align: left;
    word-break:break-all;
  }
  table th {
    color: var(--text-back-color) !important;
    font-weight: 600;
    white-space: nowrap;
  }
</style>

其中用到的兩個js,防抖節(jié)流和注冊監(jiān)聽這里也放下吧

/* 防抖節(jié)流函數(shù) */
let timeout = null // 創(chuàng)建一個標記用來存放定時器的返回值
let count = 0;
export function debounce(fn, wait = 1000, immediate = false) {
  return function () {
    const args = arguments;
    if (immediate) {
      if (count == 0) {
        fn.apply(this, arguments)
        count++;
      } else {
        if (timeout) {
          clearTimeout(timeout) // 每當用戶輸入的時候把前一個 setTimeout clear 掉 
        }
        timeout = setTimeout(() => {
          fn.apply(this, arguments)
        }, wait)
      }
    } else {
      if (timeout) {
        clearTimeout(timeout) // 每當用戶輸入的時候把前一個 setTimeout clear 掉 
      }
      timeout = setTimeout(() => {
        fn.apply(this, arguments)
      }, wait)
    }
  }()
}
let canRun = true;
let count1 = 0;
export function throttle(fn, wait = 1000, immediate = true) {
  return function () {
    if (immediate) {
      if (count1 == 0) {
        fn.apply(this, arguments);
        count1++;
      } else {
        if (canRun) {
          canRun = false
          setTimeout(function () {
            fn.apply(this, arguments)
            canRun = true
          }, wait);
        }
      }
    } else {
      if (!canRun) return
      canRun = false
      setTimeout(function () {
        fn.apply(this, arguments)
        canRun = true
      }, wait);
    }
  }()
}
/**
 * 綁定事件 on(element, event, handler)
 */
export const on = (element, event, handler) => {
  if (document.addEventListener) {
    if (element && event && handler) {
      element.addEventListener(event, handler, false)
    }
  }
}
/**
 * 解綁事件 off(element, event, handler)
 */
export const off = (element, event, handler) => {
  if (document.removeEventListener) {
    if (element && event) {
      element.removeEventListener(event, handler, false)
    }
  }
}

序號

自定義內(nèi)容(slot)

固定列

全選

展開

到此這篇關(guān)于vue3新擬態(tài)組件庫開發(fā)流程——table組件源碼的文章就介紹到這了,更多相關(guān)vue3 table組件源碼內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vue.js中ref及$refs的使用方法解析

    vue.js中ref及$refs的使用方法解析

    這篇文章主要介紹了vue.js中ref及$refs的使用方法解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-10-10
  • vue中如何下載excel流文件及設(shè)置下載文件名

    vue中如何下載excel流文件及設(shè)置下載文件名

    這篇文章主要介紹了vue中如何下載excel流文件及設(shè)置下載文件名,對vue感興趣的同學,可以參考下
    2021-05-05
  • 淺談vue中組件綁定事件時是否加.native

    淺談vue中組件綁定事件時是否加.native

    今天小編就為大家分享一篇淺談vue中組件綁定事件時是否加.native,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-11-11
  • 淺談VUE uni-app 模板語法

    淺談VUE uni-app 模板語法

    這篇文章主要介紹了uni-app 的模板語法,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-10-10
  • Vue.js 和 MVVM 的注意事項

    Vue.js 和 MVVM 的注意事項

    MVVM 是Model-View-ViewModel 的縮寫,它是一種基于前端開發(fā)的架構(gòu)模式,Vue.js 是一個提供 MVVM 風格的雙向數(shù)據(jù)綁定的 Javascript 庫,專注于View 層。這篇文章給大家介紹Vue.js 和 MVVM 的注意事項,感興趣的朋友一起看看吧
    2016-11-11
  • Vue二次封裝axios為插件使用詳解

    Vue二次封裝axios為插件使用詳解

    這篇文章主要介紹了Vue二次封裝axios為插件使用詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-05-05
  • element-plus的el-tree的雙向綁定示例代碼

    element-plus的el-tree的雙向綁定示例代碼

    這篇文章主要介紹了element-plus的el-tree的雙向綁定的示例代碼,代碼簡單易懂,結(jié)合圖文給大家展示,感興趣的朋友跟隨小編一起看看吧
    2024-12-12
  • vue數(shù)據(jù)監(jiān)聽解析Object.defineProperty與Proxy區(qū)別

    vue數(shù)據(jù)監(jiān)聽解析Object.defineProperty與Proxy區(qū)別

    這篇文章主要為大家介紹了vue數(shù)據(jù)監(jiān)聽解析Object.defineProperty Proxy源碼示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-03-03
  • Vue實現(xiàn)在線預覽pdf文件功能(利用pdf.js/iframe/embed)

    Vue實現(xiàn)在線預覽pdf文件功能(利用pdf.js/iframe/embed)

    項目要求需要預覽pdf文件,網(wǎng)上找了很久,發(fā)現(xiàn)pdf.js的效果,這篇文章主要給大家介紹了關(guān)于Vue實現(xiàn)在線預覽pdf文件功能,主要利用pdf.js/iframe/embed來實現(xiàn)的,需要的朋友可以參考下
    2021-06-06
  • Vue路由回退的完美解決方案(vue-route-manager)

    Vue路由回退的完美解決方案(vue-route-manager)

    最近做了一個vue項目關(guān)于路由場景的問題,路由如何回退指定頁面,在此做個記錄,這篇文章主要給大家介紹了關(guān)于Vue路由回退的完美解決方案,主要利用的是vue-route-manager,需要的朋友可以參考下
    2021-09-09

最新評論

德江县| 霍州市| 泊头市| 富源县| 天祝| 镇雄县| 丹东市| 韶山市| 赤壁市| 日照市| 舞阳县| 扬中市| 浮山县| 北碚区| 宁津县| 阜新市| 贺兰县| 义马市| 阿拉善盟| 昌江| 阳西县| 桐庐县| 余庆县| 锡林浩特市| 杭州市| 南溪县| 锦州市| 周口市| 鄯善县| 二连浩特市| 台安县| 无棣县| 洱源县| 滦南县| 上蔡县| 巴塘县| 新巴尔虎左旗| 于田县| 外汇| 怀宁县| 邵武市|