Vue组件参数传递问题
Vue组件参数传递问题
组件中的data为什么是函数?
组件中的数据是保存在哪里呢?顶层的Vue实例中吗?并不是的,组件无法访问Vue实例中的data。即使可以访问,如果所有组件的数据都在顶级Vue实例中,那么Vue中的data会十分的臃肿。组件中的数据应该由自己管理。
组件是一个单独功能模块的封装,这个模块有属于自己的HTML模板,也应该有属于自己的数据data,不过这个data是一个函数。这是为什么呢?
这是为了保证组件复用时,属性之间的隔离。利用方法都会重新开辟内存空间的机制。当创建多个相同组件实例时,不同组件实例之间的data必须保证不被共享
父子组件通讯之props(父->子)
需求1:在页面中,父组件请求得到的数据需要在子组件中展示。
需求2:子组件很多,每次创建都要向后他发送数据,在父组件中进行请求,将数据传递给子组件展示。
Vue中提供了props用于父组件向子组件中传递数据
在子组件中,使用props声明需要从父级接收到的数据
props的值有两种方式:
- 方式一:字符串数组,数组中的字符串就是传递时的属性名称。
- 方式二:对象,对象可以设置传递时的类型,也可以设置默认值等。
数组形式的传递
1、在父组件中创建数据
data() {
return {
userId: "rayfoo",
name:'rayfoo',
hobby: ['抽烟','喝酒','烫头']
};
}
2、在子组件中创建props
props: ['name','hobby']
3、在子组件中使用属性
<h2 v-text="name"></h2>
4、在父组件中导入并使用子组件
import News from "./views/home/news";
components: {
News
}
<News :name="name" />
对象形式的传递
对象参数的传递需要指定对象类数据类型、[默认值]、[是否必传]等参数
支持的类型类型
- String
- Number
- Boolean
- Object
- Data
- Function
- Symbol
props:{
title:{
//数据类型 参数可以指定多个[String,Number,...]
type: String,
//默认值,在没有引入传递参数时渲染
default: 'Message',
//是否为必传参数
required: false
},
hobby:{
type: Array,
default: function(){
return ['抽烟','喝酒']
}
}
}
需要注意的时,当类型如果是Object或者Array,默认值必须是一个函数。
子组件向父组件传递数据
子组件中配置事件发送:
template:
<button @click="giveAdvice">我是一个小按钮</button>
methods:
methods: {
giveAdvice: function(){
this.$emit('give-advice',this.title);
}
}
父组件中监听
template:
<News :name="name" @give-advice="showAdvice" />
methods:
showAdvice: function (advice) {
alert(advice)
}
需要注意的是,事件如果传递的是驼峰式,需要使用下划线形式发射。具体的操作可以参考官方API
https://cn.vuejs.org/v2/api/#vm-emit
参数同步问题
如果父子间传递的参数需要实时的进行双向绑定,该如何做?
如果修改了props中的值,父组件中的内容不会修改。Vue不推荐在子组件中直接修改props的值。
如果需要修改props中的值,可以在子组件中创建一个data或者computed副本
使用@input事件实现双向绑定
子组件代码:
1、在子组件中声明props,由父组件传递。
2、创建props的副本,当props的副本
3、使用v-model绑定props副本的值
4、监听控件的@input,当值发生改变,修改参数值,并且将值弹回父组件
<template>
<div name='chidren'>
<h1 v-text="title"></h1>
<p v-text="info"></p>
<input type="text" v-model="dparam" @input="valChange">
<button @click="giao">发射属性到父组件</button>
</div>
</template>
<script>
export default {
name: 'chidren',
props: {
title: String,
info: String
},
data(){
return{
param: 'GIAO',
dparam: this.title
}
},
methods:{
giao: function(){
this.$emit('giao',this.param);
},
valChange: function(event){
let newVal = event.target.value;
this.param = newVal;
this.$emit('title-change',newVal);
}
}/*,
watch:{
dparam(oldVal,newVal){
this.param = newVal;
this.$emit('title-change',newVal);
}
}*/
}
</script>
<style>
</style>
父组件代码
父组件中可以直接使用v-model来修改子组件中属性
<template>
<div name="parent">
<h1 v-text="title"></h1>
<input type="text" v-model="title">
<Childred @giao="giao" @title-change="titleChange" :title="title" :info="info"></Childred>
</div>
</template>
<script>
import Childred from './Chidren';
export default {
name: 'parent',
data(){
return {
title: 'rayfoo',
info: '真帅'
}
},
methods:{
giao: function(param){
alert(param);
},
titleChange:function(newVal){
this.title = newVal;
}
},
components:{
Childred
}
}
</script>
<style>
</style>
如果数据类型不是String,可能要牵涉一些类型转换问题。
使用watch进行子父组件双向绑定
略。。。
父组件中取得子组件的对象
$children-不常用
上面的案例中我们已经成功的在父组件中取得子组件的属性,也可以从子组件中拿到父组件的属性,下面介绍一个更加简单的操作形式-从父组件中拿到子组件对象。
在父组件中,可以使用:this.\(children[index].属性名、this.\)children[index].方法名来获取子组件内的属性和方法,但是在开发过程中一般不会使用这样的形式,因为其依赖下标,有很多的不确定性。
btnClick: function(){
console.log(this.$children[0].param);
this.$children[0].showInfo();
}
$refs-常用
可以在引用子组件的位置给子组件指定一个ref属性,例如ref='aaa'
此时,this.\(refs.aaa就是子组件对象,就可以在父组件中使用this.\)refs.aaa来访问子组件啦~
btnClick: function(){
console.log(this.$refs.child.param);
}
子组件中访问父组件对象
$parent不常用
在子组件中可以直接使用$parent来访问父组件中的内容,但是在子组件中频繁父组件中的内容,会使得组件的耦合度非常的高,所以开发过程中不常用。
btnClick: function(){
console.log(this.$parent.title);
}
$root
使用$root可以获取根组件中的内容
btnClick: function(){
console.log(this.$root.title);
}