vue重修004上部

news2024/11/22 19:38:39

文章目录

  • 版权声明
  • 组件的三大组成部分
    • scoped解决样式冲突
      • scoped原理
      • 2.代码演示
  • 组件data函数
    • 说明
    • 演示
  • 组件通信
    • 组件关系分类
    • 通信解决方案
    • 父子通信流程
    • 子向父通信代
  • props详解
    • props校验
    • props&data、单向数据流
  • 小黑记事本(组件版)
    • 基础组件结构
    • 需求和实现思路
    • 完整代码
      • App.vue
      • TodoHeader.vue
      • TodoBody.vue
      • TodoFoot.vue

版权声明

  • 本博客的内容基于我个人学习黑马程序员课程的学习笔记整理而成。我特此声明,所有版权属于黑马程序员或相关权利人所有。本博客的目的仅为个人学习和交流之用,并非商业用途。
  • 我在整理学习笔记的过程中尽力确保准确性,但无法保证内容的完整性和时效性。本博客的内容可能会随着时间的推移而过时或需要更新。
  • 若您是黑马程序员或相关权利人,如有任何侵犯版权的地方,请您及时联系我,我将立即予以删除或进行必要的修改。
  • 对于其他读者,请在阅读本博客内容时保持遵守相关法律法规和道德准则,谨慎参考,并自行承担因此产生的风险和责任。本博客中的部分观点和意见仅代表我个人,不代表黑马程序员的立场。

组件的三大组成部分

  • 结构、样式、逻辑
    在这里插入图片描述

scoped解决样式冲突

  • 默认情况:写在组件中的样式会 全局生效,很容易造成多个组件之间的样式冲突问题。
  1. 全局样式: 默认组件中的样式会作用到全局,任何一个组件中都会受到此样式的影响
  2. 局部样式: 可以给组件加上scoped 属性,可以让样式只作用于当前组件

scoped原理

  1. 当前组件内标签都被添加data-v-hash值 的属性
  2. css选择器都被添加 [data-v-hash值] 的属性选择器
  • 最终效果: 必须是当前组件的元素, 才会有这个自定义属性, 才会被这个样式作用到
    在这里插入图片描述

2.代码演示

  • BaseOne.vue
<template>
  <div class="base-one">
    BaseOne
  </div>
</template>

<script>
export default {

}
</script>

<style scoped>
/* 
  1.style中的样式 默认是作用到全局的
  2.加上scoped可以让样式变成局部样式

  组件都应该有独立的样式,推荐加scoped(原理)
  -----------------------------------------------------
  scoped原理:
  1.给当前组件模板的所有元素,都会添加上一个自定义属性
  data-v-hash值
  data-v-5f6a9d56  用于区分开不通的组件
  2.css选择器后面,被自动处理,添加上了属性选择器
  div[data-v-5f6a9d56]
*/
div{
  border: 3px solid blue;
  margin: 30px;
}
</style>
  • BaseTwo.vue
<template>
  <div class="base-one">
    BaseTwo
  </div>
</template>

<script>
export default {

}
</script>

<style scoped>
 div{
  border: 3px solid red;
  margin: 30px;
 }
</style>
  • App.vue
<template>
  <div id="app">
    <BaseOne></BaseOne>
    <BaseTwo></BaseTwo>
  </div>
</template>

<script>
import BaseOne from './components/BaseOne'
import BaseTwo from './components/BaseTwo'
export default {
  name: 'App',
  components: {
    BaseOne,
    BaseTwo
  }
}
</script>

组件data函数

说明

  • 在之前的基础阶段的练习中,data使用的是对象的写法,这是因为方便基础练习,全局只有唯一一个data对象
  • data对象写法
Vue.component('my-component', {
  data: {
    message: 'Hello, Vue!'
  },
  template: '<div>{{ message }}</div>'
})
  • data函数写法
