vue2(4)之scoped解决样式冲突/组件通信/非父子通信/ref和$refs/异步更新/.sync/事件总线/provide和inject

本文主要是介绍vue2(4)之scoped解决样式冲突/组件通信/非父子通信/ref和$refs/异步更新/.sync/事件总线/provide和inject,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

vue2

    • 一、学习目标
      • 1.组件的三大组成部分(结构/样式/逻辑)
      • 2.组件通信
      • 3.综合案例:小黑记事本(组件版)
      • 4.进阶语法
    • 二、scoped解决样式冲突
      • **1.默认情况**:
      • 2.代码演示
      • 3.scoped原理
      • 4.总结
    • 三、data必须是一个函数
      • 1、data为什么要写成函数
      • 2.代码演示
      • 3.总结
    • 四、组件通信
      • 1.什么是组件通信?
      • 2.组件之间如何通信
      • 3.组件关系分类
      • 4.通信解决方案
      • 5.父子通信流程
      • 6.父向子通信代码示例
      • 7.子向父通信代码示例
      • 8.总结
    • 五、什么是props
      • 1.Props 定义
      • 2.Props 作用
      • 3.特点
    • 六、props校验
      • 1.思考
      • 2.作用
      • 3.语法
    • 七、props校验完整写法
      • 1.语法
      • 2.代码实例
      • 3.注意
    • 八、props&data、单向数据流
      • 1.共同点
      • 2.区别
      • 3.单向数据流:
      • 4.代码演示
      • 5.口诀
    • 九、综合案例-组件拆分
      • 1.需求说明
      • 2.拆分基础组件
    • 十、综合案例-列表渲染
    • 十一、综合案例-添加功能
    • 十二、综合案例-删除功能
    • 十三、综合案例-底部功能及持久化存储
    • 十四、非父子通信-event bus 事件总线
      • 1.作用
      • 2.步骤
      • 4.总结
    • 十五、非父子通信-provide&inject
      • 1.作用
      • 2.场景
      • 3.语法
      • 4.注意
    • 十六、v-model原理
      • 1.原理:
      • 2.作用:
      • 3.注意
      • 4.v-model使用在其他表单元素上的原理
    • 十七、表单类组件封装
      • 1.需求目标
    • 十八、v-model简化代码
      • 1.目标:
      • 2.如何简化:
    • 十九、.sync修饰符
      • 1.作用
      • 2.场景
      • 3.本质
      • 4.语法
      • 5..总结
    • 二十、ref和$refs
      • 1.作用
      • 2.特点:
      • 3.语法
      • 4.注意
    • 二十一、异步更新 & $nextTick
      • 1.需求
      • 2.问题
      • 3.解决方案

一、学习目标

1.组件的三大组成部分(结构/样式/逻辑)

​ scoped解决样式冲突/data是一个函数

2.组件通信

  1. 组件通信语法
  2. 父传子
  3. 子传父
  4. 非父子通信(扩展)

3.综合案例:小黑记事本(组件版)

  1. 拆分组件
  2. 列表渲染
  3. 数据添加
  4. 数据删除
  5. 列表统计
  6. 清空
  7. 持久化

4.进阶语法

  1. v-model原理
  2. v-model应用于组件
  3. sync修饰符
  4. ref和$refs
  5. $nextTick

二、scoped解决样式冲突

在这里插入图片描述

1.默认情况

写在组件中的样式会 全局生效 → 因此很容易造成多个组件之间的样式冲突问题。

  1. 全局样式: 默认组件中的样式会作用到全局,任何一个组件中都会受到此样式的影响

  2. 局部样式: 可以给组件加上scoped 属性,可以让样式只作用于当前组件

2.代码演示

BaseOne.vue

<template><div class="base-one">BaseOne</div>
</template><script>
export default {}
</script>
<style scoped>
//默认的style样式,会作用于全局——全局样式
//加上scoped属性的style样式,只会作用于当前组件——局部样式
//组件应该有自己独立的样式,推荐加上scoped
</style>

BaseTwo.vue

<template><div class="base-one">BaseTwo</div>
</template><script>
export default {}
</script><style scoped>
</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>

3.scoped原理

  1. 当前组件内标签都被添加data-v-hash值 的属性
  2. css选择器都被添加 [data-v-hash值] 的属性选择器

最终效果: 必须是当前组件的元素, 才会有这个自定义属性, 才会被这个样式作用到

在这里插入图片描述

