Vue2 —— 学习(七)

目录

一、TodoList 案例(第一版)

(一)组件化编码流程

1.实现静态组件

2.显示动态数据 

(二)增加元素

 (三)多选框状态确定

(四)删除元素

(五)统计勾上的数据 

(六)全部勾上/取消

(七)清除完成的任务

二、总结:

(一)组件化的编码流程:

1.先拆分组件

2.实现动态组件:

(二)props 适用于

1.父组件到子组件传递数据(一层层太麻烦)

2.子组件到父组件传递数据

(三)v-model 不能绑定 props 传过来的值

(四)props 传过来的东西如果是对象

三、代码部分

(一)App.vue 

(二)MyFooter.vue 

(三)Header.vue

(四)MyItem.vue

(五)MyList.vue

(七)Main.js


一、TodoList 案例(第一版)

实现一个自定义添加项的列表 新添加的项在最上面 可以删除项 并能全选 

(一)组件化编码流程

1.实现静态组件

在我们要完成的成品页面中,抽取组件,使用组件实现静态页面

我们拆出来四个组件 先实现这四个静态组件 只考虑样式 不包含数据和动态的交互

拆分组件把四个新建四个组件到文件夹里面 然后 命名 在 App 中引入

先拆样式再拆结构,看 Html 结构都是属于哪一部分的 然后分别剪切 复制到对应的组件中,并在剪切初写上对应的组件标签

然后再拆 css 把对应的 css 结构截取出来 然会放到对应的组件中 

2.显示动态数据 

数据类型 数组对象 不能光写名字 还要有 id 什么的

数据谁用就给谁 我们给 List 

兄弟组件之间传数据 不太方便 后面会学但是我们先用一种基础的办法

所以我们把数据先把数据写到 App 中

组件间通信

(二)增加元素

父亲给儿子传:直接用 props 进行传数据就行

儿子给父亲传数据:父亲得先给儿子一个自己的函数,然后传给儿子 儿子在自己里面调用就实现了儿子给父亲传数据

兄弟间传数据:目前还办不到

先在 app 中 因为是header 想往 app 中添加数据 所以要在 app 中写个函数传给 header

<div class="todo-wrap">
        <MyHeader :addTodo="addTodo" />
        <MyList :todos="todos"/>
        <MyFooter />
      </div>
