万事从 todolist 开始

学习 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,
        },
      },
相关推荐
问心无愧05136 分钟前
ctf show web 178
前端·笔记
岁岁种桃花儿8 分钟前
Vue组件化编程第二篇:非单位件组件
前端·javascript·vue.js
晓得迷路了12 分钟前
栗子前端技术周刊第 146 期 - React 19.3、jQuery 1.0 20 周年、Bun 1.4.2...
前端·javascript·react.js
雪芽蓝域zzs12 分钟前
第四十四节:封装通用表格多选、批量操作组合式函数
前端·javascript·vue.js
ljt272496066113 分钟前
Vue笔记--路由
javascript·vue.js·笔记
那年窗外下的雪.17 分钟前
AIDC 学习日志|第 25 天|设备输出反推、MAC Flapping 与 EAD 撤销
前端·网络·git·学习·macos
IT_陈寒17 分钟前
Vite的HMR怎么突然罢工了?原来是我漏了这个配置
前端·人工智能·后端
柳杉28 分钟前
从调研到闭环,我用 GPT-Image-2.5 和 GPT-6 Astra 把智慧厂房 3D 大屏这条链路走完了
前端·ai编程·数据可视化
芳心粽伙饭29 分钟前
CSS第四章 布局
前端·css·html
CoderYanger33 分钟前
Java EE 进阶:2.3 JavaScript 综合案例
java·前端·javascript·css·职场和发展·java-ee·html