万事从 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,
        },
      },
相关推荐
wearegogog1234 小时前
基于 MATLAB 的卡尔曼滤波器实现,用于消除噪声并估算信号
前端·算法·matlab
Drawing stars4 小时前
JAVA后端 前端 大模型应用 学习路线
java·前端·学习
品克缤4 小时前
Element UI MessageBox 增加第三个按钮(DOM Hack 方案)
前端·javascript·vue.js
小二·4 小时前
Python Web 开发进阶实战:性能压测与调优 —— Locust + Prometheus + Grafana 构建高并发可观测系统
前端·python·prometheus
小沐°4 小时前
vue-设置不同环境的打包和运行
前端·javascript·vue.js
Irene19914 小时前
Vue3 <Suspense> 使用指南与注意事项
vue.js·suspense
qq_419854055 小时前
CSS动效
前端·javascript·css
烛阴5 小时前
3D字体TextGeometry
前端·webgl·three.js
acheding5 小时前
Vue3 + AntV/X6 自定义节点实践:组件化节点与事件联动
前端框架·vue
桜吹雪5 小时前
markstream-vue实战踩坑笔记
前端