methods: {
    addTodo(todoObj) {
      this.todos.unshift(todoObj);
    },

然后在 Header 中 再写一个函数 把数据传回来

 <div class="todo-header">
    <input type="text" placeholder="请输入你的任务名称,按回车键确认"   @keyup.enter="add"/>
  </div>
 methods: {
    add(e) {
      const todoObj = { id: nanoid(), title: e.target.value, done: false };
      this.addTodo(todoObj);
    },
  },

 (三)多选框状态确定

app 中 

 <div class="todo-wrap">
        <MyHeader :addTodo="addTodo" />
        <MyList :todos="todos" :checkTodo="checkTodo"/>
        <MyFooter />
      </div>
 checkTodo(id){
      this.todos.forEach((todo)=>{
        if(todo.id === id) todo.done = !todo.done
      })
    }

MyList 中

<MyItem
      v-for="todoObj in todos"
      :key="todoObj.id"
      :todo="todoObj"
      :checkTodo="checkTodo"
    />
 props: ["todos", "checkTodo"],

 MyItem 中

   <input
        type="checkbox"
        :checked="todo.done"
        @change="handleCheck(todo.id)"
      />
 methods: {
    handleCheck(id) {
      this.checkTodo(id);
    },
  },

用 v-model 也能修改 多选框 但是不建议使用

还是 app 中写函数然后一步步引入比较好

(四)删除元素

confirm 函数是根据用户的交互来输出 布尔值是真还是假

弹个窗 确认时才会弹窗

app 文件中

 handleDelete(id) {
      if (confirm("确定删除吗")) {
        this.deleteTodo(id);
      }
    },

item 文件中

handleDelete(id) {
      if (confirm("确定删除吗")) {
        this.deleteTodo(id);
      }
    },

然后把 app 中的方法通过使用props 方法 传到 item 中即可

(五)统计勾上的数据 

模板代码

<span> <span>已完成{{doneTotal}}</span> / 全部{{todos.length}}</span>

 写在 计算函数中 返回的就是最后的 return 值 里面再加一个判断 todo.done 看是否勾上 只统计勾上的项进行计数

computed:{
    doneTotal(){
     return this.todos.reduce((pre,todo)=>pre + (todo.done ? 1 : 0),0)
    }
  }

(六)全部勾上/取消

看是否还有项如果没有项就不显示这个删除框 v-show=“total”

我们能使用 v-model 的双向绑定方式来进行绑定 能显示最开始的状态,在这个isAll 函数内部写上,如果勾上就所有都全选 ,如果取消就所有都取消

<template>
  <div class="todo-footer" v-show="total">
    <label>
      <input type="checkbox" v-model="isAll" />
    </label>
    <span>
      <span>已完成{{ doneTotal }}</span> / 全部{{ total }}</span
    >
    <button class="btn btn-danger">清除已完成任务</button>
  </div>
</template>

然后在 app 里写上一个函数 用来给所有的选项都勾上或者都取消

然后用 props 连接 

checkAllTodo(done) {
      this.todos.forEach((todo) => {
        todo.done = done;
      });
    },

(七)清除完成的任务

app 中的函数

    clearAllTodo() {
      this.todos = this.todos.filter((todo) => {
        return !todo.done;
      });
    },

footer 中的函数 先用props 引入 然后在 button 中写点击事件 使用 clearAll 方法 在其中直接调用 app 中的清除已选项的函数就行了

    clearAll() {
      this.clearAllTodo();
    },

二、总结:

(一)组件化的编码流程:

1.先拆分组件

按功能拆,命名不能和 html 中的标签冲突,实现静态界面不考虑交互

2.实现动态组件:

考虑好数据的存放位置,看数据是被一个组件用还是被一些组件用

只有一个组件用这个数据就放在它自身就行

一些组件在用,就放到他们共同的父组件上(状态提升)状态就是我们数据改变引起了页面的变化就是状态的改变

(二)props 适用于

两种情况

1.父组件到子组件传递数据(一层层太麻烦)

在父组件中  :传递的数据名 

然后直接在子组件中用 props 接收即可

2.子组件到父组件传递数据

父组件要先给子组件传递一个函数(用 props)

子组件在合适的时候调用函数 通过传参的形式把数据传过去

(三)v-model 不能绑定 props 传过来的值

v-model 是双向的,如果绑定就说明我们的输入和勾选的行为都会影响 props 传进来的值,这就不符合我们所理解的规则了 (props 不可修改)

(四)props 传过来的东西如果是对象

里面属性能修改而且不报错 但是我们不推荐这么做

三、代码部分

(一)App.vue 

<template>
  <div id="root">
    <div class="todo-container">
      <div class="todo-wrap">
        <MyHeader :addTodo="addTodo" />
        <MyList
          :todos="todos"
          :checkTodo="checkTodo"
          :deleteTodo="deleteTodo"
        />
        <MyFooter
          :todos="todos"
          :checkAllTodo="checkAllTodo"
          :clearAllTodo="clearAllTodo"
        />
      </div>
    </div>
  </div>
</template>
<script>
import MyHeader from "./components/MyHeader.vue";
import MyFooter from "./components/MyFooter.vue";
import MyList from "./components/MyList.vue";
export default {
  name: "app",
  components: {
    MyHeader,
    MyFooter,
    MyList,
  },
  data() {
    return {
      todos: [
        { id: "001", title: "吃饭", done: true },
        { id: "002", title: "喝水", done: false },
        { id: "003", title: "玩游戏", done: true },
      ],
    };
  },
  methods: {
    addTodo(todoObj) {
      this.todos.unshift(todoObj);
    },
    checkTodo(id) {
      this.todos.forEach((todo) => {
        if (todo.id === id) todo.done = !todo.done;
      });
    },
    deleteTodo(id) {
      this.todos = this.todos.filter((todo) => {
        return todo.id !== id;
      });
    },
    checkAllTodo(done) {
      this.todos.forEach((todo) => {
        todo.done = done;
      });
    },
    clearAllTodo() {
      this.todos = this.todos.filter((todo) => {
        return !todo.done;
      });
    },
  },
};
</script>

<style>
/*base*/
body {
  background: #fff;
}

.btn {
  display: inline-block;
  padding: 4px 12px;
  margin-bottom: 0;
  font-size: 14px;
  line-height: 20px;
  text-align: center;
  vertical-align: middle;
  cursor: pointer;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2),
    0 1px 2px rgba(0, 0, 0, 0.05);
  border-radius: 4px;
}

