1. Vue 3.0 性能提升主要是通过哪几方面体现的?
    • 更小的打包体积
    • 采用CompositionApi
    1. Vue 3.0 所采用的 Composition Api 与 Vue 2.x使用的Options Api 有什么区别?
    • 使得代码可以以业务逻辑为模块组织,方便了复用
    1. Proxy 相对于 Object.defineProperty 有哪些优点?
    • 实现了数组用length和用下标修改不能响应式变化的缺陷
    • 代理了对象,而不是属性
    • 本身的实现过程更加简洁
    1. Vue 3.0 在编译方面有哪些优化?
    • 使用浏览器支持模块化加载的特性直接加载文件,使用服务端贬编译为js文件,再返回给浏览器解释执行,不需要提前打包项目
    • 加速了热更新响应速度,得到了更好的开发体验
    1. Vue.js 3.0 响应式系统的实现原理?
    • weakMap, Map, Set
    • reactive, ref, effect,

    数组也可以用 in 遍历

    在todo list 案例中,我觉得有收获的点:

    • 根据hash名称创建函数,完美避开if else 语句

      1. <ul class="filters">
      2. <li><a href="#/all">All</a></li>
      3. <li><a href="#/active">Active</a></li>
      4. <li><a href="#/completed">Completed</a></li>
      5. </ul>

      ```javascript const filter = { all: list => list, active: list => list.filter(todo => !todo.completed), completed: list => list.filter(todo => todo.completed) } // 处理路由变化逻辑

      const onHashChange = () => { const hash = window.location.hash.replace(‘#/‘, ‘’) if (filter[hash]) {

      1. // 正确的路由跳转只有3个
      2. type.value = hash

      } else {

      1. // 不正确的路由跳转有 路由输入错误 初始状态下没有hash 都直接转到 all hash 处理
      2. type.value = 'all'
      3. window.location.hash = ''

      } }

    // 监听hashchange事件(我不熟悉这个事件) onMounted(() => { window.addEventListener(‘hashchange’, onHashChange) onHashChange() })

    onUnmounted(() => { window.removeEventListener(‘hashchange’, onHashChange) })

    1. 疑惑的点:<br />todo === editingTodo 这都是对象,怎么可以用来判断是否相等<br />我觉得还需要听一遍,这里面的逻辑对我来说很有条理,功能各司其职,需要学习它如何拆分,又如何分类这些功能的。
    2. ```vue
    3. <template>
    4. <section id="app" class="todoapp">
    5. <header class="header">
    6. <h1>todos</h1>
    7. <input
    8. class="new-todo"
    9. placeholder="What needs to be done?"
    10. autocomplete="off"
    11. autofocus
    12. v-model="input"
    13. @keyup.enter="addTodo"
    14. >
    15. </header>
    16. <section class="main" v-show="count">
    17. <input id="toggle-all" class="toggle-all" v-model="allDone" type="checkbox">
    18. <label for="toggle-all">Mark all as complete</label>
    19. <ul class="todo-list">
    20. <li
    21. v-for="todo in filteredTodos"
    22. :key="todo"
    23. :class="{ editing: todo === editingTodo, completed: todo.completed }"
    24. >
    25. <div class="view">
    26. <input class="toggle" type="checkbox" v-model="todo.completed">
    27. <label @dblclick="editTodo(todo)">{{ todo.text }}</label>
    28. <button class="destroy" @click="remove(todo)"></button>
    29. </div>
    30. <input
    31. class="edit"
    32. type="text"
    33. v-editing-focus="todo === editingTodo"
    34. v-model="todo.text"
    35. @keyup.enter="doneEdit(todo)"
    36. @blur="doneEdit(todo)"
    37. @keyup.esc="cancelEdit(todo)"
    38. >
    39. </li>
    40. </ul>
    41. </section>
    42. <footer class="footer" v-show="count">
    43. <span class="todo-count">
    44. <strong>{{ remainingCount }}</strong> {{ remainingCount > 1 ? 'items' : 'item' }} left
    45. </span>
    46. <ul class="filters">
    47. <li><a href="#/all">All</a></li>
    48. <li><a href="#/active">Active</a></li>
    49. <li><a href="#/completed">Completed</a></li>
    50. </ul>
    51. <button class="clear-completed" @click="removeCompleted" v-show="count > remainingCount">
    52. Clear completed
    53. </button>
    54. </footer>
    55. </section>
    56. <footer class="info">
    57. <p>Double-click to edit a todo</p>
    58. <!-- Remove the below line ↓ -->
    59. <p>Template by <a href="http://sindresorhus.com">Sindre Sorhus</a></p>
    60. <!-- Change this out with your name and url ↓ -->
    61. <p>Created by <a href="https://www.lagou.com">教瘦</a></p>
    62. <p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
    63. </footer>
    64. </template>
    65. <script>
    66. import './assets/index.css'
    67. import useLocalStorage from './utils/useLocalStorage'
    68. import { ref, computed, onMounted, onUnmounted, watchEffect } from 'vue'
    69. const storage = useLocalStorage()
    70. // 1. 添加待办事项
    71. const useAdd = todos => {
    72. const input = ref('')
    73. const addTodo = () => {
    74. const text = input.value && input.value.trim()
    75. if (text.length === 0) return
    76. todos.value.unshift({
    77. text,
    78. completed: false
    79. })
    80. input.value = ''
    81. }
    82. return {
    83. input,
    84. addTodo
    85. }
    86. }
    87. // 2. 删除待办事项
    88. const useRemove = todos => {
    89. const remove = todo => {
    90. const index = todos.value.indexOf(todo)
    91. todos.value.splice(index, 1)
    92. }
    93. const removeCompleted = () => {
    94. todos.value = todos.value.filter(todo => !todo.completed)
    95. }
    96. return {
    97. remove,
    98. removeCompleted
    99. }
    100. }
    101. // 3. 编辑待办项
    102. const useEdit = remove => {
    103. let beforeEditingText = ''
    104. const editingTodo = ref(null)
    105. const editTodo = todo => {
    106. beforeEditingText = todo.text
    107. editingTodo.value = todo
    108. }
    109. const doneEdit = todo => {
    110. if (!editingTodo.value) return
    111. todo.text = todo.text.trim()
    112. todo.text || remove(todo)
    113. editingTodo.value = null
    114. }
    115. const cancelEdit = todo => {
    116. editingTodo.value = null
    117. todo.text = beforeEditingText
    118. }
    119. return {
    120. editingTodo,
    121. editTodo,
    122. doneEdit,
    123. cancelEdit
    124. }
    125. }
    126. // 4. 切换待办项完成状态
    127. const useFilter = todos => {
    128. const allDone = computed({
    129. get () {
    130. return !todos.value.filter(todo => !todo.completed).length
    131. },
    132. set (value) {
    133. todos.value.forEach(todo => {
    134. todo.completed = value
    135. })
    136. }
    137. })
    138. const filter = {
    139. all: list => list,
    140. active: list => list.filter(todo => !todo.completed),
    141. completed: list => list.filter(todo => todo.completed)
    142. }
    143. const type = ref('all')
    144. const filteredTodos = computed(() => filter[type.value](todos.value))
    145. const remainingCount = computed(() => filter.active(todos.value).length)
    146. const count = computed(() => todos.value.length)
    147. const onHashChange = () => {
    148. const hash = window.location.hash.replace('#/', '')
    149. if (filter[hash]) {
    150. type.value = hash
    151. } else {
    152. type.value = 'all'
    153. window.location.hash = ''
    154. }
    155. }
    156. onMounted(() => {
    157. window.addEventListener('hashchange', onHashChange)
    158. onHashChange()
    159. })
    160. onUnmounted(() => {
    161. window.removeEventListener('hashchange', onHashChange)
    162. })
    163. return {
    164. allDone,
    165. count,
    166. filteredTodos,
    167. remainingCount
    168. }
    169. }
    170. // 5. 存储待办事项
    171. const useStorage = () => {
    172. const KEY = 'TODOKEYS'
    173. const todos = ref(storage.getItem(KEY) || [])
    174. watchEffect(() => {
    175. storage.setItem(KEY, todos.value)
    176. })
    177. return todos
    178. }
    179. export default {
    180. name: 'App',
    181. setup () {
    182. const todos = useStorage()
    183. const { remove, removeCompleted } = useRemove(todos)
    184. return {
    185. todos,
    186. remove,
    187. removeCompleted,
    188. ...useAdd(todos),
    189. ...useEdit(remove),
    190. ...useFilter(todos)
    191. }
    192. },
    193. directives: {
    194. editingFocus: (el, binding) => {
    195. binding.value && el.focus()
    196. }
    197. }
    198. }
    199. </script>
    200. <style>
    201. </style>