第八单元(组件通信 子父,父子组件通信 自定义事件 事件修饰符 v-model props验证 )

#课程目标

  1. 掌握使用props让父组件给子组件传参(重点)

  2. 掌握props属性的使用以及prop验证的常用规则

  3. 掌握使用自定义事件让子组件给父组件传参(重点)

  4. 了解v-model在组件中的绑定原理,掌握组件的v-model的绑定

  5. 熟悉常用的表单修饰符、事件修饰符、键盘修饰符

#知识点

#1.组件间的通信方式

#1.1父组件给子组件传递数据--使用props属性

​ 在父组件中动态绑定自定义的props属性来传递的数据,Parent.vue如下:

<template>
<div>
Parent
<br />
<Children :pmsg='msg'></Children>
</div>
</template>
<script>
import Children from './Children'
export default {
name: 'Parent',
data () {
return {
msg:'我是父组件的数据'
}
},
components:{
Children
}
}
</script>


​ 代码所示中的:pmsg(:是vue指令v-bind的缩写)则是绑定的自定义props属性名称,msg则是父组件想要给子组件传递的数据

​ 在子组件中使用 props 选项去接收来自父组件传递过来的数据 ,Children.vue示例代码如下:

<template>
<div>
Children
<br />
{{pmsg}}
</div>
</template> <script>
export default {
name: 'Children',
//通过props来去接收父组件传递的值
props:['pmsg'],
data () {
return { }
}
}
</script>
 

​ 代码中要使用父亲传过来的参数,首先要在props中先定义父亲传过来的props属性名称,然后就可以在页面中使用父亲传过来的数据了,在此案例中,pmsg就是父组件的传到子组件中的数据了。

​ 注意,由于HTML特性是不区分大小写的,所以传递属性值时,如果想传递驼峰参数,pMsg应该转换成 kebab-case (短横线隔开式):p-msg='msg'。如:

//父组件传值时  想要传pMsg  应该这样写
<Children :p-msg='msg'></Children>
//子组件接收的是驼峰
props:['pMsg']
 

关于props

  • 可以使用v­-bind动态绑定父组件来的内容
  • 在组件中使用props来从父组件接收参数,注意,在props中定义的属性,都可以在子组件中直接使用
  • props来自父级,而组件中data return的数据就是组件自己的数据,两种情况作用域就是组件本身,可以在template,computed,methods中直接使用
  • props的值有两种,一种是字符串数组,一种是对象
  • 对于数组或对象类型的 prop 来说,在子组件中改变这个对象或数组本身将会影响到父组件的状态(尽可能将父子组件解耦,避免子组件无意中修改了父组件的状态)
#1.2 Prop验证

​ 我们可以给组件的props属性添加验证,当传入的数据不符合要求时,Vue会发出警告。

    props: {
// 基础类型检测 (`null` 意思是任何类型都可以)
propA: Number,
// 多种类型
propB: [String, Number],
// 必传且是字符串
propC: {
type: String,
required: true
},
// 数字,有默认值
propD: {
type: Number,
default: 100
},
// 数组/对象的默认值应当由一个工厂函数返回
propE: {
type: Object,
default: function () {
return { message: 'hello' }
}
},
// 自定义验证函数
propF: {
validator: function (value) {
return value > 10
}
}
}
 

type 可以是下面原生构造器:

  • String
  • Number
  • Boolean
  • Function
  • Object
  • Array
  • Symbol

​ type 也可以是一个自定义构造器函数,使用 instanceof 检测。

<template>
<div>
<div>名字: {{ person-prop.name }}, 年龄: {{ person-prop.age }} </div>
</div>
</template>
<script>
// 自定义Person构造器 这个可以定义在外边引进来,这里只是方便教材描写演示
function Person(name, age) {
this.name = name
this.age = age
}
export default {
name: 'Children',
//通过props来去接收父组件传递的值
//如果传过来的不是Person类型会报错,比如:1,'str',等等的其他类型...
props: {
person-prop: {
type: Person // 指定类型
}
},
data () {
return { }
}
}
</script>
 
#1.3 子组件给父组件传递数据--使用自定义事件

​ 父组件使用props传递数据给子组件,子组件怎么跟父组件通信呢?这时,Vue的自定义事件就派上用场了。接下来我们将学习Vue自定义事件。