.btn-danger {
  color: #fff;
  background-color: #da4f49;
  border: 1px solid #bd362f;
}

.btn-danger:hover {
  color: #fff;
  background-color: #bd362f;
}

.btn:focus {
  outline: none;
}

.todo-container {
  width: 600px;
  margin: 0 auto;
}
.todo-container .todo-wrap {
  padding: 10px;
  border: 1px solid #ddd;
  border-radius: 5px;
}
</style>

(二)MyFooter.vue 

<template>
  <div class="todo-footer" v-show="total">
    <label>
      <input type="checkbox" v-model="isAll" />
    </label>
    <span>
      <span>已完成{{ doneTotal }}</span> / 全部{{ total }}</span
    >
    <button class="btn btn-danger" @click="clearAll">清除已完成任务</button>
  </div>
</template>

<script>
export default {
  name: "MyFooter",
  props: ["todos", "checkAllTodo", "clearAllTodo"],
  computed: {
    total() {
      return this.todos.length;
    },
    doneTotal() {
      return this.todos.reduce((pre, todo) => pre + (todo.done ? 1 : 0), 0);
    },
    isAll: {
      get() {
        return this.doneTotal === this.total && this.total > 0;
      },
      set(value) {
        this.checkAllTodo(value);
      },
    },
  },
  methods: {
    checkAll(e) {
      console.log(e.target.checked);
      this.checkAllTodo(e.target.checked);
    },
    clearAll() {
      this.clearAllTodo();
    },
  },
};
</script>

<style scoped>
/*footer*/
.todo-footer {
  height: 40px;
  line-height: 40px;
  padding-left: 6px;
  margin-top: 5px;
}

.todo-footer label {
  display: inline-block;
  margin-right: 20px;
  cursor: pointer;
}

.todo-footer label input {
  position: relative;
  top: -1px;
  vertical-align: middle;
  margin-right: 5px;
}

.todo-footer button {
  float: right;
  margin-top: 5px;
}
</style>

(三)Header.vue

<template>
  <div class="todo-header">
    <input type="text" placeholder="请输入你的任务名称,按回车键确认"   @keyup.enter="add"/>
  </div>
</template>

<script>
import { nanoid } from "nanoid";
export default {
  name: "MyHeader",
  props: ["addTodo"],
  methods: {
    add(e) {
      const todoObj = { id: nanoid(), title: e.target.value, done: false };
      this.addTodo(todoObj);
    },
  },
};
</script>

<style scoped>
/*header*/
.todo-header input {
  width: 560px;
  height: 28px;
  font-size: 14px;
  border: 1px solid #ccc;
  border-radius: 4px;
  padding: 4px 7px;
}

.todo-header input:focus {
  outline: none;
  border-color: rgba(82, 168, 236, 0.8);
  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075),
    0 0 8px rgba(82, 168, 236, 0.6);
}
</style>

(四)MyItem.vue

<template>
  <li>
    <label>
      <input
        type="checkbox"
        :checked="todo.done"
        @change="handleCheck(todo.id)"
      />
      <span>{{ todo.title }}</span>
    </label>
    <button class="btn btn-danger" @click="handleDelete(todo.id)">删除</button>
  </li>
</template>

<script>
export default {
  name: "MyItem",
  props: ["todo", "checkTodo", "deleteTodo"],
  mounted() {
    console.log(this.todo);
  },
  methods: {
    handleCheck(id) {
      this.checkTodo(id);
    },
    handleDelete(id) {
      if (confirm("确定删除吗")) {
        this.deleteTodo(id);
      }
    },
  },
};
</script>

<style scoped>
/*item*/
li {
  list-style: none;
  height: 36px;
  line-height: 36px;
  padding: 0 5px;
  border-bottom: 1px solid #ddd;
}

li label {
  float: left;
  cursor: pointer;
}

li label li input {
  vertical-align: middle;
  margin-right: 6px;
  position: relative;
  top: -1px;
}

li button {
  float: right;
  display: none;
  margin-top: 3px;
}

li:before {
  content: initial;
}

li:last-child {
  border-bottom: none;
}
li:hover {
  background-color: #ddd;
}
li:hover button {
  display: block;
}
</style>

(五)MyList.vue

