文章目录
一:为什么组件data必须是函数
1:组件可以访问vue data里面的数据吗?
- 组件是一个单独功能模块的封装∶
这个模块有属于自己的HTML模板,也应该有属性自己的数据data。
组件中的数据是保存在哪里呢? - 顶层的Vue实例中吗?
我们先来测试一下,组件中能不能直接访问Vue实例中的data
我们发现不能访问,而且即使可以访问,如果将所有的数据都放在Vue实例中,Vue实例就会变的非常臃肿。
结论:Vue组件应该有自己保存数据的地方。
正确写法:
半个小时的视频,等我脑袋清醒了,再重新看一遍,懵了
- 在开发中,往往一些数据确实需要从上层传递到下层∶
比如在一个页面中,我们从服务器请求到了很多的数据。
其中一部分数据,并非是我们整个页面的大组件来展示的,而是需要下面的子组件进行展示。
这个时候,并不会让子组件再次发送一个网络请求,而是直接让大组件(父组件)将数据传递给小组件(子组件) - 如何进行父子组件间的通信呢?Vue官方提到
通过props向子组件传递数据
通过事件向父组件发送消息
二:父传子 props
- 在组件中,使用选项props来声明需要从父级接收到的数据。
- props的值有两种方式:
方式一︰字符串数组,数组中的字符串就是传递时的名称。
方式二︰对象,对象可以设置传递时的类型,也可以设置默认值等。
我们先来看一个最简单的props传递∶
<body>
<!-- 1:提供接收Vue数据的容器 -->
<div id='app'>
<!-- 利用v-bind -->
<cpn :cmovies='movies' :cmsg='msg'></cpn>
</div>
<!-- 2:导入vue.js文件 -->
<script src='./js/vue.js'></script>
<template id="mycpn">
<div>
<!-- 最后使用 -->
{{cmovies}}
{{cmsg}}
</div>
</template>
<script>
// 子组件
const cpn = {
// 模板
template: '#mycpn',
data() {
return {
}
},
// 接收父组件的数据
props: ['cmovies', 'cmsg']
}
</script>
<!-- 3:使用Vue语法 -->
<script>
// 根组件 可以看做一个父组件
const vm = new Vue({
el: '#app',
// 父组件的数据
data: {
movies: ['《你好,李焕英》,《送你一所小红花》,《唐人街探案》'],
msg: '你好'
},
methods: {},
// 创建组件(子组件)
components: {
cpn
}
})
</script>
</body>
1:props数据验证
-
在前面,我们的props选项是使用一个数组。
我们说过,除了数组之外,我们也可诗使用对象,
当需要对props进行类型等验证时,就需要对象写法了。 -
验证都支持哪些数据类型呢?
String
Number
Boolean
Array
object
Date
Function
Symbol -
当我们有自定义构造函数时,验证也支持自定义的类型
三:子传父 (自定义事件)
- props用于父组件向子组件传递数据,还有一种比较常见的是子组件传递数据或事件到父组件中。
- 我们应该如何处理呢?这个时候,我们需要使用自定义事件来完成。
- 什么时候需要自定义事件呢?
当子组件需要向父组件传递数据时,就要用到自定义事件了。
我们之前学习的v-on不仅仅可以用于监听DOM事件,也可以用于组件间的自定义事件。 - 自定义事件的流程︰
在子组件中,通过$emit()来触发事件。
在父组件中,通过v-on来监听子组件事件。 - 我们来看一个简单的例子∶
我们之前做过一个两个按钮+1和-1,点击后修改counter。
我们整个操作的过程还是在子组件中完成,但是之后的展示交给父组件。
这样,我们就需要将子组件中的counter,传给父组件的某个属性,比如total。
<body>
<!-- 1:提供接收Vue数据的容器 -->
<!-- 父组件模板 -->
<div id='app'>
<!-- 3:2步骤自定义的属性,设置方法cpnclick,在父组件中设置行为 -->
<cpn @itemclick='cpnclick'> </cpn>
</div>
<!-- 子组件模板 -->
<template id="mycpn">
<div>
<!-- 1:给按钮添加一个点击事件 -->
<button v-for="(item,index) in categories" @click='clickhandle(item)'>
{{item.name}}
</button>
</div>
</template>
<!-- 子组件 -->
<script>
const cpn = {
template: '#mycpn',
// 子组件中的数据
data() {
return {
categories: [
{ id: 1, name: '热门分类' },
{ id: 2, name: '手机数码' },
{ id: 3, name: '家用家电' },
{ id: 4, name: '电脑办公' },
{ id: 5, name: '娱乐轻松' },
]
}
},
methods: {
// 2:将事件发射出去,自定义属性itemclick
// 记住$emit
clickhandle(item) {
this.$emit('itemclick', item)
}
}
}
</script>
<!-- 2:导入vue.js文件 -->
<script src='./js/vue.js'></script>
<!-- 3:使用Vue语法 -->
<script>
// 父组件
const vm = new Vue({
el: '#app',
data: {},
methods: {},
components: {
cpn
},
methods: {
// 4:父组件中的行为
cpnclick(item) {
console.log(item);
}
}
})
</script>
</body>
有时候我们需要父组件直接访问子组件,子组件直接访问父组件,或者是子组件访问跟组件。
- 父组件访问子组件:使用
$children
或$refs
- 子组件访问父组件:使用
$parent
四:父访问子 children-refs
$children
的访问
this.$children
是一个数组类型,它包含所有子组件对象。- 我们这里通过一个遍历,取出所有子组件的
message
状态。
<body>
<!-- 1:提供接收Vue数据的容器 -->
<div id='app'>
<!-- $children的父组件 -->
<cpn></cpn>
<!-- $ref的父组件 -->
<cpn ref='aaa'></cpn>
<!-- 为按钮绑定点击事件 -->
<button @click='btnClick'>按钮</button>
</div>
<!-- 2:导入vue.js文件 -->
<script src='./js/vue.js'></script>
<!-- 子组件的模板部分 -->
<template id="mycpn">
<div>我是子组件</div>
</template>
<!-- 3:使用Vue语法 -->
<script>
// 父组件
const vm = new Vue({
el: '#app',
data: {},
methods: {
// 父组件的按钮绑定的事件
btnClick() {
// $children 可以点出子组件中的methods里面的行为
this.$children[0].showMessage()
// $ref
this.$refs.aaa.showMessage()
}
},
components: {
// 子组件
cpn: {
template: '#mycpn',
methods: {
showMessage() {
console.log('你好呀');
}
}
}
}
})
</script>
</body>
五:子访问父 parent -root
子访问父:
- 根组件:$root
- 父组件:$parent
<body>
<!-- 1:提供接收Vue数据的容器 -->
<div id='app'>
<cpn></cpn>
</div>
<template id="mycpn">
<div>
<h1>我是子组件</h1>
<button @click='btnClick'>按钮</button>
</div>
</template>
<!-- 2:导入vue.js文件 -->
<script src='./js/vue.js'></script>
<!-- 3:使用Vue语法 -->
<script>
const vm = new Vue({
el: '#app',
data: {
msg: '你好,北京'
},
methods: {},
components: {
cpn: {
template: '#mycpn',
methods: {
btnClick() {
console.log(this.$root.msg);
}
}
}
}
})
</script>
</body>