组件
组件的基础使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="app">
<!-- 双闭合 组件可以重复复用 -->
<my-component></my-component>
<my-component></my-component>
<my-component></my-component>
<my-component></my-component>
<!-- 单闭合 会阻断同名组件的渲染 一般用于结束的位置,最后一次用该组件 -->
<my-component/>
</div>
<script>
//全局组件
//需要注意,在模版中data是一个函数,因为数据需要从data中调用渲染到页面,但是方法只需要匹配名称原地执行即可
Vue.component('my-component',{
data(){
return{
msg:'消息123'
}
},
template:`<h2 @click='add'>{{msg}}</h2>`,
methods:{
add:function(){
console.log(1);
}
}
})
//这里的Vue也是一个组件
let vm = new Vue({
el: '#app',
data: {
}
})
</script>
</body>
</html>
全局组件和局部组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="app">
<!-- 组件分为全局组件和局部组件 -->
<!-- 全局组件 可以创建多个全局组件 -->
<assembly></assembly>
<assembly-one></assembly-one>
<ssemb></ssemb>
<ssemb-one></ssemb-one>
</div>
<script>
//创建全局组件 使用component 里面有两个参数,第一个是组件名,第二个是显示组件内容模版
Vue.component('assembly', {
template: `<h2>这是一个全局的组件</h2>`
})
Vue.component('assembly-one', {
template: `<h2>这也是一个全局组件,注意命名写法<h2>`
})
// 定义局部组件的渲染模版
var ssemb = {
template: `<h2>这是一个局部组件</h2>`
}
var ssembs = {
template: `<h2>这也是一个局部组件</h2>`
}
let vm = new Vue({
el: '#app',
data: {
},
//局部组件只能写一个components,如果需要多个局部组件,直接使用一个变量来个组件命名,然后定义这个变量的渲染模版
components: {
'ssemb': ssemb,
'ssemb-one': ssembs
}
})
</script>
</body>
</html>
全局组件:
可以同时创建多个,命名可以使用 -
局部组件:
只能出现一个components,需要创建多个就在里面创建多个变量来给组件名称命名,然后定义这个变量的渲染模版
插槽
插槽实现了一组内容的分发的API(出口),可以理解为是内容的一个占位符,是为了将父组件中的子组件模版数据正常显示,子组件和父组件是由程序员自己定义
插槽的类型 <slot>
默认插槽
在当前的模版当中创建一个插槽,可以自动匹配模版中的内容
插槽显示内容 组件显示结构
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="app">
<!-- <my-component>这里是显示的插槽的内容</my-component> -->
<alert-box>有bug</alert-box>
</div>
<script>
// 默认插槽的使用---使用slot占位 只需要在组件标签内写入展示的具体内容就可以了
// {
// components:{
// 'MyComponent':{
// template:'<div><slot /></div>'
// }
// }
// }
Vue.component('alert-box', {
template: `
<div>
<strong>ERROR:</strong>
<slot>默认内容</slot>
</div>
`
})
let vm = new Vue({
el: '#app',
data: {
}
})
</script>
</body>
</html>
如果组件中有内容就显示组件的,如果没有内容就让他显示默认的内容
具名插槽
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="app">
<!-- 具名插槽的第一种用法 -->
<!-- <alert-box>
<p slot="header">标题信息</p>
<p>主题内容</p>
<p>主题内容</p>
<p slot="footer">底部内容</p>
</alert-box> -->
<!-- 具名插槽的第二种用法 如果一个数据的内容数量很多 可以给到父元素绑定插槽 -->
<alert-box>
<template slot="header">
<p>标题信息</p>
<p>标题信息</p>
<p>标题信息</p>
</template>
<p>主题内容</p>
<p>主题内容</p>
<p slot="footer">底部内容</p>
</alert-box>
</div>
<script>
//具名插槽:使用具名插槽可以进行名字的匹配,使相应的插槽加载相应的内容
// 就是给插槽起一个名字
Vue.component('alert-box', {
template: `
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
`
})
let vm = new Vue({
el: '#app',
data: {
}
})
</script>
</body>
</html>
作用域插槽
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="app">
<!-- 在父组件使用插槽时需要访问子组件中的数据,就可以使用作用域插槽
用法:将data变量名 作为<slot>元素的一个attribute绑定上去
<slot :[自定义变量名]="[需要传递的数据]">
<slot :count="count"></slot>
在使用组件是,通过<v-slot:插槽的名字="数据别名">的方式使用-->
<!-- 作用域插槽 -->
<my-list>
<!-- 默认插槽 -->
<template v-slot:default="slotProps">
我叫:{{slotProps.detail.name}}
我的爱好是{{slotProps.detail.love}}
</template>
</my-list>
</div>
<script>
Vue.component('myList', {
template: `
<div>
<slot :detail="detail"></slot>
</div>
`,
data: function () {
return {
detail: {
name: '张三',
love: 'coding'
}
}
}
})
let vm = new Vue({
el: "#app",
data: {
}
})
</script>
</body>
</html>
组件通信
组件的作用域是相互独立的,组件之间的数据是无法相互引用的,需要使用组件通信
父组件给子组件传值
在子组件中使用props来接受传递的参数
<!-- 父组件给子组件传值
在子组件中使用props来接受传递的参数
{
props:['name']
}
在父组件中使用子组件
<parent>
<child :name="name"></child>
</parent>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="app">
<parent></parent>
</div>
<script>
//定义父组件
Vue.component('parent', {
//在父组件中绑定子组件中
template: `
<child :name="name"></child>
`,
//父组件中的数据
data: function () {
return {
name: '张三',
age: 18
}
}
})
//定义子组件
Vue.component('child', {
//使用props接受父组件中的值
props: ['name'],
template: `
<div>{{name}}</div>
`
})
let vm = new Vue({
el: "#app",
data: {
}
})
</script>
</body>
</html>
子组件给父组件传值
<!-- 子组件给父组件传值
子组件通过$emit传递事件给父组件,父组件通过$on监听事件
子组件中定义事件
this.$emit('事件名称','传递参数')
this.$emit('add',1111)
父组件中监听事件的触发
<child @事件名称="事件触发的方法"></child>
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="app">
<parent>
<child></child>
</parent>
</div>
<script>
// 定义父组件
Vue.component('parent', {
//父组件接受子组件绑定的事件
template: `
<child :name='name' :age='age' @add2='add3'></child>
`,
data: function () {
return {
name: '张三',
age: 18
}
},
methods: {
add3: function (age) {
this.age = age
}
}
})
// 定义子组件
Vue.component('child', {
props: ['name', 'age'],
template: `
<div>
{{name}}{{age}}
<button @click='add1'>加一岁</button>
</div>
`,
methods: {
add1: function () {
//子组件注册事件
this.$emit('add2', this.age + 1)
}
}
})
let vm = new Vue({
el: '#app',
data: {
}
})
</script>
</body>
</html>
兄弟组件传值
本次使用构造函数原型链的方法,将公共属性和方法放在原型对象上
<!-- 定义事件总线
let bus = new Vue()
Vue.prototype.bus=bus
定义发送的事件
this.bus.$emit('事件名称',data)
定义接受的事件 并在回调函数中接受参数
this.bus.$on('事件名称',(data)=>{
//数据的处理
})
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="app">
<person></person>
<detail></detail>
</div>
<script>
let bus = new Vue()
Vue.prototype.bus = bus
Vue.component('person', {
template: `
<div>
<div>姓名: <input type="text" v-model="name"></div>
<div>年龄: <input type="text" v-model="count"></div>
<button @click="modify">修改</button>
</div>
`,
data() {
return {
name: '张三',
count: 10
}
},
methods: {
modify: function () {
this.bus.$emit('modify', { name: this.name, count: this.count })
}
}
})
Vue.component('detail', {
template: `
<div>我是:{{name}},今年{{count}}岁了</div>
`,
data(){
return {
name: '李四',
count: 18
}
},
mounted() {
this.bus.$on('modify', (detail) => {
this.name = detail.name
this.count = detail.count
})
}
})
let vm = new Vue({
el: '#app',
data: {
}
})
</script>
</body>
</html>
动态组件
<!--
通过使用<component>元素,动态的把组件名绑定到is特性上 可以实现动态切换
keep-alive:缓存组件
activated 和 deactivated
activated:进入组件时触发
deactivated: 退出组件时触发
include和exclude
include可以是表达式 也可以是正则 名称匹配的组件被缓存
exclude可以是表达式 也可以是正则 名称匹配的组件不被缓存
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="app">
<!-- 把要缓存的组件房间keep-alibe标签里 -->
<keep-alive>
<component :is="currentview"></component>
</keep-alive>
<button @click="changeView('A')">组件A</button>
<button @click="changeView('B')">组件B</button>
<button @click="changeView('C')">组件C</button>
<button @click="changeView('D')">组件D</button>
</div>
<script>
Vue.component('ComponentA', {
template: `<div>人生若只如初见</div>`,
created() {
console.log('组件A created');
},
activated() {
console.log('进入A被触发');
},
deactivated() {
console.log('退出A被触发');
}
})
Vue.component('ComponentB', {
template: `<div>何事秋风悲画扇</div>`,
created() {
console.log('组件B created');
},
activated() {
console.log('进入B被触发');
},
deactivated() {
console.log('退出A被触发');
}
})
Vue.component('ComponentC', {
template: `<div>此情可待成追忆</div>`,
created() {
console.log('组件C created');
},
activated() {
console.log('进入C被触发');
},
deactivated() {
console.log('退出A被触发');
}
})
Vue.component('ComponentD', {
template: `<div>只是当时已惘然</div>`,
created() {
console.log('组件D created');
},
activated() {
console.log('进入D被触发');
},
deactivated() {
console.log('退出A被触发');
}
})
let vm = new Vue({
el: '#app',
data: function () {
return {
currentview: 'ComponentC'
}
},
methods: {
changeView: function (name) {
this.currentview = `Component${name}`
}
}
})
</script>
</body>
</html>