学习 vue3 从最基础开始,步步完善,最终完成✅
实现简单的todolist
jQuery思维类似这样
xml
<div>
<h2 id="app"></h2>
<input type="text" id="todo-input">
</div>
<script src="jquery.min.js"></script>
<script>
// 找到输入框,监听输入
$('#todo-input').on('input',function(){
let val = $(this).val() // 获取值
$('#app').html(val) // 找到标签,修改内容
})
</script>
Vue 思维
xml
<body>
<div id="app">
<h2>{{title}}</h2>
<input type="text" v-model="title" />
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
const App = {
data() {
return {
title: '', // 定义一个数据
}
},
}
// 启动应用
Vue.createApp(App).mount('#app')
</script>
</body>

区别在于
jQuery 时代的开发逻辑,就是我们先要找到目标元素,然后再进行对应的修改。Vue 时代不要再思考页面的元素怎么操作,而是要思考数据是怎么变化的。
如果有多个想做的事
使用 v-for 循环展示数据
xml
<body>
<div id="app">
<h2>{{ title }}</h2>
<input type="text" v-model="title" />
<ul>
<li v-for="todo in todos">{{ todo }}</li>
</ul>
</div>
<!-- 使用完整版 Vue(带模板编译器) -->
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
const App = {
data() {
return {
title: '',
todos: ['赖床', '熬夜', '要不改改?'],
}
},
}
Vue.createApp(App).mount('#app')
</script>
</body>

添加交互
xml
<body>
<div id="app">
<input type="text" v-model="title" @keydown.enter="addTodo" />
<ul>
<li v-for="todo in todos">{{todo}}</li>
</ul>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
const App = {
data() {
return {
title: '', // 定义一个数据
todos: ['赖床', '熬夜', '要不改改?'],
}
},
methods: {
addTodo() {
this.todos.push(this.title)
this.title = ''
},
},
}
// 启动应用
Vue.createApp(App).mount('#app')
</script>
</body>

勾选完成并置灰
需要加一个 是否完成状态
xml
<body>
<div id="app">
<input type="text" v-model="title" @keydown.enter="addTodo" />
<ul>
<li v-for="todo in todos">
<input type="checkbox" v-model="todo.done" />
<span :class="{done:todo.done}"> {{todo.title}}</span>
</li>
</ul>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
const App = {
data() {
return {
title: '', // 定义一个数据
todos: [
{ title: '赖床', done: true },
{ title: '熬夜', done: true },
{ title: '要不改改?', done: false },
],
}
},
methods: {
addTodo() {
this.todos.push({
title: this.title,
done: false,
})
this.title = ''
},
},
}
// 启动应用
Vue.createApp(App).mount('#app')
</script>
<style>
.done {
color: gray;
text-decoration: line-through;
}
</style>
</body>

添加已完成/未完成数量
xml
<body>
<div id="app">
<input type="text" v-model="title" @keydown.enter="addTodo" />
<ul>
<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>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
const App = {
data() {
return {
title: '', // 定义一个数据
todos: [
{ title: '赖床', done: true },
{ title: '熬夜', done: true },
{ title: '要不改改?', done: false },
],
}
},
computed: {
active() {
return this.todos.filter((v) => !v.done).length
},
all() {
return this.todos.length
},
allDone: {
get: function () {
return this.active === 0
},
set: function (val) {
this.todos.forEach((todo) => {
todo.done = val
})
},
},
},
methods: {
addTodo() {
this.todos.push({
title: this.title,
done: false,
})
this.title = ''
},
},
}
// 启动应用
Vue.createApp(App).mount('#app')
</script>
<style>
.done {
color: gray;
text-decoration: line-through;
}
</style>
</body>


条件渲染 清理按钮
xml
<button v-if="active<all" @click="clear">清理</button>
<script>
methods:{
clear(){
this.todos = this.todos.filter(v=>!v.done)
}
}
</script>

点击清理🧹后

如果全部都清理 展示暂无数据
xml
<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 v-else>暂无数据</div>

缓存数据 刷新依旧有效
javascript
const STORAGE_KEY = 'todos_v1'
mounted() {
try {
const saved = localStorage.getItem(STORAGE_KEY)
if (saved) this.todos = JSON.parse(saved)
} catch (e) {
console.warn('restore failed', e)
}
},
watch: {
todos: {
handler(list) {
localStorage.setItem(STORAGE_KEY, JSON.stringify(list))
},
deep: true,
},
},