4.总结

  1. style的默认样式是作用到哪里的?
  2. scoped的作用是什么?
  3. style中推不推荐加scoped?

三、data必须是一个函数

1、data为什么要写成函数

一个组件的 data 选项必须是一个函数。目的是为了:保证每个组件实例,维护独立的一份数据对象。

每次创建新的组件实例,都会新执行一次data 函数,得到一个新对象。

在这里插入图片描述

2.代码演示

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></div>
</template><script>
import BaseCount from './components/BaseCount'
export default {components: {BaseCount,},
}
</script><style>
</style>

3.总结

data写成函数的目的是什么?

四、组件通信

1.什么是组件通信?

组件通信,就是指组件与组件之间的数据传递

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

2.组件之间如何通信

思考:

  1. 组件之间有哪些关系?
  2. 对应的组件通信方案有哪几类?

3.组件关系分类

  1. 父子关系
  2. 非父子关系
    在这里插入图片描述

4.通信解决方案

在这里插入图片描述

5.父子通信流程

  1. 父组件通过 props 将数据传递给子组件
  2. 子组件利用 $emit 通知父组件修改更新
    在这里插入图片描述

6.父向子通信代码示例

父组件通过props将数据传递给子组件

父组件App.vue

<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>

子组件Son.vue

<template><div class="son" style="border:3px solid #000;margin:10px">//3.渲染使用我是Son组件{{title}}</div>
</template><script>
export default {name: 'Son-Child',//2.通过props进行接收props:['title']
}
</script><style></style>

在这里插入图片描述

父向子传值步骤

  1. 给子组件以添加属性的方式传值
  2. 子组件内部通过props接收
  3. 模板中直接使用 props接收的值

7.子向父通信代码示例

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

在这里插入图片描述

子向父传值步骤

  1. $emit触发事件,给父组件发送消息通知
  2. 父组件监听$emit触发的事件
  3. 提供处理函数,在函数的性参中获取传过来的参数

8.总结

  1. 组件关系分类有哪两种
  2. 父子组件通信的流程是什么?
    1. 父向子
    2. 子向父

五、什么是props

1.Props 定义

组件上 注册的一些 自定义属性

2.Props 作用

向子组件传递数据

3.特点

  1. 可以 传递 任意数量 的prop
  2. 可以 传递 任意类型 的prop

在这里插入图片描述

六、props校验

1.思考

组件的props可以乱传吗

2.作用

为组件的 prop 指定验证要求,不符合要求,控制台就会有错误提示 → 帮助开发者,快速发现错误

3.语法

  • 类型校验
  • 非空校验
  • 默认值
  • 自定义校验

在这里插入图片描述

七、props校验完整写法

1.语法

props: {校验的属性名: {type: 类型,  // Number String Boolean ...required: true, // 是否必填default: 默认值, // 默认值validator (value) {// 自定义校验逻辑return 是否通过校验}}
},

2.代码实例

<script>
export default {// 完整写法(类型、默认值、非空、自定义校验)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}},},},
}
</script>

3.注意

1.default和required一般不同时写(因为当时必填项时,肯定是有值的)

2.default后面如果是简单类型的值,可以直接写默认。如果是复杂类型的值,则需要以函数的形式return一个默认值

八、props&data、单向数据流

1.共同点

都可以给组件提供数据

2.区别

  • data 的数据是自己的 → 随便改
  • prop 的数据是外部的 → 不能直接改,要遵循 单向数据流

3.单向数据流:

父级props 的数据更新,会向下流动,影响子组件。这个数据流动是单向的

4.代码演示

App.vue

<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){// console.log(newVal);this.count = newVal}}
}
</script><style></style>

BaseCount.vue

