vue 记事本案例详解

javascript 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="./css/index.css" />
<title>记事本</title>
</head>
<body>

<!-- 主体区域 -->
<section id="app">
  <!-- 输入框 -->
  <header class="header">
    <h1>小黑记事本</h1>
    <input v-model="todoName"  placeholder="请输入任务" class="new-todo" />
    <button @click="add" class="add">添加任务</button>
  </header>
  <!-- 列表区域 -->
  <section class="main">
    <ul class="todo-list">
      <li class="todo" v-for="(item, index) in list" :key="item.id">
        <div class="view">
          <span class="index">{{ index + 1 }}.</span> <label>{{ item.name }}</label>
          <button @click="del(item.id)" class="destroy"></button>
        </div>
      </li>
    </ul>
  </section>
  <!-- 统计和清空 → 如果没有任务了,底部隐藏掉 → v-show -->
  <footer class="footer" v-show="list.length > 0">
    <!-- 统计 -->
    <span class="todo-count">合 计:<strong> {{ list.length }} </strong></span>
    <!-- 清空 -->
    <button @click="clear" class="clear-completed">
      清空任务
    </button>
  </footer>
</section>

<!-- 底部 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
  // 添加功能
  // 1. 通过 v-model 绑定 输入框 → 实时获取表单元素的内容
  // 2. 点击按钮,进行新增,往数组最前面加 unshift
  const app = new Vue({
    el: '#app',
    data: {
      todoName: '',
      list: [
        { id: 1, name: '跑步一公里' },
        { id: 2, name: '跳绳200个' },
        { id: 3, name: '游泳100米' },
      ]
    },
    methods: {
      del (id) {
        // console.log(id) => filter 保留所有不等于该 id 的项
        this.list = this.list.filter(item => item.id !== id)
      },
      add () {
        if (this.todoName.trim() === '') {
          alert('请输入任务名称')
          return
        }
        this.list.unshift({
          id: +new Date(),
          name: this.todoName
        })
        this.todoName = ''
      },
      clear () {
        this.list = []
      }
    }
  })

</script>
</body>
</html>

一、HTML 视图层:页面结构与交互绑定

HTML 部分负责展示页面内容,并通过 Vue 指令与逻辑层的数据和方法绑定,实现 "数据驱动视图"。

