目录
- 组件可以访问Vue实例数据吗?
- 组件的data参数
- 组件中的methods函数
- 父子组件
- 使用场景
- 如何通信(传递数据)
- 父传子
- 子传父
- 组件中的双向绑定
- 父组件访问子组件($children或$refs)
- 子组件访问父组件($parent)
- 组件的扩展-slot
- 基本使用
- 具名插槽
组件可以访问Vue实例数据吗?
-
组件是一个单独功能模块的封装,有属于自己的HTML模板,也有自己的数据data
-
组件中不能直接访问Vue实例里的数据,以下代码在组件是不能访问到message的
消息内容:{{message}}
组件的data参数
- 组件定义时也有一个data参数,但这个data参数不像Vue实例的data是一个对象类型,它这里是一个函数类型,如果你定义成了一个对象类型,会报以下错误
- 该data函数需要返回一个对象,对象内部保存着数据
- 示例代码:https://jsrun.net/EevKp/edit
const cpnC = Vue.extend({
template: "#cpn",
data(){
return {
title:"这里是标题吧",
content:"这里是内容哦!~~"
}
}
})
组件中的methods函数
- 用于定义一些事件处理的函数,同Vue实例里的methods函数类型
- 示例代码:https://jsrun.net/JevKp/edit
const cpnC = Vue.extend({
template: "#cpn",
data(){
return {
counter:0
}
},
methods:{
increment:function(){
this.counter++
},
decrement:function(){
this.counter--
}
}
})
父子组件
使用场景
- 比如一个商城的首页,上面有一个轮播图,下面有一个商品的列表
- 像这种页面,我们在开发时,会在最外层组件(父组件)里,向服务端一次请求到轮播图,商品列表数据,然后将数据分别传给轮播图组件,商品列表组件;然后商品列表组件在将数据传传商品组件来进行整个页面的渲染
如何通信(传递数据)
父传子
- 通过
prots
向子组件传数据(prots
为proterties
的简写,意为属性
) - props的二种方式
1.一种是可以传一个字符串数组,里面第一项对应变量名
将godos和message传给子组件进行渲染,示例代码:http://jsrun.net/5PvKp/edit
//1.Vue.extend创建组件
const cpnC = Vue.extend({
template: "#cpn1",
props:['cgoods','cmessage']
})
//2.注册组件
Vue.component('my-cpn', cpnC)
const app = new Vue({
el: "#app",
data: {
message: "我是message",
goods:["衣服","鞋子","帽子","短裤"]
}
})
2.第二种是传一个对象类型,可以进行类型限制type
和默认值default
,是否必需reauired
type
-指定参数的类型,有:String,Array,Boolean,Number,Date,Function,Symbol
default
-指定默认值
reauired
-指定是否必须要传该参数,是boolean类型,传(true或false)
const cpnC = Vue.extend({
template: "#cpn1",
props: {
//1.类型限制
// cgoods: Array,
// cmessage: String
//2.提供默认值,没传时显示
cgoods:{
type:Array,
default:[]
},
cmessage:{
type:String,
default:"这里是默认值",
required:true
}
}
})
props
的一些使用示例
Vue.component('cnp',{
props:{
//1.基础的类型检查(null匹配任何类型)
propA:Number,
//2.多个可能的类型
propB:[String,Number],
//3.必填的字符串
propC:{
type:String,
required:true
},
//4.带有默认值的数字
propD:{
type:Number,
default:100
},
//5.默认值的对象,数组或对象的需要返回一个函数
propE:{
type:Object,
default:function(){
return {name:"hello"}
}
},
//6.带自定义验证函数
propF:{
validator:function(val){
//这个val必须匹配下列数组中的一个
return ['张三','李四','王五'].indexOf(val) !== -1
}
}
}
})
- 组件中驼峰标识,
props
中定义了cTitle
,但在组件使用是需要变为:c-title
,子组件中使用时又为cTitle
//1.Vue.extend创建组件
const cpnC = Vue.extend({
template: "#cpn1",
props: {
//驼峰标识
cTitle:{
type:String
}
}
})
//2.注册组件
Vue.component('my-cpn', cpnC)
const app = new Vue({
el: "#app",
data: {
title:"我是驼峰标识"
}
})
子传父
{{message}}
//1.Vue.extend创建组件
const cpnC = Vue.extend({
template: "#cpn1",
data: function () {
return {
students: [
{ id: "001", name: "关晓彤",imgUrl:"https://5b0988e595225.cdn.sohucs.com/images/20181224/ecf125cb199d4808a067f682c6c5e6c6.jpeg" },
{ id: "002", name: "迪丽热巴",imgUrl:"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1593861542943&di=9fe9365124a4aae6cc6cf483aa2a9e18&imgtype=0&src=http%3A%2F%2Fb.hiphotos.baidu.com%2Fzhidao%2Fwh%253D680%252C800%2Fsign%3Dbb541c4377f40ad115b1cfe56f1c3de7%2F50da81cb39dbb6fde349ce5d0524ab18972b37be.jpg" },
{ id: "003", name: "郑爽",imgUrl:"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1593861570612&di=60b6d39dcbac9e1ea77b747d42f9f19d&imgtype=0&src=http%3A%2F%2Ftc.sinaimg.cn%2Fmaxwidth.800%2Ftc.service.weibo.com%2Fmmbiz_qpic_cn%2F1ab918195e7c8a94cc6c95182fbde786.jpg" },
{ id: "004", name: "杨幂",imgUrl:"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1593861759697&di=6771e7279c145513968ce221a29a6b0e&imgtype=0&src=http%3A%2F%2Fphotocdn.sohu.com%2F20130816%2FImg384334041.jpg" }
]
}
},
methods: {
btnclick(item) {
//发射事件,自定义事件
this.$emit("itemclick", item)
}
}
})
const app = new Vue({
el: "#app",
components: {
"my-cpn": cpnC
},
data: {
message: "",
imgUrl:""
},
methods: {
btnClick: function (item) {
this.message = "你选择了:" + item.name + ",学号:" + item.id
this.imgUrl=item.imgUrl
}
}
})
组件中的双向绑定
- 不能直接绑定
props
里的属性,要绑定data里定义的属性 - 示例:http://jsrun.net/R7vKp/edit
//1.Vue.extend创建组件
const cpnC = Vue.extend({
template: "#cpn",
data(){
return {
dnumber:this.number1
}
},
props:{
number1:{
type:Number,
default:0
}
},
methods:{
numInput:function(event){
this.dnumber=event.target.value
}
}
})
const app = new Vue({
el: "#app",
components:{
'my-cpn':cpnC
},
data: {
num: 1
}
})
父组件访问子组件($children或$refs)
$children
-是一个数组,通过下标访问,这种方式不建议使用,因为组件变化维护后,相应的下标也要变化,后期难维护
示例代码:http://jsrun.net/VcvKp/edit
const app = new Vue({
el: "#app",
methods:{
btnClick:function(){
//1.$children是一个数组
alert(this.$children[0].title)
},
},
components:{
'my-cpn':{
template:"#cpn",
data(){
return {
title:"我是子组件的标题"
}
}
}
}
})
$refs
-通过在组件上定义ref
进行访问
示例代码:http://jsrun.net/7cvKp/edit
const app = new Vue({
el: "#app",
methods:{
btnClick:function(){
//1.$children是一个数组
//alert(this.$children[0].title)
alert(this.$refs.aaa.title)
},
},
components:{
'my-cpn':{
template:"#cpn",
data(){
return {
title:"我是子组件的标题"
}
}
}
}
})
子组件访问父组件($parent)
- 子组件通过
$parent
访问父组件 $root
可以用来访问根组件,一般是Vue实例
示例代码:http://jsrun.net/dcvKp/edit
{{message}}
const app = new Vue({
el: "#app",
data: {
message: "我是Vue标题"
},
components: {
'my-cpn': {
template: "#cpn",
methods: {
btnClick: function () {
alert(this.$parent.message)
//访问根组件还可以使用$root,根组件一般是Vue实例
//我们这里的parent就等于根组件
//alert(this.$root.message)
}
}
}
}
})
组件的扩展-slot
基本使用
{{message}}
我是slot
我是slot span
const app = new Vue({
el: "#app",
data: {
message: "我是Vue标题"
},
components: {
'my-cpn': {
template: "#cpn"
}
}
})
具名插槽
{{message}}
center
right
right
const app = new Vue({
el: "#app",
data: {
message: "我是Vue标题"
},
components: {
'my-cpn': {
template: "#cpn"
}
}
})