Vue.component('my-component', {
  data: function () {
    return {
      count: 0
    }
  },
  template: '<div>{{ count }}</div>'
})
  • 在Vue.js中,一个组件的data选项必须是一个函数,而不是一个对象。为了确保每个组件实例都能维护独立的数据对象,避免数据共享和潜在的问题。
  • 每次创建一个新的组件实例时,Vue会调用这个函数来返回一个新的数据对象,以保证实例之间的数据隔离。
    在这里插入图片描述
Vue.component('my-component', {
  data() {
    return {
      message: 'Hello, Vue!'
    }
  },
  template: '&lt;div&gt;{{ message }}&lt;/div&gt;'
})

演示

  • BaseCount.vue
    <template>
      <div class="base-count">
        <button @click="count--">-</button>
        <span>{{ count }}</span>
        <button @click="count++">+</button>
      </div>
    </template>
    
    <script>
    export default {
      data: function () {
        return {
          count: 100,
        }
      },
    }
    </script>
    
    <style>
    .base-count {
      margin: 20px;
    }
    </style>
    
  • App.vue
<template>
  <div class="app">
    <baseCount></baseCount>
    <baseCount></baseCount>
    <baseCount></baseCount>
  </div>
</template>

<script>
import baseCount from './components/BaseCount'
export default {
  components: {
    baseCount,
  },
}
</script>
<style>
</style>

组件通信

  • 组件通信,就是指组件与组件之间的数据传递
  • 组件的数据是独立的,无法直接访问其他组件的数据。想使用其他组件的数据,就需要组件通信
    在这里插入图片描述

组件关系分类

在这里插入图片描述

通信解决方案

在这里插入图片描述

父子通信流程

  1. 父组件通过 props 将数据传递给子组件
  2. 子组件利用 $emit 通知父组件修改更新
  • 原因:再vue设定中数据是有属主的,只有创建数据其的属主组件可以修改该数据
    在这里插入图片描述

  • 父向子传值步骤:

  1. 给子组件以添加属性的方式传值
  2. 子组件内部通过props接收
  3. 模板中直接使用 props接收的值
    在这里插入图片描述
  • 父组件代码
<template>
  <div class="app" style="border: 3px solid #000; margin: 10px">
    我是APP组件
    <!-- 1.给组件标签,添加属性方式 赋值 -->
    <Son :title="myTitle"></Son>
  </div>
</template>

<script>
import Son from './components/Son.vue'
export default {
  name: 'App',
  data() {
    return {
      myTitle: '学前端',
    }
  },
  components: {
    Son,
  },
}
</script>

<style>
</style>
  • 子组件代码
<template>
  <div class="son" style="border:3px solid #000;margin:10px">
    <!-- 3.直接使用props的值 -->
    我是Son组件 {{title}}
  </div>
</template>

<script>
export default {
  name: 'Son-Child',
  // 2.通过props来接受
  props:['title']
}
</script>

<style>

</style>

子向父通信代

  • 子组件利用 $emit 通知父组件,进行修改更新

  • 子向父传值步骤

  1. $emit触发事件,给父组件发送消息通知
  2. 父组件监听$emit触发的事件
  3. 提供处理函数,在函数的形参中获取传过来的参数
    在这里插入图片描述

  • 子组件代码
<template>
  <div class="son" style="border: 3px solid #000; margin: 10px">
    我是Son组件 {{ title }}
    <button @click="changeFn">修改title</button>
  </div>
</template>

<script>
export default {
  name: 'Son-Child',
  props: ['title'],
  methods: {
    changeFn() {
      // 通过this.$emit() 向父组件发送通知
      this.$emit('changTitle','son')
    },
  },
}
</script>

<style>
</style>
  • 父组件代码
<template>
  <div class="app" style="border: 3px solid #000; margin: 10px">
    我是APP组件
    <!-- 2.父组件对子组件的消息进行监听 -->
    <Son :title="myTitle" @changTitle="handleChange"></Son>
  </div>
</template>

<script>
import Son from './components/Son.vue'
export default {
  name: 'App',
  data() {
    return {
      myTitle: 'father',
    }
  },
  components: {
    Son,
  },
  methods: {
    // 3.提供处理函数,提供逻辑
    handleChange(newTitle) {
      this.myTitle = newTitle
    },
  },
}
</script>

