- Vue 3.0 性能提升主要是通过哪几方面体现的?
- 更小的打包体积
- 采用CompositionApi
- Vue 3.0 所采用的 Composition Api 与 Vue 2.x使用的Options Api 有什么区别?
- 使得代码可以以业务逻辑为模块组织,方便了复用
- Proxy 相对于 Object.defineProperty 有哪些优点?
- 实现了数组用length和用下标修改不能响应式变化的缺陷
- 代理了对象,而不是属性
- 本身的实现过程更加简洁
- Vue 3.0 在编译方面有哪些优化?
- 使用浏览器支持模块化加载的特性直接加载文件,使用服务端贬编译为js文件,再返回给浏览器解释执行,不需要提前打包项目
- 加速了热更新响应速度,得到了更好的开发体验
- Vue.js 3.0 响应式系统的实现原理?
- weakMap, Map, Set
- reactive, ref, effect,
数组也可以用 in 遍历
在todo list 案例中,我觉得有收获的点:
根据hash名称创建函数,完美避开if else 语句
<ul class="filters">
<li><a href="#/all">All</a></li>
<li><a href="#/active">Active</a></li>
<li><a href="#/completed">Completed</a></li>
</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]) {
// 正确的路由跳转只有3个
type.value = hash
} else {
// 不正确的路由跳转有 路由输入错误 初始状态下没有hash 都直接转到 all hash 处理
type.value = 'all'
window.location.hash = ''
} }
// 监听hashchange事件(我不熟悉这个事件) onMounted(() => { window.addEventListener(‘hashchange’, onHashChange) onHashChange() })
onUnmounted(() => { window.removeEventListener(‘hashchange’, onHashChange) })
疑惑的点:<br />todo === editingTodo 这都是对象,怎么可以用来判断是否相等<br />我觉得还需要听一遍,这里面的逻辑对我来说很有条理,功能各司其职,需要学习它如何拆分,又如何分类这些功能的。
```vue
<template>
<section id="app" class="todoapp">
<header class="header">
<h1>todos</h1>
<input
class="new-todo"
placeholder="What needs to be done?"
autocomplete="off"
autofocus
v-model="input"
@keyup.enter="addTodo"
>
</header>
<section class="main" v-show="count">
<input id="toggle-all" class="toggle-all" v-model="allDone" type="checkbox">
<label for="toggle-all">Mark all as complete</label>
<ul class="todo-list">
<li
v-for="todo in filteredTodos"
:key="todo"
:class="{ editing: todo === editingTodo, completed: todo.completed }"
>
<div class="view">
<input class="toggle" type="checkbox" v-model="todo.completed">
<label @dblclick="editTodo(todo)">{{ todo.text }}</label>
<button class="destroy" @click="remove(todo)"></button>
</div>
<input
class="edit"
type="text"
v-editing-focus="todo === editingTodo"
v-model="todo.text"
@keyup.enter="doneEdit(todo)"
@blur="doneEdit(todo)"
@keyup.esc="cancelEdit(todo)"
>
</li>
</ul>
</section>
<footer class="footer" v-show="count">
<span class="todo-count">
<strong>{{ remainingCount }}</strong> {{ remainingCount > 1 ? 'items' : 'item' }} left
</span>
<ul class="filters">
<li><a href="#/all">All</a></li>
<li><a href="#/active">Active</a></li>
<li><a href="#/completed">Completed</a></li>
</ul>
<button class="clear-completed" @click="removeCompleted" v-show="count > remainingCount">
Clear completed
</button>
</footer>
</section>
<footer class="info">
<p>Double-click to edit a todo</p>
<!-- Remove the below line ↓ -->
<p>Template by <a href="http://sindresorhus.com">Sindre Sorhus</a></p>
<!-- Change this out with your name and url ↓ -->
<p>Created by <a href="https://www.lagou.com">教瘦</a></p>
<p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
</footer>
</template>
<script>
import './assets/index.css'
import useLocalStorage from './utils/useLocalStorage'
import { ref, computed, onMounted, onUnmounted, watchEffect } from 'vue'
const storage = useLocalStorage()
// 1. 添加待办事项
const useAdd = todos => {
const input = ref('')
const addTodo = () => {
const text = input.value && input.value.trim()
if (text.length === 0) return
todos.value.unshift({
text,
completed: false
})
input.value = ''
}
return {
input,
addTodo
}
}
// 2. 删除待办事项
const useRemove = todos => {
const remove = todo => {
const index = todos.value.indexOf(todo)
todos.value.splice(index, 1)
}
const removeCompleted = () => {
todos.value = todos.value.filter(todo => !todo.completed)
}
return {
remove,
removeCompleted
}
}
// 3. 编辑待办项
const useEdit = remove => {
let beforeEditingText = ''
const editingTodo = ref(null)
const editTodo = todo => {
beforeEditingText = todo.text
editingTodo.value = todo
}
const doneEdit = todo => {
if (!editingTodo.value) return
todo.text = todo.text.trim()
todo.text || remove(todo)
editingTodo.value = null
}
const cancelEdit = todo => {
editingTodo.value = null
todo.text = beforeEditingText
}
return {
editingTodo,
editTodo,
doneEdit,
cancelEdit
}
}
// 4. 切换待办项完成状态
const useFilter = todos => {
const allDone = computed({
get () {
return !todos.value.filter(todo => !todo.completed).length
},
set (value) {
todos.value.forEach(todo => {
todo.completed = value
})
}
})
const filter = {
all: list => list,
active: list => list.filter(todo => !todo.completed),
completed: list => list.filter(todo => todo.completed)
}
const type = ref('all')
const filteredTodos = computed(() => filter[type.value](todos.value))
const remainingCount = computed(() => filter.active(todos.value).length)
const count = computed(() => todos.value.length)
const onHashChange = () => {
const hash = window.location.hash.replace('#/', '')
if (filter[hash]) {
type.value = hash
} else {
type.value = 'all'
window.location.hash = ''
}
}
onMounted(() => {
window.addEventListener('hashchange', onHashChange)
onHashChange()
})
onUnmounted(() => {
window.removeEventListener('hashchange', onHashChange)
})
return {
allDone,
count,
filteredTodos,
remainingCount
}
}
// 5. 存储待办事项
const useStorage = () => {
const KEY = 'TODOKEYS'
const todos = ref(storage.getItem(KEY) || [])
watchEffect(() => {
storage.setItem(KEY, todos.value)
})
return todos
}
export default {
name: 'App',
setup () {
const todos = useStorage()
const { remove, removeCompleted } = useRemove(todos)
return {
todos,
remove,
removeCompleted,
...useAdd(todos),
...useEdit(remove),
...useFilter(todos)
}
},
directives: {
editingFocus: (el, binding) => {
binding.value && el.focus()
}
}
}
</script>
<style>
</style>