<template><div class="base-count"><button @click="handleSub">-</button><span>{{ count }}</span><button @click="handleAdd">+</button></div>
</template><script>
export default {// 1.自己的数据随便修改  (谁的数据 谁负责)// data () {//   return {//     count: 100,//   }// },// 2.外部传过来的数据 不能随便修改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>

在这里插入图片描述

5.口诀

谁的数据谁负责

九、综合案例-组件拆分

1.需求说明

  • 拆分基础组件
  • 渲染待办任务
  • 添加任务
  • 删除任务
  • 底部合计 和 清空功能
  • 持久化存储

2.拆分基础组件

咱们可以把小黑记事本原有的结构拆成三部分内容:头部(TodoHeader)、列表(TodoMain)、底部(TodoFooter)

十、综合案例-列表渲染

思路分析:

  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监听数据变化,持久化到本地

十四、非父子通信-event bus 事件总线

1.作用

非父子组件之间,进行简易消息传递。(复杂场景→ Vuex)

2.步骤

  1. 创建一个都能访问的事件总线 (空Vue实例)

    import Vue from 'vue'
    const Bus = new Vue()
    export default Bus
    
  2. A组件(接受方),监听Bus的 $on事件

    created () {Bus.$on('sendMsg', (msg) => {this.msg = msg})
    }
    
  3. B组件(发送方),触发Bus的$emit事件

    Bus.$emit('sendMsg', '这是一个消息')
    

    在这里插入图片描述

4.总结

1.非父子组件传值借助什么?

2.什么是事件总线

3.发送方应该调用事件总线的哪个方法

4.接收方应该调用事件总线的哪个方法

5.一个组件发送数据,可不可以被多个组件接收

十五、非父子通信-provide&inject

1.作用

跨层级共享数据

2.场景

在这里插入图片描述

3.语法

  1. 父组件 provide提供数据
export default {provide () {return {// 普通类型【非响应式】color: this.color, // 复杂类型【响应式】userInfo: this.userInfo, }}
}

2.子/孙组件 inject获取数据

export default {inject: ['color','userInfo'],created () {console.log(this.color, this.userInfo)}
}

4.注意

  • provide提供的简单类型的数据不是响应式的,复杂类型数据是响应式。(推荐提供复杂类型数据)
  • 子/孙组件通过inject获取的数据,不能在自身组件内修改

十六、v-model原理

1.原理:

v-model本质上是一个语法糖。例如应用在输入框上,就是value属性 和 input事件 的合写

<template><div id="app" ><input v-model="msg" type="text"><input :value="msg" @input="msg = $event.target.value" type="text"></div>
</template>

2.作用:

提供数据的双向绑定

  • 数据变,视图跟着变 :value
  • 视图变,数据跟着变 @input

3.注意

$event 用于在模板中,获取事件的形参

4.v-model使用在其他表单元素上的原理

不同的表单元素, v-model在底层的处理机制是不一样的。比如给checkbox使用v-model

底层处理的是 checked属性和change事件。

不过咱们只需要掌握应用在文本框上的原理即可

十七、表单类组件封装

1.需求目标

实现子组件和父组件数据的 双向绑定 (实现App.vue中的selectId和子组件选中的数据进行双向绑定)
在这里插入图片描述

十八、v-model简化代码

1.目标:

父组件通过v-model 简化代码,实现子组件和父组件数据 双向绑定

2.如何简化:

v-model其实就是 :value和@input事件的简写

  • 子组件:props通过value接收数据,事件触发 input
  • 父组件:v-model直接绑定数据
    在这里插入图片描述

十九、.sync修饰符

1.作用

可以实现 子组件父组件数据双向绑定,简化代码

简单理解:子组件可以修改父组件传过来的props值

2.场景

封装弹框类的基础组件, visible属性 true显示 false隐藏

3.本质

.sync修饰符 就是 :属性名@update:属性名 合写
在这里插入图片描述

4.语法

父组件

//.sync写法
<BaseDialog :visible.sync="isShow" />
--------------------------------------
//完整写法
<BaseDialog :visible="isShow" @update:visible="isShow = $event" 
/>

子组件

props: {visible: Boolean
},this.$emit('update:visible', false)

5…总结

1.父组件如果想让子组件修改传过去的值 必须加什么修饰符?

2.子组件要修改父组件的props值 必须使用什么语法?

二十、ref和$refs

1.作用

利用ref 和 $refs 可以用于 获取 dom 元素 或 组件实例

2.特点:

查找范围 → 当前组件内(更精确稳定)

3.语法

1.给要获取的盒子添加ref属性

<div ref="chartRef">我是渲染图表的容器</div>

2.获取时通过 $refs获取 this.$refs.chartRef 获取

mounted () {console.log(this.$refs.chartRef)
}

在这里插入图片描述
在这里插入图片描述

4.注意

之前只用document.querySelect(‘.box’) 获取的是整个页面中的盒子

二十一、异步更新 & $nextTick

1.需求

编辑标题, 编辑框自动聚焦

  1. 点击编辑,显示编辑框
  2. 让编辑框,立刻获取焦点
    在这里插入图片描述
    在这里插入图片描述

2.问题

“显示之后”,立刻获取焦点是不能成功的!

原因:Vue 是异步更新DOM (提升性能)

3.解决方案

$nextTick:等 DOM更新后,才会触发执行此方法里的函数体

语法: this.$nextTick(函数体)

this.$nextTick(() => {this.$refs.inp.focus()
})

注意:$nextTick 内的函数体 一定是箭头函数,这样才能让函数内部的this指向Vue实例

这篇关于vue2(4)之scoped解决样式冲突/组件通信/非父子通信/ref和$refs/异步更新/.sync/事件总线/provide和inject的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/955658

相关文章

504 Gateway Timeout网关超时的根源及完美解决方法

《504GatewayTimeout网关超时的根源及完美解决方法》在日常开发和运维过程中,504GatewayTimeout错误是常见的网络问题之一,尤其是在使用反向代理(如Nginx)或... 目录引言为什么会出现 504 错误?1. 探索 504 Gateway Timeout 错误的根源 1.1 后端

解决升级JDK报错:module java.base does not“opens java.lang.reflect“to unnamed module问题

《解决升级JDK报错:modulejava.basedoesnot“opensjava.lang.reflect“tounnamedmodule问题》SpringBoot启动错误源于Jav... 目录问题描述原因分析解决方案总结问题描述启动sprintboot时报以下错误原因分析编程异js常是由Ja

深度剖析SpringBoot日志性能提升的原因与解决

《深度剖析SpringBoot日志性能提升的原因与解决》日志记录本该是辅助工具,却为何成了性能瓶颈,SpringBoot如何用代码彻底破解日志导致的高延迟问题,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言第一章:日志性能陷阱的底层原理1.1 日志级别的“双刃剑”效应1.2 同步日志的“吞吐量杀手”

MySQL 表空却 ibd 文件过大的问题及解决方法

《MySQL表空却ibd文件过大的问题及解决方法》本文给大家介绍MySQL表空却ibd文件过大的问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考... 目录一、问题背景:表空却 “吃满” 磁盘的怪事二、问题复现:一步步编程还原异常场景1. 准备测试源表与数据

Python异步编程之await与asyncio基本用法详解

《Python异步编程之await与asyncio基本用法详解》在Python中,await和asyncio是异步编程的核心工具,用于高效处理I/O密集型任务(如网络请求、文件读写、数据库操作等),接... 目录一、核心概念二、使用场景三、基本用法1. 定义协程2. 运行协程3. 并发执行多个任务四、关键

解决Nginx启动报错Job for nginx.service failed because the control process exited with error code问题

《解决Nginx启动报错Jobfornginx.servicefailedbecausethecontrolprocessexitedwitherrorcode问题》Nginx启... 目录一、报错如下二、解决原因三、解决方式总结一、报错如下Job for nginx.service failed bec

SysMain服务可以关吗? 解决SysMain服务导致的高CPU使用率问题

《SysMain服务可以关吗?解决SysMain服务导致的高CPU使用率问题》SysMain服务是超级预读取,该服务会记录您打开应用程序的模式,并预先将它们加载到内存中以节省时间,但它可能占用大量... 在使用电脑的过程中,CPU使用率居高不下是许多用户都遇到过的问题,其中名为SysMain的服务往往是罪魁

MySQ中出现幻读问题的解决过程

《MySQ中出现幻读问题的解决过程》文章解析MySQLInnoDB通过MVCC与间隙锁机制在可重复读隔离级别下解决幻读,确保事务一致性,同时指出性能影响及乐观锁等替代方案,帮助开发者优化数据库应用... 目录一、幻读的准确定义与核心特征幻读 vs 不可重复读二、mysql隔离级别深度解析各隔离级别的实现差异

MySQL 数据库表操作完全指南:创建、读取、更新与删除实战

《MySQL数据库表操作完全指南:创建、读取、更新与删除实战》本文系统讲解MySQL表的增删查改(CURD)操作,涵盖创建、更新、查询、删除及插入查询结果,也是贯穿各类项目开发全流程的基础数据交互原... 目录mysql系列前言一、Create(创建)并插入数据1.1 单行数据 + 全列插入1.2 多行数据

linux安装、更新、卸载anaconda实践

《linux安装、更新、卸载anaconda实践》Anaconda是基于conda的科学计算环境,集成1400+包及依赖,安装需下载脚本、接受协议、设置路径、配置环境变量,更新与卸载通过conda命令... 目录随意找一个目录下载安装脚本检查许可证协议,ENTER就可以安装完毕之后激活anaconda安装更