单项数据流‘:父组件可以随意传数据给子组件, 父可以随意修改 , 子不能修改父的数据,会报错。
如果子组件修改了父组件的数据。那么会对其他的子组件也会有相应的影响。
处理方式:父组件的值,子组件接收够用一个变量接收。这样就变成子组件自用的了 (完美解决)
父组件向子组件传值:通过属性传值
父组件要传值给子组件,需要在子组件上绑定属性(用v-bind动态绑定,如果不用那就相当于传入固定值),子组件需要使用props来接收父组件传的数据。以下就是简单的父向子组件传值
首先在头便签引入vue
<head>
<meta charset="UTF-8">
<title>Vue</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<div id="app">
<my-div :number ="number"></my-div>
</div>
<script>
//定义子组件
Vue.component("my-div", {
props: ['number'], //接收父级数据
template: `
<div>
<h1>联系方式</h1>
<p>联系电话{{number}}</p>
</div>`
})
new Vue({
el: "#app",
data: {
number: 7758258
},
})
</script>
当然,对于props我们可以在深入了解。他可以限定父级传的数据类型,只有符合的类型才接收
对于props的简单了解可以直接搜索我的 prop文章
对于props的深入可以参考一下文章 https://www.cnblogs.com/xiaohuochai/p/7388866.html
比如我们规定父组件传过来的数据必须是Number类型的。(如果不是数据也会显示,但是控制台会抛出错误)
Vue.component("my-div", {
props: {
number:{
type:Number
}
},
template: `
<div>
<h1>联系方式</h1>
<p>联系电话{{number}}</p>
</div>`
})
new Vue({
el: "#app",
data: {
number: 7758258
},
})
对于以上代码。如果我们子组件要改变父组件传的数据,就需要一个变量接收,克隆接收过来的副本。(小问题。因为是克隆出来的,当父组件数据变化时候,子组件的数据是不会变化的)
以下代码就是把父组件传的数据用变量接收了,点击btn的时候只改变父组件的,改变不了子组件的
<div id="app">
<div>{{number}}</div>
<my-div :number="number"></my-div>
<button @click="Clickbtn">点我</button>
</div>
<script>
//定义子组件
Vue.component("my-div", {
props: {
number: {
type: Number
}
},
data() {
return {
num: this.number
}
},
template: `
<div>
<h1>联系方式</h1>
<p>联系电话{{num}}</p>
</div>`
})
new Vue({
el: "#app",
data: {
number: 7758258
},
methods: {
Clickbtn() {
this.number++
}
}
})
</script>
父子组件的动态值:
因为是动态绑定数据。所以我们能在改变父组件的数据时同时也改变子组件。
<div id="app">
<my-div :number="number"></my-div>
<h1>父组件数据</h1>
<div>{{number}}</div>
<button @click="Clickbtn">点我</button>
</div>
<script>
//定义子组件
Vue.component("my-div", {
props: {
number: {
type: Number
}
},
data() {
return {
num: this.number
}
},
template: `
<div>
<h1>子组件数据</h1>
<p>{{number}}</p>
</div>`
})
new Vue({
el: "#app",
data: {
number: 1
},
methods: {
Clickbtn() {
this.number++
}
}
})
</script>
子组件变量接收父组件数据后:
这时候我们改变父组件数据,子组件不不会变化。我们给子组件添加了点击事件。可以单项改变子组件的值。不影响到其他组件
<div id="app">
<my-div :number="number"></my-div>
<h1>父组件数据</h1>
<div>{{number}}</div>
<button @click="Clickbtn">点我</button>
</div>
<script>
//定义子组件
Vue.component("my-div", {
props: {
number: {
type: Number
}
},
data() {
return {
num: this.number
}
},
methods: {
Clickbtn() {
this.num++
}
},
template: `
<div>
<h1>子组件数据</h1>
<p>{{num}}</p>
<button @click="Clickbtn">点我</button>
</div>`
})
new Vue({
el: "#app",
data: {
number: 1
},
methods: {
Clickbtn() {
this.number++
}
}
})
</script>
子组件像父组件传值:通过事件传值
现在我们需要实现父组件和子组件的数据累加。这时候我们需要把子组件改变的数据传到父组件。我们可以使用事件将数据传递到父组件。
在组件定义一个$emit()事件。参数:第一个参数为自定义事件名(像下面的foo为对应的回调函数,写在父组件中,因为整个模板都是定义在父组件中,对应的函数就写在父组件中)。其他参数为子组件传给父组件的数据(参数不限)
自定义事件child 在子组件点击的时候被触发。在父组件定义foo函数。
每当子组件点击事件触发,父组件都会执行foo函数
下面我实现一个小功能:做一个累加器。数据一个来自子组件,一个来自父组件(代码有点冗余)。这里用计算属性来解决非常实用!自己实现咯~
思路:
父组件传值给子组件(属性传值)。子组件定义变量接收。然后可以私有化后修改。
通过点击事件修改数值。这时候触发自定义事件,将修改的值传给父组件。
父组件函数foo以参数形式接收子组件数据,
此时我们改变的值需要实时反馈到累加器上。我们就在foo函数中直接操作了父组件和子组件的数据相加。
但是这有一个问题:子组件修改我们能实时改变累加器。父组件数据修改不行。因为父组件定义点击函数中拿不到子组件的数值。(自己的折中办法就是父组件定义一个变量接收子组件的值,然后去实现改变。方法是可行的。应该还用更简单的操作办法)
代码如下:
<div id="app">
<h1>合计{{add}}</h1>
<my-div :number="number" @child="foo"></my-div>
<p>父组件数据</p>
<div>{{number}}</div>
<button @click="Clickbtn">点我</button>
</div>
<script>
//定义子组件
Vue.component("my-div", {
props: {
number: {
type: Number
}
},
data() {
return {
num: this.number
}
},
methods: {
Clickbtn() {
this.num++
//点击事件触发自定义事件child
this.$emit('child', this.num)
}
},
template: `
<div>
<p>子组件数据</p>
<p>{{num}}</p>
<button @click="Clickbtn">点我</button>
</div>`
})
new Vue({
el: "#app",
data: {
number: 1,
childNum: '',
add: ''
},
methods: {
Clickbtn() {
this.number++
this.add = this.childNum + this.number
},
foo(num) {
this.childNum = num
this.add = this.childNum + this.number
}
}
})
</script>
优化后的代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<h1>合计:{{add}}</h1>
<my-div :number="number" @child="foo"></my-div>
<p>父组件数据</p>
<div>{{number}}</div>
<button @click="Clickbtn">点我</button>
</div>
<script>
Vue.component("my-div", {
props: {
number: {
type: Number,
required: true //必传
}
},
data() {
return {
num: this.number
}
},
methods: {
Clickbtn() {
this.num++
//点击事件触发自定义事件child
this.$emit('child', this.num)
}
},
template: `
<div>
<p>子组件数据</p>
<p>{{num}}</p>
<button @click="Clickbtn">点我</button>
</div>`
})
new Vue({
el: "#app",
data: {
number: 1,
childNum: '',
},
methods: {
Clickbtn() {
this.number++
},
foo(num) {
this.childNum = num
},
},
computed: {
add() {
return this.childNum + this.number
}
}
})
</script>
</body>
</html>
通过以上。我们能简单了解和学习父子组件的传值,以及对vue单项数据特点的认真。
以及关于非父子组件,vue更是给了vuex插件帮我们解决的这个难题(当数据量小的时候。我们也可以通过总线模式解决)