App.vue 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. <script setup lang="ts" vapor>
  2. import {
  3. ref,
  4. shallowRef,
  5. triggerRef,
  6. type ShallowRef,
  7. createSelector,
  8. } from '@vue/vapor'
  9. import { buildData } from './data'
  10. import { defer, wrap } from './profiling'
  11. const isVapor = !!import.meta.env.IS_VAPOR
  12. const selected = ref<number>()
  13. const rows = shallowRef<
  14. {
  15. id: number
  16. label: ShallowRef<string>
  17. }[]
  18. >([])
  19. // Bench Add: https://jsbench.me/45lzxprzmu/1
  20. const add = wrap('add', () => {
  21. rows.value.push(...buildData(1000))
  22. triggerRef(rows)
  23. })
  24. const remove = wrap('remove', (id: number) => {
  25. rows.value.splice(
  26. rows.value.findIndex(d => d.id === id),
  27. 1,
  28. )
  29. triggerRef(rows)
  30. })
  31. const select = wrap('select', (id: number) => {
  32. selected.value = id
  33. })
  34. const run = wrap('run', () => {
  35. rows.value = buildData()
  36. selected.value = undefined
  37. })
  38. const update = wrap('update', () => {
  39. const _rows = rows.value
  40. for (let i = 0, len = _rows.length; i < len; i += 10) {
  41. _rows[i].label.value += ' !!!'
  42. }
  43. })
  44. const runLots = wrap('runLots', () => {
  45. rows.value = buildData(10000)
  46. selected.value = undefined
  47. })
  48. const clear = wrap('clear', () => {
  49. rows.value = []
  50. selected.value = undefined
  51. })
  52. const swapRows = wrap('swap', () => {
  53. const _rows = rows.value
  54. if (_rows.length > 998) {
  55. const d1 = _rows[1]
  56. const d998 = _rows[998]
  57. _rows[1] = d998
  58. _rows[998] = d1
  59. triggerRef(rows)
  60. }
  61. })
  62. async function bench() {
  63. for (let i = 0; i < 30; i++) {
  64. rows.value = []
  65. await defer()
  66. await runLots()
  67. }
  68. }
  69. const isSelected = createSelector(selected)
  70. </script>
  71. <template>
  72. <h1>Vue.js ({{ isVapor ? 'Vapor' : 'Virtual DOM' }}) Benchmark</h1>
  73. <div
  74. id="control"
  75. style="display: flex; flex-direction: column; width: fit-content; gap: 6px"
  76. >
  77. <button @click="bench">Benchmark mounting</button>
  78. <button id="run" @click="run">Create 1,000 rows</button>
  79. <button id="runLots" @click="runLots">Create 10,000 rows</button>
  80. <button id="add" @click="add">Append 1,000 rows</button>
  81. <button id="update" @click="update">Update every 10th row</button>
  82. <button id="clear" @click="clear">Clear</button>
  83. <button id="swaprows" @click="swapRows">Swap Rows</button>
  84. </div>
  85. <div id="time"></div>
  86. <table>
  87. <tbody>
  88. <tr
  89. v-for="row of rows"
  90. :key="row.id"
  91. :class="{ danger: isSelected(row.id) }"
  92. >
  93. <td>{{ row.id }}</td>
  94. <td>
  95. <a @click="select(row.id)">{{ row.label.value }}</a>
  96. </td>
  97. <td>
  98. <button @click="remove(row.id)">x</button>
  99. </td>
  100. <td class="col-md-6"></td>
  101. </tr>
  102. </tbody>
  103. </table>
  104. </template>
  105. <style>
  106. .danger {
  107. background-color: red;
  108. }
  109. </style>