目录
组件高级
一、传值
1 正向属性传值——父传子
2反向传值——子传父
2.1 子组件通过自定义事件给父组件传新值 $emit
2.2 反向传值的sync
2.3 反向传值的v-model
3多层组件传值:$listeners/$attrs(了解)
4 $ parent/$root、$children/$refs(了解)
5中央事件总线bus(了解) event bus
6Vue 依赖注入 - **Provide/Inject(重点)**
7仓库vuex(重点)
二、笔试题 / 面试题
1、关于 Vue 组件间的参数传递,下列哪项是不正确的?
2、下列关于 v-model 的说法,哪项是不正确的?
组件高级
1、传值 2.动态组件 3.缓存组件keep-alive 4.异步组件(高薪意向)
父组件通过属性给子组件传值: 子组件的props接受数据
在页面模板中 使用变量名:属性 data 计算属性(重点)
//注意属性传值是单向的
APP.vue
Box.vue
{{ title }}----{{ price }}元 数量:
{{ count }}
2.1 子组件通过自定义事件给父组件传新值 $emit
子组件通过自定义事件给父组件传count的新值n,父组件收到新值后修改自己的data,自然就会刷新自己 和子组件的模板
子组件通过调用父组件的方法给父组件传值:子组件的自定义事件中,用$emit触发事件调用父组件方法给父组件传值 (重点)
**因为通过属性传值是单向的**,有时候我们需要子组件的data 数据需要交给父组件使用:
通过在子组件上定义自定义事件,在子组件中通过$emit 来触发事件;子组件的事件被触发并传参,事件处理函数可以接收到子组件的数据;事件绑定的事件处理函数在父节点上,故可在事件处理函数中用到子组件的数据值来修改父节点的数据。
//父组件中:
//myevent是事子组件的自定义事件
//handleEvent是绑定的父组件的方法
子组件中:
在任意业务中触发事件:this.$emit("myevent","要给父组件传的数据")
app.vue
Box.vue
{{title}}----{{price}}元
数量:
{{count}}
2.2 反向传值的sync
此方法就省略了写事件名字
自定义事件
子组件==>methods里面==>this.$emit("update:a1","数据更新了“)
父组件==>
app.vue
app组件--msg-{{msg}}--{{msg2}}
Box.vue
box组件---a1-{{a1}}--{{a2}}
2.3 反向传值的v-model
父组件:
(v-model这是一个语法糖==>
) 子组件:
props:["value"],,然后上面的标签使用这个{{value}}
点击写事件:fn(){this.$emit("input","传值")}
v-model.语法==>官网学
APP.vue
app--{{msg}}
Box.vue
box--{{value}}
在不用状态管理vuex的时候,如何让GrandFather与Son通信,我们可以用可以emit一层一层的传递,==>但是会显得冗余
vue2.4之后,提出$attrs、$listeners ,可以实现跨级组件通信。
$listeners官网解说:事件传递 $attrs官网解说:属性传递
在组件中绑定 可以把当前组件的自定义属性和方法传给子元素使用:
one组件:
two组件中:
three组件:可以访问two的 属性和触发事件: {{this.$attrs.xx}} this.$emit("twoEvent",20)
APP.vue
app-{{msg}}
Box1.vue
{{$attrs.b1}}
Box2.vue
box2--{{b1}}
这些功能都是有劣势或危险的场景的,官方建议我们尽量避开它们,但是高级点的面试题中会出现
$root:
访问根组件vm (就是new Vue)对象,所有的子组件都可以将这个实例作为一个全局 store 来访问或使用,现在有更好的技术vuex代替。
$parent:访问父组件对象,直接操作父组件的data数据,不需要再使用属性传值,但是容易出现渲染混乱之后只渲染一个的情况
$children:访问子组件对象数组,不能保证顺序,没有按照顺序加载,加载的顺序是乱的,因此写项目的时候不能按照下标去获取组件,然后操作组件。也不是响应式的
$refs:只会在组件渲染完成之后生效,并且它们不是响应式的。应该避免在模板或计算属性中访问 $refs。 (就相当于DOM获取元素)
Tips:1、在Box1中打印this,this.$parent,$root,就会打印自己的VueComponent 、app.vue的VueComponent 、 Vue根节点对象
2、$parent 、$children都是代表组件,不是元素,就算Box1放在一个div中,它的$parent也是app.vue
3、可以直接修改 父/爷爷/孙子/...组件:
this.$parent.msg="Box1将app.vue里面的msg修改了"
//在组件或者原生元素绑定ref属性(类似于id):
//在父组件中可以通过 this.$refs访问到它:
methods: {
focus: function () {
this.$refs.myInput2.focus()
}
}
APP.vue
app--{{msg}}
Box1.vue
box1
66666
234234
Box2.vue
{{$parent.$parent.msg}}
box2
案例:利用$ref实现放大镜代码迁移
一个网站中有一个很好的功能,别人是DOM操作,而我们用Vue来操作,获取元素
==>mounted之后就去执行,将它的class改为ref,然后用var div1=this.$refs.div1来获取
通过创建一个新的vm对象,专门统一注册事件,供所有组件共同操作,达到所有组件随意隔代传值的效果
//vue-bus.js文件
const install = function (Vue) {
const Bus = new Vue({
methods: {
emit(event, ...args) {
this.$emit(event, ...args);
},
on(event, callback) {
this.$on(event, callback);
},
off(event, callback) {
this.$off(event, callback);
}
}
});
Vue.prototype.$bus=Bus;//由于这个新的vm放在与界面绑定的那个vm的原型上,因此页面上的所有组件都能通过this.$bus访问这个新vm对象
};
export default install;
//main.js文件
import VueBus from './vue-bus'
Vue.use(VueBus);
//组件文件中:
任意业务中都可以通过调用来绑定事件,触发事件并传值,和销毁事件
this.$bus.on(event,callback)
this.$bus.off(event,callback)
this.$bus.emit(event, ...args)
示例:
组件1:
this.$bus.on('changedFormObject',(val) =>{
//接受并处理传过来的值:val
this.msg = val;
});
组件2:
this.$bus.emit('changedFormObject',this.inputValue);//把组件2的data中的给inputValue值传给组件1
通常情况下,**父**组件向**孙**组件传递数据,可以采用父子`props`层层传递,也可以使用`bus`和`Vuex`直接交互。在Vue2.2.0之后,Vue还提供了`provide/inject`选项
官网不建议在应用中直接使用该办法,理由很直接:他怕你"管不好"
//爷爷
{{ title }}
//爸爸
{{ title }}
//孙子
message:{{ message }}
后面讲
A. 若子组件给父组件传值,可使用 $emit 方法
B. 祖孙组件之间可以使用 provide 和 inject 方式跨层级相互传值
C. 若子组件使用 $emit('say') 派发事件,父组件可使用 @say 监听
D. 若父组件给子组件传值,子组件可通过 props 接受数据选B
A. v-model 能实现双向绑定
B. v-model 本质上是语法糖,它负责监听用户的输入事件以更新数据
C. v-model 是内置指令,不能用在自定义组件上
D. 对 input 使用 v-model,实际上是指定其 :value 和 @input选C,能用
A. 若子组件给父组件传值,可使用 $emit 方法
B. 祖孙组件之间可以使用 provide 和 inject 方式跨层级相互传值
C. 若子组件使用 $emit('say') 派发事件,父组件可使用 @say 监听
D. 若父组件给子组件传值,子组件可通过 props 接受数据选B
A. 可通过 this.$parent 查找当前组件的父组件
B. 可使用 this.$refs 查找命名子组件
C. 可使用 this.$children 按顺序查找当前组件的直接子组件
D. 可使用 $root 查找根组件,并可配合 children 遍历全部组件选C 无顺序