<style>
</style>

props详解

  • 在Vue.js中,props(属性)是一种用于从父组件向子组件传递数据的机制。
  • props 定义:组件上 注册的一些 自定义属性
  • props 作用:向子组件传递数据
  • 特点
    1. 可以 传递 任意数量 的prop
    2. 可以 传递 任意类型 的prop

在这里插入图片描述

props校验

  • 作用:为组件的 prop 指定验证要求,不符合要求,控制台就会有错误提示 → 帮助开发者,快速发现错误
  • 语法:
    ① 类型校验
    ② 非空校验
    ③ 默认值
    ④ 自定义校验
  • 基础写法:
    在这里插入图片描述
  • 完整写法
    在这里插入图片描述
  • default和required一般不同时写(因为当时必填项时,肯定是有值的)
  • default后面如果是简单类型的值,可以直接写默认。如果是复杂类型的值,则需要以函数的形式return一个默认值
props: {
    w: {
      type: Number,
      required: true,
      default: 0,
      validator(val) {
        // console.log(val)
        if (val >= 100 || val <= 0) {
          console.error('传入的范围必须是0-100之间')
          return false
        } else {
          return true
        }
      },
    },
  }

props&data、单向数据流

  • 共同点:都可以给组件提供数据

  • 区别

    • data 的数据是自己的 → 随便改
    • prop 的数据是外部的 → 不能直接改,要遵循 单向数据流
  • 单向数据流:父级props 的数据更新,会向下流动,影响子组件。这个数据流动是单向的
    在这里插入图片描述

  • 父组件代码

<template>
  <div class="app">
    <BaseCount :count="count" @changeCount="handleChange"></BaseCount>
  </div>
</template>

<script>
import BaseCount from './components/BaseCount.vue'
export default {
  components:{
    BaseCount
  },
  data(){
    return {
      count:100
    }
  },
  methods:{
    handleChange(newVal){
      this.count = newVal
    }
  }
}
</script>

<style>

</style>
  • 子组件代码
<template>
  <div class="base-count">
    <button @click="handleSub">-</button>
    <span>{{ count }}</span>
    <button @click="handleAdd">+</button>
  </div>
</template>

<script>
export default {
  props: {
    count: {
      type: Number,
    },
  },
  methods: {
    handleSub() {
      this.$emit('changeCount', this.count - 1)
    },
    handleAdd() {
      this.$emit('changeCount', this.count + 1)
    },
  },
}
</script>

<style>
.base-count {
  margin: 20px;
}
</style>

小黑记事本(组件版)

基础组件结构

在这里插入图片描述

需求和实现思路

需求说明:
① 拆分基础组件
② 渲染待办任务
③ 添加任务
④ 删除任务
⑤ 底部合计 和 清空功能
⑥ 持久化存储


  • 列表渲染思路分析:
  1. 提供数据:提供在公共的父组件 App.vue
  2. 通过父传子,将数据传递给TodoMain
  3. 利用v-for进行渲染

  • 添加功能思路分析:
  1. 收集表单数据 v-model
  2. 监听时间 (回车+点击 都要进行添加)
  3. 子传父,将任务名称传递给父组件App.vue
  4. 父组件接受到数据后 进行添加 unshift(自己的数据自己负责)

  • 删除功能思路分析:
  1. 监听时间(监听删除的点击)携带id
  2. 子传父,将删除的id传递给父组件App.vue
  3. 进行删除 filter (自己的数据自己负责)

  • 底部功能及持久化存储思路分析:
  1. 底部合计:父组件传递list到底部组件 —>展示合计
  2. 清空功能:监听事件 —> 子组件通知父组件 —>父组件清空
  3. 持久化存储:watch监听数据变化,持久化到本地

完整代码

App.vue

<template>
  <!-- 主体区域 -->
  <section id="app">
    <TodoHeader @add="handleAdd"></TodoHeader>
    <TodoBody :list="list" @del="handleDel"></TodoBody>
    <TodoFoot :len="list.length" @clear="handleClear"></TodoFoot>
  </section>
