2
0

App.vue 3.1 KB

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