万事从 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,
        },
      },
相关推荐
小胖霞4 小时前
从零开始:在阿里云 Ubuntu 服务器部署 Node+Express 接口(基于公司 GitLab)
前端·后端
A_Bin4 小时前
前端工程化之【包管理器】
前端
小肚肚肚肚肚哦4 小时前
CSS 伪类函数 :where 简介
前端·css
Nick56834 小时前
Swift -- 第三方登录之微信登录 源码分享
前端
麦麦大数据4 小时前
D026 vue3+django 论文知识图谱推荐可视化系统 | vue3+vite前端|neo4j 图数据库
前端·django·vue3·知识图谱·推荐算法·论文文献·科研图谱
小肚肚肚肚肚哦4 小时前
伪元素与普通元素的层级关系问题浅析
前端·css
梦想CAD控件5 小时前
网页CAD中组(Group)功能的二次开发
前端·javascript·github
讨厌吃蛋黄酥5 小时前
🔥 JavaScript异步之谜:单线程如何实现“同时”做多件事?99%的人都理解错了!
前端·javascript·面试
华仔啊5 小时前
别再纠结Pinia和Vuex了!一篇文章彻底搞懂区别与选择
前端·vue.js