</template>

<script>
import TodoHeader from "@/components/TodoHeader";
import TodoBody from "@/components/TodoBody";
import TodoFoot from "@/components/TodoFoot";


// 渲染功能:
// 1.提供数据: 提供在公共的父组件 App.vue
// 2.通过父传子,将数据传递给TodoMain
// 3.利用 v-for渲染

// 添加功能:
// 1.手机表单数据  v-model
// 2.监听事件(回车+点击都要添加)
// 3.子传父,讲任务名称传递给父组件 App.vue
// 4.进行添加 unshift(自己的数据自己负责)
// 5.清空文本框输入的内容
// 6.对输入的空数据 进行判断

// 删除功能
// 1.监听事件(监听删除的点击) 携带id
// 2.子传父,讲删除的id传递给父组件的App.vue
// 3.进行删除filter(自己的数据 自己负责)

// 底部合计:父传子  传list.length 渲染
// 清空功能:子传父  通知父组件 → 父组件进行更新
// 持久化存储:watch深度监视list的变化 -> 往本地存储 ->进入页面优先读取本地数据

export default {
  components:{
    TodoHeader,
    TodoBody,
    TodoFoot
  },
  data () {
    return {
      //优先从本地存储读取
      list: JSON.parse(localStorage.getItem('list')) || [
        {id:1, name: "干饭"},
        {id:2, name: "干饭"},
        {id:3, name: "干饭"}
      ]
    }
  },
  methods:{
    handleAdd(newVal) {
      //console.log(newVal)
      this.list.unshift({
        id: +new Date(),
        name: newVal
      }
      )
    },
    handleDel(id) {
      this.list=this.list.filter(item=> item.id!==id)
    },
    handleClear() {
      this.list=[]
    }
  },
  watch:{
    list:{
      deep: true,
      handle(newValue) {
        localStorage.setItem('list',JSON.stringify(newValue))
      }
    }
  }
}
</script>

<style>

</style>

TodoHeader.vue

<template>
  <!-- 输入框 -->
  <header class="header">
    <h1>小黑记事本</h1>
    <input placeholder="请输入任务" class="new-todo"  v-model="todoname" @keyup.enter="handleAdd"/>
    <button class="add" @click="handleAdd">添加任务</button>
  </header>

</template>

<script>
export default {
  name: "TodoHeader",
  data() {
    return{
      todoname: ''
    }
  },
  methods:{
    handleAdd() {
      if(this.todoname.trim()===''){
        alert("任务名称为空")
        return
      }
      this.$emit("add",this.todoname)
      this.todoname=''
    }
  }
}

</script>

<style scoped>

</style>

TodoBody.vue

<template>
  <!-- 列表区域 -->
  <section class="main">
    <ul v-for="(item,index) in list" :key="item.id" class="todo-list">
      <li class="todo">
        <div class="view">
          <span class="index">{{index+1}}.</span> <label>{{item.name}}</label>
          <button class="destroy" @click="handeleDel(item.id)"></button>
        </div>
      </li>
    </ul>
  </section>
</template>

<script>
export default {
  name: "TodoBody",
  props: {
    list: {
      type: Array
    }
  },
  methods:{
    handeleDel(id) {
      this.$emit('del',id)
    }
  }
}
</script>

<style scoped>

</style>

TodoFoot.vue

<template>
  <!-- 统计和清空 -->
  <footer class="footer">
    <!-- 统计 -->
    <span class="todo-count">合 计:<strong> {{len}} </strong></span>
    <!-- 清空 -->
    <button class="clear-completed" @click="clear">
      清空任务
    </button>
  </footer>

</template>

<script>
export default {
  name: "TodoFoot",
  props:{
    len: Number
  },
  methods:{
    clear() {
      this.$emit('clear')
    }
  }
}
</script>

<style scoped>

</style>

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【AI处理器组合】python实现-附ChatGPT解析