<template>
  <ul class="todo-main">
    <MyItem
      v-for="todoObj in todos"
      :key="todoObj.id"
      :todo="todoObj"
      :checkTodo="checkTodo"
      :deleteTodo="deleteTodo"
    />
  </ul>
</template>

<script>
import MyItem from "./MyItem.vue";
export default {
  name: "MyList",
  components: {
    MyItem,
  },
  props: ["todos", "checkTodo","deleteTodo"],
};
</script>

<style scoped>
/*main*/
.todo-main {
  margin-left: 0px;
  border: 1px solid #ddd;
  border-radius: 2px;
  padding: 0px;
}

.todo-empty {
  height: 40px;
  line-height: 40px;
  border: 1px solid #ddd;
  border-radius: 2px;
  padding-left: 5px;
  margin-top: 10px;
}
</style>

(七)Main.js

import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

new Vue({
  el: '#app',
  render: h => h(App),

})

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/552651.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

「 网络安全常用术语解读 」漏洞利用交换VEX详解

漏洞利用交换&#xff08;Vulnerability Exploitability eXchange&#xff0c;简称VEX&#xff09;是一个信息安全领域的标准&#xff0c;旨在提供关于软件漏洞及其潜在利用的实时信息。根据美国政府发布的用例(PDF)&#xff0c;由美国政府开发的漏洞利用交换(VEX)使供应商和用…

ARM_day8:温湿度数据采集应用

