文章目录
组件
组件就是把各自独立的积木拼成一个整体然后进行数据交互
一、组件注册
1. 全局注册
组件注意事项
- 全局组件 注册后,任何 vue实例 都可以用
- 组件参数的data值必须是函数同时这个函数要求返回一个对象
- 组件模板必须是单个根元素
- 组件模板的内容可以是模板字符串
Vue.component('组件名称', {
data: function () {return{}}, // data 在这里是函数
template: '模板'
})
就是相当于封装了一个模板,然后任何 vue实例 都可以用它自定义的名字来调用它
2. 局部注册
- 只能在当前注册它的vue实例中使用
let aaa = {
data() {
return {
ppp: 'ppp'
}
},
template: `<div>{{ppp}}</div>`
}
// Vue 组件
const vm = new Vue({
el: '#box',
components: {
'xxx': aaa // 使用 <xxx></xxx>
}
})
二、组件之间传值
1. 父组件向子组件传值
父组件在子组件的模板标签里面,使用属性传值给子组件的 props
接收,子组件直接在 template
定义模板里面使用
- 父组件发送的形式是以属性的形式绑定值到子组件身上,有静态和加
:
的动态两种形式 - 然后子组件用属性 props 接收
- 在 props 中使用驼峰形式,模板中需要使用短横线的形式字符串形式的模板中没有这个限制
props 属性值类型
- 字符串 String
-
数值 Number
静态绑定是传字符串,:
动态绑定是数值 -
布尔 Boolean
静态绑定是传字符串,:
动态绑定是布尔 - 数组 Array
- 对象 Object
<body>
<div id="box">
<ce-shi :pstr='pstr' :pnum='10' :pboo='true' :parr='parr' :pobj='pobj'></ce-shi>
</div>
<script src="../vue.js"></script>
<script>
Vue.component('CeShi', {
props: ['pstr', 'pnum', 'pboo', 'parr', 'pobj'],
template: `
<div>
<div>{{pstr}}</div>
<div>{{pnum + 10}}</div>
<div>{{pboo}}</div>
<ul>
<li :key='index' v-for='(item,index) in parr'>{{item}}</li>
</ul>
<div>
<span>{{pobj.name}}</span>
<span>{{pobj.age}}</span>
<span>{{pobj.like}}</span>
</div>
</div>
`
})
const vm = new Vue({
el: '#box',
data: {
pstr: 'yjy',
parr: [1, 2, 3],
pobj: {
name: '远近渔',
age: 18,
like: 'me'
}
}
})
</script>
</body>
2. 子组件向父组件传值
虽然可以从子组件传数据到父组件,但别用
props 传数据的原则:单项数据流,只能父传子,不要子传父
- 子组件调用
$emit()
方法触发事件 -
$emit()
第一个参数为自定义的事件名称,第二个参数为需要传递的数据 - 父组件用
v-on
监听子组件的事件
<body>
<div id="box">
<ce-shi @big='dadada'></ce-shi>
<div :style='{fontSize: font + "px"}'>{{parr}}</div>
</div>
<template id="moban">
<div>
<button @click='$emit("big")'>扩大</button>
</div>
</template>
<script src="../vue.js"></script>
<script>
Vue.component('CeShi', {
template: `#moban`,
})
const vm = new Vue({
el: '#box',
data: {
parr: '远近渔',
font: 10
},
methods: {
dadada() {
this.font += 5
}
}
})
</script>
</body>
$event是固定写法
<body>
<div id="box">
<ce-shi @big='bbb($event)'></ce-shi>
<div :style='{fontSize: font + "px"}'>{{msg}}</div>
</div>
<template id="moban">
<div>
<button @click='$emit("big", 100)'>变大</button>
</div>
</template>
<script src="../vue.js"></script>
<script>
Vue.component('CeShi', {
template: `#moban`,
})
const vm = new Vue({
el: '#box',
data: {
msg: '远近渔',
font: 10
},
methods: {
bbb(v) {
this.font += v
}
}
})
</script>
</body>
3. 兄弟组件间传值
-
兄弟之间传递数据需要通过 事件中心
用let hub = new Vue()
来作为 事件中心 -
传递数据 ,通过一个事件 触发
hub.$emit(名, 传递的数据)
-
接收数据 ,在
mounted(){}
钩子中触发hub.$on(名, (接收的值)=>{做的事})
方法 -
销毁事件 ,在父组件中通过
hub.$off(名)
方法名销毁之后无法进行传递数据
<body>
<div id="box">
<one></one>
<two></two>
<button @click='c'>禁止</button>
</div>
<script src="../vue.js"></script>
<script>
let hub = new Vue()
Vue.component('one', {
data() {
return {
num: 0
}
},
template: `
<div>
<div>one --- {{num}}</div>
<button @click='a'>+++2</button>
</div>
`,
methods: {
a() {
hub.$emit('two-b', 2)
}
},
mounted() {
hub.$on('one-a', (v) => {
this.num += v
})
}
})
Vue.component('two', {
data() {
return {
num: 0
}
},
template: `
<div>
<div>two --- {{num}}</div>
<button @click='b'>+++1</button>
</div>
`,
methods: {
b() {
hub.$emit('one-a', 1)
}
},
mounted() {
hub.$on('two-b', (v) => {
this.num += v
})
}
})
const vm = new Vue({
el: '#box',
methods: {
c() {
hub.$off('two-b')
hub.$off('one-a')
}
}
})
</script>
</body>
三、组件插槽
组件插槽的作用: 父组件向子组件传递内容(模板的内容)
因为父组件在子组件的模板里面写东西无法显示,所以使用插槽把父组件标签里面的内容传到子组件
1. 匿名插槽
插槽位置
子组件的模板里面预留 <slot></slot>
位置接收父的自定义内容
插槽内容slot
里面可以写默认的内容,父的标签里面可以自定义内容
<body>
<div id="box">
<aaa>有刺客</aaa>
<aaa></aaa>
</div>
<script src="../vue.js"></script>
<script>
Vue.component('aaa', {
template:`
<div>
<strong>ERROR:</strong>
<slot>123</slot>
</div>
`
})
const vm = new Vue({
el: '#box',
})
</script>
</body>
2. 具名插槽
- 使用
<slot>
中的"name"
属性绑定元素 - 模板里面写
<slot name='abc'></slot>
- 标签里面写
<p slot="abc">xxxxxxx</p>
- slot 属性 只能加给子组件里面的内容标签
- 如果元素没有绑定 slot 属性 ,则放到默认的插槽
<slot></slot>
- 一个个加属性太麻烦,可以放到总的
<template slot="abc"><p>xxx</p></template>
里面
<body>
<div id="box">
<aaa>
<p slot="abc">xxx</p>
<p slot="ggg">yyy</p>
<p slot="www">zzz</p>
<p>qwerqwerqwer</p>
<p>asdfasdfasdfasdf</p>
</aaa>
<aaa>
<template slot="abc">
<p>xxx</p>
<p>qwerqwerqwer</p>
<p>asdfasdfasdfasdf</p>
</template>
<template slot="ggg">
<p>123</p>
<p>321</p>
<p>213</p>
</template>
</aaa>
</div>
<script src="../vue.js"></script>
<script>
Vue.component('aaa', {
template:`
<div>
<slot></slot>
<slot name='ggg'></slot>
<strong>123</strong>
<slot name='abc'></slot>
<slot name='www'></slot>
</div>
`
})
const vm = new Vue({
el: '#box',
})
</script>
</body>
3. 作用域插槽
- 好处,既可以父用子组件的slot,又可以使slot内容不一致
- 因为子组件的东西一般都是封装好的,所以我们需要用父组件来对子组件进行加工
- 先给子组件的模板的
<slot></slot>
自定义一个属性<slot :shuxing="item"></slot>
- 然后在父组件的模板标签里面使用
<template slot-scope='slotProps'></template>
获取子组件的数据slotProps
自定义的名字,是个对象,包含子组件里面的所有slot
的属性
<body>
<div id="box">
<aaa :qwer='list'>
<template slot-scope='slotProps'>
<strong v-if='slotProps.shuxing.id==2'>{{slotProps.shuxing.name}}</strong>
<span v-else>{{slotProps.shuxing.name}}</span>
</template>
</aaa>
</div>
<script src="../vue.js"></script>
<script>
Vue.component('aaa', {
props: ['qwer'],
template: `
<div>
<div>
<li :key="item.id" v-for="item in qwer">
<slot :shuxing="item"></slot>
</li>
</div>
</div>
`
})
const vm = new Vue({
el: '#box',
data: {
list: [{
id: 1,
name: '远近渔'
}, {
id: 2,
name: '渔渔渔'
}, {
id: 3,
name: '渔渔子'
}]
}
})
</script>
</body>