Skip to content

Commit 421e1ac

Browse files
committed
feat[ptr]: Vue2 中计算属性可以通过 set 影响原始数据
Vue3 的 computed 最佳设计只设置 get 视为是只读的快照
1 parent 50d62a8 commit 421e1ac

4 files changed

Lines changed: 80 additions & 10 deletions

File tree

Vue3/sandboxs-vite/src/components/Todos.vue

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,41 @@
1414
<!-- 通过 enter 修饰符,当回车时 -->
1515
</header>
1616
<section class="main">
17-
<input id="toggle-all" class="toggle-all" type="checkbox" />
17+
<input
18+
id="toggle-all"
19+
class="toggle-all"
20+
type="checkbox"
21+
:checked="allDoneRef"
22+
@input="setAllChecked($event.target.checked)"
23+
/>
24+
<!-- 事件源(checkbox)的勾选状态,true/false -->
1825
<!-- checkbox 是设置了背景图 ⭕️ ,然后设置了本体完全透明(点击仍是本体处理 -->
1926
<label for="toggle-all">Mark all as complete</label>
2027
<ul class="todo-list">
2128
<li
2229
class="todo"
23-
:class="{ completed: todo.completed }"
30+
:class="{ completed: todo.completed, editing: todo === nowEditing }"
2431
v-for="todo in filteredTodoRef"
2532
:key="todo.id"
2633
>
27-
<!-- li 自带类样式 completed -->
34+
<!-- li 自带类样式 completed 和 editing -->
2835
<div class="view">
2936
<input class="toggle" type="checkbox" v-model="todo.completed" />
30-
<label>{{ todo.title }}</label>
37+
<label @dblclick="() => handleDBLClick(todo)">{{
38+
todo.title
39+
}}</label>
40+
<!-- double left click -->
3141
<button class="destroy"></button>
3242
</div>
33-
<input class="edit" type="text" />
43+
<input
44+
class="edit"
45+
type="text"
46+
v-model="todo.title"
47+
@blue="doneEdit"
48+
@keyup.enter="doneEdit"
49+
@keyup.escape="() => cancelEdit(todo)"
50+
/>
51+
<!-- 双向绑定之后,todoRef 变化 => 自动执行监控副作用 todoStorage.saveTodos -->
3452
</li>
3553
</ul>
3654
</section>
@@ -68,7 +86,12 @@
6886
</template>
6987

7088
<script>
71-
import { useNewTodo, useTodoList, useFilter } from "../compositions";
89+
import {
90+
useNewTodo,
91+
useTodoList,
92+
useFilter,
93+
useEditTodo,
94+
} from "../compositions";
7295
7396
export default {
7497
setup() {
@@ -78,6 +101,7 @@ export default {
78101
todoRef,
79102
...useNewTodo(todoRef),
80103
...useFilter(todoRef),
104+
...useEditTodo(todoRef),
81105
};
82106
},
83107
};
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export { default as useCount } from './useCount'
22
export { default as useNewTodo } from './useNewTodo'
33
export { default as useTodoList } from './useTodoList'
4-
export { default as useFilter } from './useFilter'
4+
export { default as useFilter } from './useFilter'
5+
export { default as useEditTodo } from './useEditTodo'
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { ref, computed } from "vue";
2+
3+
export default function useEditTodo(TodoRef) {
4+
const nowEditing = ref(null)
5+
6+
let originCache = null // 存储原先值用于取消更改后恢复
7+
// 由于一次只有一个 nowEditing 所以只需要维护一个即可
8+
9+
const handleDBLClick = (todo) => {
10+
nowEditing.value = todo
11+
originCache = todo.title
12+
}
13+
14+
const doneEdit = () => {
15+
nowEditing.value = null
16+
}
17+
18+
const cancelEdit = (todo) => {
19+
nowEditing.value = null
20+
todo.title = originCache
21+
}
22+
23+
// 用于处理页面刷新后 :checked 样式
24+
const allDoneRef = computed(() => {
25+
var val = TodoRef.value.filter((it) => !it.completed).length === 0;
26+
return val;
27+
});
28+
29+
function setAllChecked(checked) {
30+
TodoRef.value.forEach((todo) => {
31+
todo.completed = checked;
32+
});
33+
}
34+
35+
return {
36+
nowEditing,
37+
handleDBLClick,
38+
doneEdit,
39+
cancelEdit,
40+
allDoneRef,
41+
setAllChecked,
42+
}
43+
}

Vue3/sandboxs-vite/src/compositions/useFilter.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,13 @@ export default function useFilter(todoRef) {
2626
window.removeEventListener("hashchange", onHashChange)
2727
})
2828

29-
const filteredTodoRef = computed({
30-
get() {
29+
const filteredTodoRef = computed(
30+
// {get()
31+
() => {
3132
return filter(todoRef.value, filterRef.value) // 别忘记 .value
3233
}
33-
})
34+
// }
35+
)
3436

3537
const remainingRef = computed(() => {
3638
return filter(todoRef.value, "active").length;

0 commit comments

Comments
 (0)