继续前面的学习笔记。
1. 写一个累加器组件
在 src 下的 components 目录下新建一个 Counter.vue ,并在这个文件里写出下面的代码:
<template><div><h1 @click="add">{{ count }}</h1></div>
</template><script setup>
import { ref } from 'vue';
let count = ref(0)
function add() {count.value++
}
</script><style scoped>
h1 {color: blueviolet;
}
</style>
这里使用了<script setup>
的语法,引入ref函数包裹数字,这样count变量就变成了响应式数据了。使用add修改数字的时候,要修改.value才可以。<script setup>
标签内的变量和函数,都可以在模板<template>
中直接使用。
2. 使用累加器组件
src/pages/Home.vue 组件中,使用累加器组件。方法是在<script setup>
中import Counter.vue组件,这样<script setup>
就自动把组件注册到当前组件。在模板中直接使用<Counter />
即可。
<template><h1>这是首页</h1><Counter />
</template><script setup>
import Counter from '../components/Counter.vue';
</script>
通过这种方式,可以实现对业务逻辑的复用。
3. 重构清单组件
3.1 引入ref和setup
在 src 下的 components 目录下新建一个 Todos.vue ,并在这个文件里写出下面的代码:
<template><div><input type="text" v-model="title" @keydown.enter="addTodo" /><ul v-if="todos.length"><li v-for=" todo in todos"><input type="checkbox" v-model="todo.done" /><span :class="{ done: todo.done }">{{ todo.title }}</span></li></ul></div>
</template><script setup>
import { ref } from 'vue';
let title = ref("")
let todos = ref([{ title: "学习", done: false }])
function addTodo() {todos.value.push({ title: title.value, done: false });title.value = ""
}
</script><style> .done {color: gray;text-decoration: line-through;}
</style>
和累加器组件的写法一样。使用ref包裹响应式数据。在修改响应式数据的时候,要修改.value值。
src/pages/Home.vue 组件中,使用Todos组件。
<template><h1>这是首页</h1><Counter /><Todos />
</template><script setup>
import Counter from '../components/Counter.vue';
import Todos from '../components/Todos.vue';
</script>
3.2 使用 computed 函数实现计算属性
Vue2的 computed 是组件的一个配置项,而Vue3的 computed 的用法是单独引入,并作为函数使用的。
- 使用computed函数统计未完成项目和所有项目。
- 使用函数实现全选功能。
- 使用computed函数清理已完成的项目。
<template><div><input type="text" v-model="title" @keydown.enter="addTodo" /><button v-if="active < all" @click="clear">清理</button><ul v-if="todos.length"><li v-for=" todo in todos"><input type="checkbox" v-model="todo.done" /><span :class="{ done: todo.done }">{{ todo.title }}</span></li></ul><div>全选<input type="checkbox" v-model="allDone" /><span>{{ active }} / {{ all }}</span></div></div>
</template><script setup>
import { computed, ref } from 'vue';
let title = ref("");
let todos = ref([{ title: "学习", done: false }]);
// 添加待办项
function addTodo() {todos.value.push({ title: title.value, done: false });title.value = ""
}
// 清理完成项
function clear() {todos.value = todos.value.filter((v) => !v.done);
}
// 未完成待办项
let active = computed(() => { return todos.value.filter((v) => !v.done).length; });
// 所有待办项
let all = computed(() => { return todos.value.length });
// 全选
let allDone = computed({get: function(){return active.value === 0;},set: function(value){todos.value.forEach((todo)=>{todo.done = value;});}
});
</script><style scoped>
.done {color: gray;text-decoration: line-through;}
</style>
在 style 标签上,加上 scoped 这个属性的时候,定义的 CSS 就只会应用到当前组件的元素上,这样就很好地避免了一些样式冲突的问题。
4. 使用重构后的清单组件
<template><h1>这是首页</h1><Counter /><Todos />
</template><script setup>
import Counter from '../components/Counter.vue';
import Todos from '../components/Todos.vue';
</script>
5. 把功能独立的模块封装成独立的函数
使用 Composition API 的逻辑来拆分代码,把一个功能相关的数据和方法都维护在一起。
在utils里面,我们新建了一个todos.js文件,里面定义一个函数 useTodos:
import { computed, ref } from 'vue';export function useTodos() {let title = ref("");let todos = ref([{ title: "学习", done: false }]);// 添加待办项function addTodo() {todos.value.push({ title: title.value, done: false });title.value = ""}// 清理完成项function clear() {todos.value = todos.value.filter((v) => !v.done);}// 未完成待办项let active = computed(() => { return todos.value.filter((v) => !v.done).length; });// 所有待办项let all = computed(() => { return todos.value.length });// 全选let allDone = computed({get: function () {return active.value === 0;},set: function (value) {todos.value.forEach((todo) => {todo.done = value;});}});return { title, todos, addTodo, clear, active, all, allDone };
}
这个函数就是把那些和清单相关的所有数据和方法,都放在函数内部定义并且return。注意函数要export。
Todos.vue组件入口,也就是<script setup>
中的代码,就可以变得非常简单和清爽了。只需要调用 useTodos,并且获取所需要的变量即可,具体的实现逻辑可以去 useTodos 内部维护,代码可维护性大大增强。
<script setup>
import {useTodos} from '../utils/todos'
let { title, todos, addTodo, clear, active, all, allDone } = useTodos();
</script>
Tips:
export default和export都能导出一个模块里面的常量,函数,文件,模块等,在其它文件或模块中通过import来导入常量,函数,文件或模块。这样就可以使用它们了。
在一个文件或模块中,export和import可以有多个,export default却只能有一个。
通过export方式导出,在导入的时候需要加{}大括号,export default 就不需要{}.
6. CSS 中使用 JavaScript 中的变量
script 里定义了一个响应式的 color 变量,并且在累加的时候,将变量随机修改为红或者蓝。在 style 内部,我们使用 v-bind 函数绑定 color 的值,就可以动态地通过 JavaScript 的变量实现 CSS 的样式修改。
<template><div><h1 @click="add">{{ count }}</h1></div>
</template><script setup>
import { ref } from 'vue';
let count = ref(0)
let color = ref('red') //定义了一个响应式的 color 变量
function add() {count.value++;color.value = Math.random()>0.5? "blue":"red" //随机修改为红或者蓝。
}
</script><style scoped>
h1 {color:v-bind(color); // v-bind 函数绑定 color 的值
}
</style>