1. 主体容器(<section id="app">

javascript 复制代码
<section id="app"> ... </section>
  • 作用:这是整个 Vue 应用的 "根容器",通过 Vue 实例的el: '#app'配置,将 Vue 的作用范围限定在这个元素内。
  • 所有需要 Vue 控制的标签(如绑定数据、事件)都必须放在这个容器内部。

2. 输入框区域(<header class="header">

javascript 复制代码
<header class="header">
  <h1>小黑记事本</h1>
  <input v-model="todoName" placeholder="请输入任务" class="new-todo" />
  <button @click="add" class="add">添加任务</button>
</header>
  • 功能:负责接收用户输入的新任务,并触发 "添加" 操作。
  • 核心细节:
    • <h1>:显示应用标题 "小黑记事本"。
    • <input v-model="todoName">:通过v-model实现双向数据绑定 ------ 输入框的内容会实时同步到 Vue 实例的todoName变量中,反之todoName的变化也会实时反映到输入框(后续添加任务后清空输入框就是利用这一点)。
    • <button @click="add">:通过@click(Vue 的事件绑定语法,等同于v-on:click)绑定add方法,点击按钮时会执行add方法(添加新任务)。

3. 任务列表区域(<section class="main">

javascript 复制代码
<section class="main">
  <ul class="todo-list">
    <li class="todo" v-for="(item, index) in list" :key="item.id">
      <div class="view">
        <span class="index">{{ index + 1 }}.</span> 
        <label>{{ item.name }}</label>
        <button @click="del(item.id)" class="destroy"></button>
      </div>
    </li>
  </ul>
</section>
  • 功能:展示所有任务列表,并支持删除单个任务。
  • 核心细节:
    • v-for="(item, index) in list":Vue 的列表渲染指令,遍历list数组(存储所有任务),每次循环将当前任务对象赋值给item,索引赋值给index
    • :key="item.id":key(等同于v-bind:key)是 Vue 优化列表渲染的关键,通过任务的唯一标识item.id(每个任务的id不重复),让 Vue 能精准识别每个列表项,避免更新时的 DOM 复用错误。
    • <span class="index">{``{ index + 1 }}.</span>:通过{``{ }}(插值表达式)显示任务序号,index是数组索引(从 0 开始),index + 1将序号转为从 1 开始。
    • <label>{``{ item.name }}</label>:显示任务名称,item.name是当前任务对象的name属性(如 "跑步一公里")。
    • <button @click="del(item.id)">:删除按钮,点击时调用del方法,并传入当前任务的iditem.id),用于精准删除该任务。

4. 统计与清空区域(<footer class="footer">

javascript 复制代码
<footer class="footer" v-show="list.length > 0">
  <span class="todo-count">合 计:<strong> {{ list.length }} </strong></span>
  <button @click="clear" class="clear-completed">清空任务</button>
</footer>
  • 功能:显示当前任务总数,提供 "清空所有任务" 的按钮,且当任务为空时自动隐藏。
  • 核心细节:
    • v-show="list.length > 0":条件渲染指令,当list.length > 0(即有任务)时,footer显示;当list为空时,footer隐藏(通过 CSS 的display: none实现)。
    • {``{ list.length }}:通过插值表达式显示任务总数,list.length是数组的长度(即任务数量)。
    • <button @click="clear">:清空按钮,点击时调用clear方法,删除所有任务。

二、Vue 逻辑层:数据与方法(<script>部分)

Vue 实例通过data定义数据,通过methods定义方法,实现对任务的添加、删除、清空等操作,是应用的 "大脑"。

1. Vue 实例初始化

javascript 复制代码
const app = new Vue({
  el: '#app', // 挂载到id为app的元素
  data: { ... }, // 定义数据
  methods: { ... } // 定义方法
})
  • el: '#app':指定 Vue 实例控制的 DOM 元素(即前面的<section id="app">),只有该元素内的 Vue 指令才会被解析。

2. 数据(data

javascript 复制代码
data: {
  todoName: '', // 绑定输入框的任务名称
  list: [ // 存储所有任务的数组
    { id: 1, name: '跑步一公里' },
    { id: 2, name: '跳绳200个' },
    { id: 3, name: '游泳100米' },
  ]
}
  • todoName: '':初始为空字符串,通过v-model与输入框绑定,实时存储用户输入的新任务名称。
  • list:数组类型,存储所有任务对象。每个任务对象包含:
    • id:唯一标识(用于删除时精准定位),初始值为 1、2、3(后续新增任务会自动生成唯一id)。
    • name:任务名称(如 "跑步一公里")。

3. 方法(methods

方法是实现交互逻辑的核心,通过修改data中的数据(如listtodoName),驱动视图自动更新。

(1)del(id):删除单个任务
javascript 复制代码
del(id) {
  this.list = this.list.filter(item => item.id !== id)
}
  • 作用:根据传入的id,从list数组中删除对应的任务。
  • 逻辑:
    • filter是数组方法,用于过滤数组,返回一个 "符合条件的新数组"。
    • item => item.id !== id:保留所有id不等于传入id的任务(即排除要删除的任务)。
    • this.list = ...:将过滤后的新数组赋值给list,Vue 会检测到list的变化,自动更新列表视图(删除对应的li)。
(2)add():添加新任务
javascript 复制代码
add() {
  // 1. 验证输入:如果输入为空(或仅空格),提示并终止
  if (this.todoName.trim() === '') {
    alert('请输入任务名称')
    return
  }
  // 2. 向list数组开头添加新任务
  this.list.unshift({
    id: +new Date(), // 生成唯一id(当前时间戳)
    name: this.todoName // 任务名称为用户输入的内容
  })
  // 3. 清空输入框(通过双向绑定同步到页面)
  this.todoName = ''
}
  • 作用:将用户输入的内容添加到任务列表中。
  • 逻辑分步:
    • 输入验证:this.todoName.trim() === ''判断用户是否输入了有效内容(trim()去除前后空格,避免纯空格被当作有效任务),如果无效则弹出提示并通过return终止方法(不执行后续添加逻辑)。
    • 添加任务:unshift是数组方法,向数组开头 添加新元素(新任务会显示在列表最上方)。新任务的id+new Date()生成(当前时间的时间戳,毫秒级,确保唯一),name为用户输入的this.todoName
    • 清空输入框:this.todoName = ''将绑定的输入框变量设为空,通过v-model双向绑定,页面输入框会同步清空,方便用户继续输入。
(3)clear():清空所有任务
javascript 复制代码
clear() {
  this.list = []
}
  • 作用:删除所有任务,清空列表。
  • 逻辑:将list数组赋值为空数组[],Vue 检测到list变化后,会自动清空列表视图;同时list.length变为 0,footer会通过v-show自动隐藏。

三、整体功能流程总结

  1. 初始加载:页面显示初始任务列表(3 条预设任务),底部显示统计(合计:3)和清空按钮。
  2. 添加任务 :用户在输入框输入内容(如 "读书 30 分钟"),点击 "添加任务",add方法验证输入有效后,将新任务添加到list开头,输入框自动清空,列表实时显示新任务,统计数量 + 1。
  3. 删除任务 :点击某任务后的删除按钮,del方法根据该任务的idlist中移除它,列表实时移除该任务,统计数量 - 1。
  4. 清空任务 :点击 "清空任务",clear方法将list设为空数组,列表清空,底部统计区域因list.length = 0自动隐藏。

扩展:this指向

在你提供的 Vue 代码中,this 是一个非常核心的概念,它的指向和作用直接关系到代码的正常运行。我们结合代码具体分析:

一、this 的指向:当前的 Vue 实例

在 Vue 实例的 methods 方法(如 adddel)中,this 始终指向 当前的 Vue 实例对象 (即代码中 const app = new Vue(...) 创建的那个 app 实例)。

可以简单理解为:this 就是 app 本身。例如在 add 方法中,this 和外部的 app 是同一个对象。

二、this 在代码中的具体作用

this 的核心作用是 让 Vue 实例的方法(如 adddel)能够访问和操作实例内部的数据(data)和其他资源,是连接方法与实例数据的 "桥梁"。

具体看代码中的用法:

1. 访问 data 中的数据

data 中定义的属性(如 todoNamelist)会被 Vue 代理到实例上,因此可以通过 this.属性名 直接访问。

  • 例 1:this.todoNameadd 方法中,this.todoName 访问的是 data 中定义的 todoName(与输入框通过 v-model 绑定的变量),用于获取用户输入的任务名称。

  • 例 2:this.list``this.list 访问的是 data 中定义的 list 数组(存储所有任务),用于后续添加或删除任务。

2. 修改 data 中的数据

通过 this.属性名 = 新值 可以修改 data 中的数据,而 Vue 会自动监听数据变化,同步更新页面视图(这是 Vue "数据驱动视图" 的核心特性)。

  • 例 1:this.list.unshift(...)``unshift 是数组的方法,this.list.unshift(...)list 数组的开头添加新任务对象,修改后 Vue 会自动重新渲染列表,展示新任务。

  • 例 2:this.todoName = ''在添加任务后,通过 this.todoName = '' 清空 data 中的 todoName,由于输入框与 todoName 双向绑定(v-model),页面上的输入框会同步被清空。

  • 例 3:this.list = this.list.filter(...)del 方法中,通过 filter 生成新数组并赋值给 this.list,修改后 Vue 会自动更新列表,移除被删除的任务。

3. 调用实例中的其他方法(如果有)

如果实例中定义了多个方法,this 也可以用来调用其他方法。例如:

javascript 复制代码
methods: {
  add() {
    // 调用另一个方法
    this.validateInput(); 
  },
  validateInput() {
    // 验证输入的逻辑
  }
}

三、关键注意点:为什么 this 能正确指向实例?

Vue 在初始化时,会对 methods 中的方法进行 "绑定处理",确保方法内部的 this 固定指向当前 Vue 实例,而不会因调用方式改变(例如避免在事件回调中 this 指向 window 或 DOM 元素)。

反例:如果用箭头函数定义方法(如 add: () => {}),this 会指向外部作用域(通常是 window),导致无法访问 data 中的属性(会报错 this.todoName is undefined)。因此,methods 中的方法必须用普通函数定义。

感谢大家的阅读 制作不易 麻烦各位点点关注和收藏 每天8点持续更新!!!

相关推荐
wangjialelele9 小时前
Qt中的常用组件:QWidget篇
开发语言·前端·c++·qt
乔冠宇9 小时前
vue需要学习的点
前端·vue.js·学习
用户479492835691510 小时前
同样是 #,锚点和路由有什么区别
前端·javascript
Hero_112710 小时前
在pycharm中install不上需要的包
服务器·前端·pycharm
爱上妖精的尾巴10 小时前
5-26 WPS JS宏数组元素添加删除应用
开发语言·前端·javascript·wps·js宏
是谁眉眼10 小时前
wpsapi
前端·javascript·html
谅望者10 小时前
Flexbox vs Grid:先学哪一个?CSS 布局完全指南(附可视化示例)
前端·css·html·css3·css布局·css flexbox·css grid
老华带你飞10 小时前
商城推荐系统|基于SprinBoot+vue的商城推荐系统(源码+数据库+文档)
java·前端·数据库·vue.js·spring boot·毕设·商城推荐系统
JS.Huang10 小时前
【JavaScript】Pointer Events 与移动端交互
前端·javascript