1、IIC通信过程 主机发送起始信号、主机发送8位(7位从机地址1位传送方向(0W&#xff0c;1R))、从机应答、发数据、应答、数据传输完&#xff0c;主机发送停止信号 2、起始信号和终止信号 SCL时钟线&#xff0c;SDA数据线 SCL高电平&#xff0c;SDA由高到低——起始信号 SC…

密码学 | 椭圆曲线密码学 ECC 入门(一)

目录 正文 1 公共密钥密码学的兴起 2 玩具版 RSA 算法 2.1 RSA 基本原理 2.2 RSA 举例说明 1 加密 2 解密 3 不是完美的陷门函数 ⚠️ 原文地址&#xff1a;A (Relatively Easy To Understand) Primer on Elliptic Curve Cryptography ⚠️ 写在前面&#xff1…

第3章 内存管理(1)

3.1 内存管理概念 程序放入内存才能执行【缓解CPU与硬盘速度差异大的矛盾】 3.1.1 内存管理的基本原理和要求 内存管理的主要功能&#xff1a; 1.内存分配与回收2.地址转换:逻辑地址转换成物理地址3.内存空间的扩充4.内存共享5.存储保护 ①设置上下限寄存器②采用重定位寄存器…

有条件的打破IBGP水平分割----反射规则和联邦+实验举例

背景&#xff1a;在一个AS中的设备运行了BGP协议&#xff0c;那么正常应该都连接了其他的AS&#xff0c;存在EBGP邻居关系&#xff1b;又由于IBGP的水平分割规则&#xff0c;导致从外部学习到的路由传递给本地AS时&#xff0c;需要和本地AS中运行BGP协议都要建立IBGP邻居关系&a…

C++ 一些编程问题解决 (C++ some programming error solutions)

电脑配置&#xff1a;window10, 64位操作系统&#xff0c;基于x64的处理器&#xff0c;Microsoft Visual Studio Community 2019 Version 16.4.5 问题1&#xff1a;Unhandled exception at 0x00007FFDB39AA839 in TesseractLACadd1.exe: Microsoft C exception: boost::filesy…

移动端双验证码登录实现

说明&#xff1a;本文介绍如何用图形验证码短信验证码实现移动端登录思路&#xff1b; 分析 通过手机号图形验证码手机验证码实现登录的时序图如下&#xff1a; 说明&#xff1a; &#xff08;1&#xff09;用户进入登录界面&#xff0c;出现图形验证码&#xff0c;可点击图形…

外贸人寻找客户的6大锦囊 | 进出口的贸易数据服务 | 箱讯科技

一信息特征法---培养一双善于甄别的眼 1、客户的询盘&#xff0c;每个客户在写询盘时用的语言是不一样的&#xff0c;这就构成了客户语言的特征。有的朋友可能发现有的客户英语差的太狠&#xff0c;写出来的询盘很简单很搞笑。如果你一笑而过&#xff0c;那么就太可惜了。这个…

活动的生命周期

返回栈 Android是使用任务(Task)来管理活动的&#xff0c;一个任务就是一组存放在栈里的活动的集合&#xff0c;这个栈也被称作返回栈(Back Stack )。系统总是会显示处于栈顶的活动给用户 活动状态 运行状态当一个活动位于返回栈的栈顶时&#xff0c;这时活动就处于运行状态…

音乐小程序|基于微信开发音乐小程序的系统设计与实现(源码+数据库+文档)

音乐小程序目录 基于微信开发音乐小程序的系统 一、前言 二、系统设计 三、系统功能设计 小程序端&#xff1a; 后台 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xff1a;✌️大厂码农|毕设布道师…

广西建筑模板批发供应,工厂直销

随着广西地区基础设施建设的不断加速,建筑模板作为工程施工的重要辅材,其需求也在持续攀升。在众多建筑模板生产企业中,贵港市能强优品木业有限公司以其25年的丰富生产经验和卓越的产品品质,脱颖而出,成为了广西知名的建筑模板供应商。 能强优品木业公司专注于建筑模板的生产与…

mac IDEA激活 亲测有效

1、官网下载mac版本IDEA并安装 2、打开激活页面 3、下载脚本文件 链接: https://pan.baidu.com/s/1I2BqdfxSJv1A96422rflnA?pwdm494 提取码: m494 4、命令行到该界面&#xff0c;执行 sudo bash idea.sh 可能出现的问题&#xff1a; 查看sh文件&#xff0c;targetFilePath…

西瓜书学习——第一、二章笔记

[] 什么是机器学习? 研究关于“学习算法”(一类能从数据中学习出其背后潜在规律的算法)的一门学科。 PS:深度学习指的是神经网络那一类学习算法&#xff0c;因此是机器学习的子集。 假设空间和版本空间 举个栗子:假设现已收集到某地区近几年的房价和学校数量数据&#xf…

[Java EE] 多线程(二): 线程的创建与常用方法(下)

2.3 启动一个线程–>start() 之前我们已经看到了如何通过重写run()方法来创建一个线程对象,但是线程对象被创建出来并不意味着线程就开始运行了. 覆写run方法是给线程提供了所要做的事情的指令清单创建线程对象就是把干活的人叫了过来.而调用start方法,就是喊一声"行…

国产主流数据库存储类型简析

国产数据库在技术架构上主要分为集中式、基于中间件分布式和原生分布式架构&#xff0c;衍生出集中式架构和分布式架构。那么在这些部署架构中&#xff0c;从数据分布的视角来看&#xff0c;在数据库中数据分布的形态是怎样的。本文将简要分析OceanBase、PolarDB、OpenGauss、G…

【Spring】-编程式事务和声明式事务

spring中控制事务的方式有两种&#xff1a;编程式事务和声明式事务&#xff0c;今天我以两种事务出发&#xff0c;对spring中实现事务的EnableTransactionManagement和Transaction两个注解的底层原理进行讨论。 一、编程式事务 什么是编程式事务&#xff1f; 硬编码的方式实现…

牛客NC197 跳跃游戏(一)【中等 动态规划 Java、Go、PHP】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/23407eccb76447038d7c0f568370c1bd 思路 答案说的merge区间就是每个A[i]的地方能跳到的最远坐标是A[i] [i]&#xff0c; 有一个maxReach&#xff0c;遍历一遍A[i], 不断刷新MaxReach, 如果某个i 位置比maxReac…

MT3023 歌词中找单词

1.暴力 10/12 #include <bits/stdc.h> using namespace std; int n; string a[10005]; int main() {cin >> n;for (int i 0; i < n; i)cin >> a[i];string ll;cin >> ll;for (int i 0; i < n; i){string u a[i];int num 0;int j 0;for (in…

ssm056基于Java语言校园快递代取系统的设计与实现+jsp

校园快递代取系统设计与实现 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本校园快递代取系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短…

【在线OJ】雪花算法代码实现

雪花算法 用一个64比特位的long类型来作为生成id的类型&#xff0c;首先我们要了解哪些位置对应的意义&#xff0c;其中在本项目中10位的工作机器id被细分位5bit的机房id与5bit的机器id。雪花算法支持每毫秒生成2的12次方-1个id。 用一个64比特位的long类型来作为生成id的类型…