1.题目 AI处理器组合 知识点数组 时间限制:1s 空间限制: 256MB 限定语言:不限 题目描述: 某公司研发了一款高性能AI处理器。每台物理设备具备8颗AI处理器,编号分别为0、1、2、3、4、5、6、7。编号0-3的处理器处于同一个链路中,编号4-7的处理器处于另外一个链路中,不通链路中…

【计算机网络笔记九】I/O 多路复用

阻塞 IO 和 非阻塞 IO 阻塞 I/O 和 非阻塞 I/O 的主要区别&#xff1a; 阻塞 I/O 执行用户程序操作是同步的&#xff0c;调用线程会被阻塞挂起&#xff0c;会一直等待内核的 I/O 操作完成才返回用户进程&#xff0c;唤醒挂起线程非阻塞 I/O 执行用户程序操作是异步的&#xf…

阿里云PolarDB数据库详细介绍_3分钟看懂

阿里云PolarDB数据库是阿里巴巴自研的关系型分布式云原生数据库&#xff0c;PolarDB兼容三种数据库引擎&#xff1a;MySQL、PostgreSQL、Oracle&#xff08;语法兼容&#xff09;&#xff0c;目前提供云原生数据库PolarDB MySQL版、云原生数据库PolarDB PostgreSQL版和云原生数…

简单聊聊 TCP 协议

简单聊聊 TCP 协议 如何实现可靠传输 ?完全可靠存在比特差错存在丢包流水线可靠数据传输协议回退N步 (GBN)选择重传 (ARQ) 小结 TCPTCP 连接报文段结构序号和确认号 可靠数据传输避免重传超时时间加倍快速重传回退N步还是选择重传 流量控制连接管理拥塞控制拥塞原因拥塞控制方…

国庆10.03

运算符重载 代码 #include <iostream> using namespace std; class Num { private:int num1; //实部int num2; //虚部 public:Num(){}; //无参构造Num(int n1,int n2):num1(n1),num2(n2){}; //有参构造~Num(){}; //析构函数const Num operator(const Num &other)co…

想用ChatGPT写申请文书?那你肯定会被拒!

美国总统乔拜登&#xff08;Joe Biden&#xff09;、诗人TS艾略特&#xff08;T. S. Eliot&#xff09;和历史学家斯蒂芬安布罗斯&#xff08;Stephen Ambrose&#xff09;&#xff0c;他们的名字都曾与抄袭事件联系在一起。 其中&#xff0c;艾略特的抄袭行为是在他去世后才被…

A3纸内容分2页打在A4纸上

需求&#xff1a;文档是A3纸大小&#xff0c;因为打印机只能打A4纸&#xff0c;需要将内容分2页打在A4纸上。 网上搜索了一圈&#xff0c;可行解决方案如下&#xff1a; 1、打印纸的输出改成2分A4文件&#xff0c;首先设置打印输出的文档是A4纸大小&#xff0c;如图&#xff…

维基百科启用HTTPS的全球影响

2015 年 6 月&#xff0c;维基媒体基金会宣布维基百科默认启用 HTTPS&#xff0c;基金会称此举旨在保护访问者的隐私和安全&#xff0c;让用户能安全和不被审查的自由获取知识。在没有启用 HTTPS 的年代&#xff0c;审查者能知道访问者访问了维基百科上的哪些条目&#xff0c;它…

阿里云数据库RDS有哪些?细数关系型数据库大全

阿里云RDS关系型数据库大全&#xff0c;关系型数据库包括MySQL版、PolarDB、PostgreSQL、SQL Server和MariaDB等&#xff0c;NoSQL数据库如Redis、Tair、Lindorm和MongoDB&#xff0c;阿里云百科分享阿里云RDS关系型数据库大全&#xff1a; 目录 阿里云RDS关系型数据库大全 …

项目实训 文章评论

1.需求实现 以下功能&#xff1a; 1&#xff09;基本增删改查API 2&#xff09;根据文章id查询评论 3&#xff09;评论点赞 数据库&#xff1a;articledb 2 文章微服务模块搭建 &#xff08;1&#xff09;搭建项目工程article&#xff0c;并设置pom.xml引入依赖&#xff…

阿里云数据库大全_3分钟看懂阿里云RDS和NoSQL数据库汇总

