props是vue当中最基本的常用的组件间通信方式
适用场景:父子之间
父可以给子传递 非函数和函数
传非函数数据 就是父给子
传函数数据 本质是父想要子的数据
props子组件声明接收属性三种写法
1、[‘todos’]
2、{ todos:Array}
3、{ todos:{type:Array,default:100,validator:(value) => {return value > 100}}}
特殊:
路由配置 props(三种) 路由组件之间没有标签,但是可以把参数通过路由映射为属性
1、布尔值 true 把路径params参数映射为要显示的组件内属性
2、对象 {name:'赵丽颖'} 只能映射传递额外的静态的数据 一般不用
3、函数 props:(route) =>{} 自己手动映射params参数和query参数 成为要显示的组件内属性
如果不用props,那么组件内要用数据必须要写成 this.$route.params.xxx this.$route.query.xxx
组件通信的一种方式
适用场合:子向父传递数据
怎么做
在父组件当中给子组件标签绑定自定义事件,事件回调留在父组件当中
在子组件当中触发它自己身上绑定的自定义事件,触发事件调用回调函数可以通过实参传递
原生dom事件 (三要素:事件源 事件类型 回调函数)
事件类型 回调函数 谁调用 默认传递的实参是什么1、事件类型 固定的几十个
2、回调函数 自己去定义的
3、触发(分发、触发事件)了谁调用 系统调用 浏览器去调用
4、event事件对象 (浏览器在调用回调函数的时候,会把当前这一次触发事件相关的所有信息封装成一个对象
传递给回调函数的第一个形参) $event
box.onclick = function(){
}
自定义事件
事件类型 回调函数 谁调用 默认传递的是什么
1、事件类型 无数个
2、回调函数 自己去定义的
3、谁调用 自己去调用 自己使用$emit触发调用的
4、默认传递的是什么 默认传递的是自己给的参数 (有就有,没有就没有undefined)
this.$emit('haha',10,20)
原生dom事件在html标签和组件标签上的区别
在html标签上添加就是原生的dom事件
在组件标签上添加就是自定义事件,想成为原生的事件得添加修饰符.native,就是把原生dom事件添加到子组件根元素上 (事件委派)
vue自定义的事件在html标签和组件标签上的区别
在html标签上添加自定义事件无意义,所以自定义事件是给组件标签添加的
添加给组件标签:事件名可以任意,也可以和原生的dom事件名相同,但是在组件标签身上即使添加原生dom事件也是自定义的
所有场合
全局事件总线的角色标准
本质是一个对象
1、所有的组件对象都可以看到它
2、可以使用$on和$emit方法
怎么添加事件总线
1、安装总线
2、在接收数据的组件对象当中 获取总线给总线绑定自定义事件 回调函数的定义会留在本组件 this.$bus.$on
3、在发送数据的组件对象当中 获取总线触发总线身上绑定的自定义事件 就可以调用回调函数,通过函数传参 this.$bus.$emit
element-ui表单相关项都使用到了v-model
官方网站也提出了怎么去使用
1、html input v-model的本质
:value = “data” //读取数据
@input = "data = $event.target.value" //写数据
2、组件标签上 v-model本质
:value = "data" 父组件传递属性给子组件,子组件需要接受
@input = "data = $event" //父组件当中给子组件添加的自定义事件
子组件当中必须这样写
先接受props:['value']
子组件表单类元素
:value = "value"
@input = "$emit('input',$event.target.value)"
属性如果写在组件标签身上无论带不带冒号,都是在给组件内部传递属性
写在原生html标签身上是给标签绑定属性值,没有传递
干了两件事
先绑定数据 只不过在html标签身上是绑定数据,在组件标签身上是传递属性
再绑定修改数据的事件
只不过在html和组件标签上绑定的@input事件不同 一个是原生的 一个是自定义的事件
实现父子组件双向数据同步
源码查看element-ui的input是不是使用了
本质上还是自定义事件和props组合
==
1、通过:value="msg"把value传递给子组件,子组件内部可以接收
2、子组件内部接收了value之后,可以在子组件内部去使用,但是不能修改
3、父组件给子组件绑定自定义事件input,触发事件之后,会把子组件修改的数据赋值给父组件当中的msg
4、子组件当中绑定input原生dom事件,一旦用户输入数据,触发子组件绑定的自定义事件,传递最新输入的值
5、父组件接收数据之后赋值给msg,msg变为最新的数据,再次传递给子组件,子组件内部msg数据更新 -->
{{value}}
实现父子组件双向数据同步问题
和 v-model 实现效果几乎一样
v-model一般用于带表单项的组件
sync属性修饰符一般用于不带表单项的组件
父组件给子组件属性传递数据后面添加.sync
子组件修改数据 需要分发事件@click = $emit("update:属性名",要更新的数据)
本质上还是自定义事件和props组合
小明的爸爸现在有{{money}}元
不使用sync修改符
使用sync修改符
使用v-model修改符
child
小明每次花100元
爸爸还剩 {{money}} 元
child2
小明每次花100元
爸爸还剩 {{value}} 元
$attrs是一个对象,里面包含了父组件传递的所有属性,但是不包含props接收的属性以及和样式相关的属性
$listeners是一个对象,里面包含了父组件给子组件绑定的所有事件监听
本质就是父组件中给 子组件传递的所有属性组成的对象及自定义事件方法组成的对象
$attrs 如果不声明props 那么子组件当中是可以看到
如果声明了哪个属性,那么那个属性在$attrs当中看不到
它会排除 props声明接收的属性 以及class style
可以通过v-bind 一次性把父组件传递过来的属性添加给子组件
可以通过v-on 一次性把父组件传递过来的事件监听添加给子组件
对一个组件进行二次封装
element-ui的button添加click事件会触发,添加dblclick就不会触发的问题
element-ui的button 子组件内部触发了这个单击事件
element-ui的button 子组件内部没有触发这个双击事件扩展双击点击触发element-ui button事件,使用原生.native
$children:所有子组件对象的数组
$parent:代表父组件对象
ref用在html标签身上,是用来获取真实dom元素,用在组件标签身上,获取的是组件对象
父组件当中可以通过$children找到所有的子组件去操作子组件的数据(当然可以找孙子组件)
不过$children拿到所有子组件数组内部顺序不定
子组件当中可以通过$parent找到父组件(当然可以继续找爷爷组件)操作父组件的数据,
如果父组件有多个,没反应
$parent 和 $children用的时候注意(会出问题)
扩展: 多个组件有部分相同的js代码
html js css 相同 封装组件
单个组件js代码重复 封装函数
不同的组件js代码重复 封装模块 (混入mixin)
实现组件之间js代码的复用 利用vue的mixin技术 参考官网比如多个组件的methods里面很多函数都是重复的 那么我们可以定义单独的模块去把这些相同的代码定义到外部
export const xxxMixin = {methods:{
重复的代码写在这
}}
适用:父子之间
数据是在父组件当中的,数据是要给子组件去展示的(vfor)
展示的过程当中,数据的结构 子组件说了不算,是由父组件决定的
父组件要把需要子组件展示的数据传递给子组件
子组件在展示的过程当中,如果需要额外的结构和样式,子组件说了不算,由父组件说了算,需要改变结构的数据传回给父组件,父组件再把结果和数据一并传回给子组件
5个核心概念
state //共享状态数据,state的数据在每次打开项目和刷新项目的时候都要重新初始化
mutations 直接修改state当中的数据
actions // 提交mutations修改数据 响应组件dispacth异步发送请求
getters 等价于组件内部的computed的getter
modules //vuex的模块化开发 影响的是state
PubSubJS是一个第三方包,本质引入是一个对象
PubSub.publish() 方法是用来发布消息的
PubSub.subscribe() 方法是用来订阅消息的
由于是第三方包使用的时候不需要在main当中注册
在接收数据的组件当中,通过PubSub.subscribe(消息名,回调函数)去订阅消息,回调函数就留在当前组件
在发送数据的组件当中,通过PubSub.publish(消息名,数据)去发布消息,可以调用函数传递数据
它和全局事件总线用法很相似,有一个很大的区别: 回调函数的第一个形参
全局事件总线事件回调的第一个参数就是我们传递的数据
消息的订阅发布,回调的第一个参数是消息名,即使不用也要占位,第二个参数才是我们传递的数据
Vue2在做响应式数据的时候针对的就是两种数据:对象 数组
数组:响应式是通过7个重写的方法去实现的,只要是数组数据用这7个方法,数据一定是响应式的
数组如果直接通过下标去操作,不是响应式
对象:响应式是通过(数据代理)数据劫持,数据劫持做了两件事
1、给data当中所有的属性,递归生成dep
2、修改data当中所有的属性,为响应式属性,通过Object.defineProperty给每个属性添加get和set方法
当访问this.xxx 访问的是vm.xxx 会触发vm身上的xxx get方法,它会最终返回data当中的同名属性值,
要返回data当中同名属性值,就会触发data当中同名属性的get方法,最终读取data同名属性值进行返回
当修改this.xxx 修改的是vm.xxx 会触发vm身上的xxx set方法,最终修改的是data当中的同名属性值,
要修改data当中同名属性值,就会触发data当中同名属性的set方法
在set方法当中做了以下三件事:
1)判断新值和旧值是否相同,相同return 不相同更新
2) 如果修改的新值又是一个对象,会递归给修改的新值也进行响应式处理
3)通知让页面根据新数据进行更新
补充:初始化的data数据一定是响应式,更新的data当中属性新数据也是一定响应式
问 如果是后期(页面挂载完,点击按钮触发事件),给data当中添加属性,那么这个新添加的属性是不是响应式的属性数据?
答:不是
怎么办? $set