​ 每个 Vue 实例都实现了事件接口 (Events interface),即:使用 $on(eventName) 监听事件、 使用 $emit(eventName) 触发事件。

父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。

也就是说:子组件用 $emit() 来触发事件 ,父组件用 v-on来 监听子组件的事件 。

注意:不能用 $on 侦听子组件抛出的事件,而必须在模板里直接用 v-on 绑定。

第一步:在子组件中触发$emit自定义事件。(第一个参数是事件名,后边的参数是要传递的数据 )

//smsg 是自定义事件的名称
//和原生的click,change,keyup等等类似
//上面几个分别是 点击事件的名称、数据变动事件的名称、键盘抬起事件的名称
//data是想要传递的数据
this.$emit('smsg',data)
 

第二步:在父组件中监听自定义事件中来接收子组件的参数

//监听原生的click事件  是@click
//那么监听自定义事件 也是如此 @smsg
//getMsg是函数
//这个函数中如果有值的传递,必须传递$event参数 $event就是子组件中传递过来的data
//所以可以有两种方式写
<Children @smsg="getMsg"></Children>
//或者
<Children @smsg="getMsg($event)"></Children>
 

子组件Children.vue具体代码:

<template>
<div class="cc">
Children
<br />
<button @click="clickMe">点击我</button>
</div>
</template>
<script>
export default {
name: 'Children',
data () {
return {
msg:'我是子组件的数据'
}
},
methods:{
clickMe(){
//子组件中先触发这个emit事件
this.$emit('smsg',this.msg);
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.cc{
height: 100px;
background-color: red;
}
</style>
 

父组件Parent.vue具体代码:

<template>
<div class="pp">
Parent--{{msg}}
<br />
<Children @smsg="getMsg"></Children>
<!--也可以这样写-->
<!--<Children @smsg="getMsg($event)"></Children>-->
</div>
</template>
<script>
import Children from './Children'
export default {
name: 'Parent',
data () {
return {
msg:'我是没有改变之前的数据'
}
},
methods:{
//this.$emit('smsg',this.msg);
//data这个参数 指的就是子组件中 this.msg
getMsg(data){
//console.log(msg)
this.msg = data;
}
},
components:{
Children
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.pp{
height: 500px;
background-color: pink;
}
</style>
 
#1.4 在组件中使用 v-model

一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件。

我们可以使用v-model来去绑定组件,试试怎么实现组件间的传值。

首先我们得知道v-model的绑定原理:

//正常表单绑定v-model
//data中的msg会随着input中的值变化而变化 也就是双向绑定
<input type="text" v-model="msg" /> //不使用v-model完成数据的双向绑定
<input type="text" @input="msg=$event.target.value" :value="msg" />
 

​ 通过上述的代码,我们已经明白了v-model的绑定原理,那么如果我们想给一个子组件上的input与父组件的某个数据做一个双向数据绑定,我们该怎么做呢?(Children组件,假定这个组件有一个input元素)

//如果这样绑定这个v-model指令
<Children v-model="msg"></Children> //根据之前的原理剖析,上面这个代码可以转换成:
<Children @input="msg=$event.target.value" :value="msg"></Children>
 

思考:这么写对不对呢?

我们再看子组件Children.vue中的部分代码:

<template>
<div>
//如果想要作为双向绑定,那么子组件中的值就应该往父组件中传,这里就要用到$emit去自定义事件
//因为父组件是使用input来监听,那么我们就应该使用自定义'input'的事件触发 这里是和原生input同名而已
//并把当前value值传给父组件
<input type="text" @input="$emit('input',$event.target.value)" :value="value" />
</div>
</template> //既然父组件传了prop名为value的的值,那么props中应该定义一个value
props:['value']
 

写到这里我们打开浏览器会发现,我们并没有实现双向绑定,为什么呢?

我们再回顾一下,在讲父组件监听自定义事件的时候,说过参数$event就是子组件传回来的参数。

那么,在父组件中,我们应该改为:

<Children @input="msg=$event" :value="msg"></Children>
 

到此为止,我们就实现了父组件与子组件中表单元素的双向绑定

#2.修饰符

#2.1表单修饰符

(1).lazy

在默认情况下,v-model 在每次 input 事件触发后将输入框的值与数据进行同步。你可以添加 lazy 修饰符,从而转变为使用 change 事件进行同步。

如下,示例:

<!-- 在“change”时而非“input”时更新 -->
<input v-model.lazy="msg" />
 

(2).number

如果想自动将用户的输入值转为数值类型,可以给 v-model 添加 number 修饰符。

如下,示例:

<input v-model.number="age" />
 

(3).trim

如果要自动过滤用户输入的首尾空白字符,可以给 v-model 添加 trim 修饰符。

如下,示例:

<input v-model.trim="msg" />
 
#2.2事件修饰符

在Vue中,事件修饰符处理了许多DOM事件的细节,让我们不再需要花大量的时间去处理这些烦恼的事情,而能有更多的精力专注于程序的逻辑处理。在Vue中事件修饰符主要有:

  • .stop:等同于JavaScript中的event.stopPropagation(),防止事件冒泡
  • .prevent:等同于JavaScript中的event.preventDefault(),防止执行预设的行为(如果事件可取消,则取消该事件,而不停止事件的进一步传播)
  • .capture:与事件冒泡的方向相反,事件捕获由外到内
  • .self:只会触发自己范围内的事件,不包含子元素
  • .once:只会触发一次

.stop:等同于JavaScript中的event.stopPropagation(),防止事件冒泡

<div id="app">
  <div class="outeer" @click.stop="outer">
    <div class="middle" @click.stop="middle">
      <button @click.stop="inner">点击我</button>
    </div>
  </div>
</div>
 

.prevent取消默认事件

.prevent等同于JavaScript的event.preventDefault(),用于取消默认事件。

<!--不会跳转到另外一个页面-->
<a href="https://www.baidu.com" @click.prevent="clickMe"></a>
 

.capture 捕获事件

捕获事件:嵌套两三层父子关系,然后所有都有点击事件,点击子节点,就会触发从外至内 父节点 ==>子节点的点击事件

<div class="outeer" @click.capture="outer">
<div class="middle" @click.capture="middle">
<button @click.capture="inner">点击我</button>
</div>
</div>
 

.self

修饰符.self只会触发自己范围内的事件,不会包含子元素。

<div class="outeer" @click.self="outer">
<div class="middle" @click.self="middle">
<button @click.stop="inner">点击我</button>
</div>
</div>
 

.once 只执行一次点击

如果我们在@click事件上添加.once修饰符,只要点击按钮只会执行一次。

#2.3键盘修饰符

在JavaScript事件中除了前面所说的事件,还有键盘事件,也经常需要监测常见的键值。在Vue中允许v-on在监听键盘事件时添加关键修饰符。记住所有的keyCode比较困难,所以Vue为最常用的键盘事件提供了别名:

  • .enter:回车键
  • .tab:制表键
  • .delete:含deletebackspace
  • .esc:返回键
  • .space: 空格键
  • .up:向上键
  • .down:向下键
  • .left:向左键
  • .right:向右键

#授课思路

#案例和作业

使用组件方式实现弹窗

vue第八单元(组件通信 子父,父子组件通信 自定义事件 事件修饰符 v-model props验证 )的更多相关文章

  1. react第六单元(react组件通信-父子组件通信-子父组件通信-跨级组件的传参方式-context方式的传参)

    第六单元(react组件通信-父子组件通信-子父组件通信-跨级组件的传参方式-context方式的传参) #课程目标 1.梳理react组件之间的关系 2.掌握父子传值的方法 3.掌握子父传值的方法 ...

  2. 组件基础(非父子组件传值)—Vue学习笔记

    最近几天忙着写Api去了,抽空把后面的内容下出来,然后再分享给大家web可以使用的api. 上次说了父子组件直接的传值,这次看一下非父子组件之间的传值(总线机制) 要实现非父子组件之间的传值非常重要的 ...

  3. vue-learning:28 - component - 组件事件的修饰符`.native / .sync`,以及组件属性`model`

    组件事件的修饰符.native / .sync,以及组件属性model .native 原生事件修饰符 在一个组件中,如果我们为其绑定一个原生的点击事件@click,基本是无效的. 在vue中对组件绑 ...

  4. vue单文件组件形成父子(子父)组件之间通信(vue父组件传递数据给子组件,子组件传递数据给父组件)

    看了很多文章,官网文档也有看,对父子组件通信说的不是很明白:决定自己总结一下: vue一般都使用构建工具构建项目:这样每个组件都是单文件组件:而网上很多文章都是script标签方式映入vue,组件通信 ...

  5. Vue组件通信之非父子组件传值

    前言: 如果想要了解非父子关系的组件传值,最好是在了解父传子和子传父的基础上在来了解非父子传值可能会有更透彻的思路. 因为非父子传值是通过定义事件总线来代理实现父传子+子传父从而实现的传值方式. 这是 ...

  6. vue 2 使用Bus.js进行兄弟(非父子)组件通信 简单案例

    vue2中废弃了$dispatch和$broadcast广播和分发事件的方法.父子组件中可以用props和$emit().如何实现非父子组件间的通信,可以通过实例一个vue实例Bus作为媒介,要相互通 ...

  7. vue组件通信之非父子组件通信

    什么顺序不顺序的.. 先来说说非父子组件通信. 首先,我们先来了解下vue中的 1.$emit  触发当前实例上的事件,附加参数都会传给监听器回调. 2.$on  监听当前实例上的自定义事件.事件可以 ...

  8. vue教程3-05 vue组件数据传递、父子组件数据获取,slot,router路由

    vue教程3-05 vue组件数据传递 一.vue默认情况下,子组件也没法访问父组件数据 <!DOCTYPE html> <html lang="en"> ...

  9. VUE生命周期中的钩子函数及父子组件的执行顺序

    先附一张官网上的vue实例的生命周期图,每个Vue实例在被创建的时候都需要经过一系列的初始化过程,例如需要设置数据监听,编译模板,将实例挂载到DOM并在数据变化时更新DOM等.同时在这个过程中也会运行 ...

随机推荐

  1. jdk的切换

    1.下载安装新版本的jdk 2.使用该命令,添加新版jdk alternatives --install /usr/bin/java java /opt/jdk1.8.0_144/bin/java 2 ...

  2. 新鲜出炉!春招-面试-阿里钉钉、头条广告,美团面经分享,看我如何拿下offer!

    之前给大家分享了一个朋友在字节面试的面试经历和拿到offer的过程,过程也算是比较精彩了,感兴趣的朋友可以去翻翻之前的那篇文章.话不多说重点来啦,一直有人发私信问我有没有其他大厂的面经分享啊,我也是联 ...

  3. 全面解析RayFire的动态对象与静态对象

    我们在日常使用RayFire的过程中,接触得比较多的应该就是RayFire的对象设置了.RayFire的对象包含了动态对象.静态对象与休眠对象,其中动态对象.静态对象可以结合动力学.运动学概念设置动作 ...

  4. MathType中如何编辑求和公式

    在学习过程中,尤其是在写需要用到数学公式的论文的时,需要输入数学公式并进行格式编辑等,那么对于简单的公式可以使用Office自带的公式编辑器,对于复杂的公式建议使用专业的公式编辑器MathType,该 ...

  5. 吉他自学用Guitar Pro好不好?

    很多人心中都有一个吉他梦,可苦于没有坚持下来.其实一个人自学吉他过程是非常枯燥的.经常手上被磨得都是茧,但是也不清楚自己弹的到底对不对. 如果不跟着老师练习,那很有可能就走了歪路或者是无法长期坚持.所 ...

  6. 【VUE】4.配置axios发起请求

    1.配置axios 1. 前端请求后端接口进行数据交互的时候,需要配置axios 2. 导入axios包, main.js import axios from 'axios' 3. 挂载到原型配置上, ...

  7. Nacos安装与启动教程

    前言 Nacos是阿里巴巴集团开源的一个易于使用的平台,专为动态服务发现,配置和服务管理而设计,Nacos基本上支持现在所有类型的服务,例如,Dubbo / gRPC服务,Spring Cloud R ...

  8. docker 中的mysql启动端口号总是被占用解决

    解决: 1 查 netstat -lnp|grep 3306 2 杀 kill -9 3819 3 再查 netstat -lnp|grep 3306 4 发现还有,杀不尽 5 重启docker 6 ...

  9. 使用Python过程出现的细节问题:TypeError: not enough arguments for format string

    今天使用字符串格式化时,遇到的一点小问题:调用这个方法解释器出错了:TypeError: not enough arguments for format string def ll(name,age) ...

  10. 如何测试一个APP

    1.是否支持各种手机系统 2.是否会因为分辨率而出错 3.不同机型能否安装 4.老旧机型 能否通用 5.广告时长 6.测试能否登陆注册 7.卸载时是否会发生意外 8.安装时会不会误认为带病毒 9.用户 ...