阿里云数据库大全&#xff1a;RDS关系型数据库如MySQL版、PolarDB、PostgreSQL、SQL Server和MariaDB等&#xff0c;NoSQL数据库如Redis、Tair、Lindorm和MongoDB&#xff0c;数据仓库如AnalyticDB MySQL版、PostgreSQL、ClickHouse&#xff0c;阿里云还提供数据库管理工具如数…

leetcode 习题集 【9月】

leetcode 习题集 [9月] 回溯 77. 组合 class Solution { private:vector<vector <int>> result;vector<int> path;// path用来存放符合条件的结果 void backtracking(int n, int k, int startIndex){if(path.size() k){result.push_back(path);return;…

常用的分布式ID解决方案原理解析

目录 前言 一&#xff1a;分布式ID的使用场景 二&#xff1a;分布式ID设计的技术指标 三&#xff1a;常见的分布式ID生成策略 3.1 UUID 3.2 数据库生成 3.3 数据库的多主模式 3.4 号段模式 3.5 雪花算法 前言 分布式ID的生成是分布式系统中非常核心的基础性模块&#…

【翻译工具】如何复活谷歌翻译之二

&#x1f41a;作者简介&#xff1a;花神庙码农&#xff08;专注于Linux、WLAN、TCP/IP、Python等技术方向&#xff09;&#x1f433;博客主页&#xff1a;花神庙码农 &#xff0c;地址&#xff1a;https://blog.csdn.net/qxhgd&#x1f310;系列专栏&#xff1a;善假于物&#…

使用canal和openfire实现Mysql的实时数据订阅

文章目录 1、Openfire插件接收binlog数据1.1、创建用户组1.2、接口实现 2、Canal客户端开发3、Smack消息客户端实现。 mysql的binlog的实时数据订阅 &#xff08;1&#xff09; canal安装与客户端使用 &#xff08;2&#xff09; openfire 4.7.5 Web插件开发 &#xff08;3&a…

gitee提交代码Commit和Push时窗口不小心关了,怎么继续推送提交?

gitee提交代码Commit和Push时窗口不小心关了&#xff0c;怎么继续推送提交&#xff1f; 一、commit关了解决办法 二、Push关了解决办法 一、commit关了 在我们使用gitee提交代码时&#xff0c;原本是commit或push但不小心按到ok关了&#xff0c;导致代码提交失败。 解决办法…

分享73个Python源代码总有一个是你想要的

分享73个Python源代码总有一个是你想要的 下载链接&#xff1a;https://pan.baidu.com/s/15qO16Vdcy6BxK5AzbXFpOw?pwd8888 提取码&#xff1a;8888 AI悦创Python小项目代码 AI视频创作ffmpegopenai-whispertts flask大屏展示Python项目 flask框架下的前后端分离的房屋租…

关于字符拼接

当然&#xff0c;以下是加入了幽默注释的代码和对应的逻辑树&#xff1a; # 提示用户输入input和txt内容&#xff0c;期待用户真有输入 input_text input("请输入input文本&#xff1a;") # 好了&#xff0c;快点输入吧 txt_text input("请输入txt文本&#…

OpenGLES:绘制一个彩色、旋转的3D圆柱

一.概述 上一篇博文讲解了怎么绘制一个彩色旋转的立方体 这一篇讲解怎么绘制一个彩色旋转的圆柱 圆柱的顶点创建主要基于2D圆进行扩展&#xff0c;与立方体没有相似之处 圆柱绘制的关键点就是将圆柱拆解成&#xff1a;两个Z坐标不为0的圆 一个长方形的圆柱面 绘制2D圆的…

不做静态化,当部署到服务器上的项目刷新出现404【已解决】

当线上项目刷新出现404页面解决方法&#xff1a; 在nginx配置里加入这样一段代码 try_files $uri $uri/ /index.html; 它的作用是尝试按照给定的顺序访问文件 变量解释 try_files 固定语法 $uri 指代home文件(ip地址后面的路径&#xff0c;假如是127.0.0.1/index/a.png&…