一、创建Vue组件的四种方式
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title></title>
<script src="bootstrap-3.4.1-dist/vue.min.js"></script>
</head>
<body>
<div id='app'>
<tem1></tem1>
<tem2></tem2>
<tem3></tem3>
<tem4></tem4>
</div>
<script id="tem3" type="x-template">
<h2>这是第三种方式</h2>
</script>
<template id="tem4">
<div>
这是第四种方式,我在body中
</div>
</template>
<script>
//1
var tem = Vue.extend({
template: '<h2>这是第一种方式</h2>'
})
// Vue.component("组件名称",组件内容)
Vue.component("tem1", tem)
//2
Vue.component('tem2', {
template: '<h2>我是第二种方式</h2>'
})
//3.
Vue.component('tem3', {
template: "#tem3",
})
//4
Vue.component('tem4', {
template: "#tem4",
data() {
return {
}
},
methods: {
}
})
const vm = new Vue({
el: '#app',
data: {
},
methods: {
}
})
</script>
</body>
</html>
二、切换组件
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title></title>
<script src="bootstrap-3.4.1-dist/vue.min.js"></script>
</head>
<body>
<div id='app'>
<father></father>
<son></son>
</div>
<template id="father">
<div>
父组件
</div>
</template>
<template id="son">
<div>
子组件
</div>
</template>
</body>
<script>
Vue.component('father', {
template: '#father',
data() {
return {
}
},
methods: {
}
})
Vue.component('son', {
template: '#son',
data() {
return {
}
},
methods: {
}
})
const vm = new Vue({
el: '#app',
data: {
},
methods: {
}
})
</script>
</html>
三、组件的切换
使用:is属性来切换不同的子组件,并添加切换动画
组件实例定义方式:
// 登录组件
const login = Vue.extend({
template: `<div>
<h3>登录组件</h3>
</div>`
});
Vue.component('login', login);
// 注册组件
const register = Vue.extend({
template: `<div>
<h3>注册组件</h3>
</div>`
});
Vue.component('register', register);
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: { comName: 'login' },
methods: {}
});
使用component标签,来引用组件,并通过:is属性来指定要加载的组件:
<div id="app">
<a href="#" @click.prevent="comName='login'">登录</a>
<a href="#" @click.prevent="comName='register'">注册</a>
<hr>
<transition mode="out-in">
<component :is="comName"></component>
</transition>
</div>
添加切换样式:
<style>
.v-enter,
.v-leave-to {
opacity: 0;
transform: translateX(30px);
}
.v-enter-active,
.v-leave-active {
position: absolute;
transition: all 0.3s ease;
}
h3{
margin: 0;
}
</style>
四、slot插槽
什么是插槽?
插槽就是子组件中的提供给父组件使用的一个占位符,用<slot></slot> 表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的<slot></slot>标签。
五、具名插槽
<template id="course">
//定义
<slot name="header"></slot>
</template>
<template v-slot:footer>
//使用
课程底部
</template>
六、父组件传值子组件
- 接受父组件传值
设置props属性就可以接受父组件传值
示例:
// html部分
<son :parent-msg='msg' :list='list'></son>
<template id='myComTemp'>
<div>
<button @click='changeMsg'>修改parentMsg</button>
<h1>你好{{parentMsg}}</h1>
<ul>
<li v-for='item in list'>{{item.name}}</li>
</ul>
</div>
</template>
// 组件定义部分
var vm = new Vue({
el: '#app',
components: {
son: {
template: '#myComTemp',
// 定义父组件传过来的值
props: ['parentMsg', 'list']
}
}
})
- 设置传递类型
props: {
// 规定了父组件只能传对象类型
prop1:Object
// 可以设置多个类型,可以传Number也可以传String
parentMsg: [Number, String],
list: {
// 设置类型
type: Array,// [Array,String]
// 设置默认值的时候必须使用函数,原理和data必须使用函数是一样的
default: function () {
return [{
name: '这个一个默认的名字'
}]
}
},
}
- 属性的继承和传递
属性继承的特征:
父组件的属性会覆盖子组件的属性
class 和 style 会进行合并,不会覆盖
设置禁用继承
加在子组件上的属性,使用了这个属性之后会阻止组件继承父组件的属性,但是class和style除外
inheritAttrs: false
在组件内可以使用$attrs获取父组件传过来的属性
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<style>
.parent-class {
background-color: bisque;
color: red
}
.son-class {
color: aquamarine
}
</style>
</head>
<body>
<div id='app'>
<!-- 如果想传递一个非字符串类型,必须用数据绑定的方式 -->
<!--
属性继承的特征:
父组件的属性会覆盖子组件的属性
class 和 style 会进行合并,不会覆盖
-->
<!-- 通过这种方式就可以为子组件设置一些属性 -->
<son :parent-msg='msg' required class="parent-class" name='fuzujian'></son>
</div>
<template id='myComTemp'>
<div name='zizujian' class='son-class'>
<button @click='changeMsg'>修改parentMsg</button>
<input type="text" :name='$attrs.name' >
<h1>你好{{parentMsg}}</h1>
<ul>
<li v-for='item in list'>{{item.name}}</li>
</ul>
</div>
</template>
<script>
var vm = new Vue({
el: '#app',
data: {
msg: '这个父组件的数据',
list: [{
name: '张三'
},
{
name: '李四'
},
{
name: '王五'
},
]
},
components: {
son: {
template: '#myComTemp',
// 使用了这个属性之后会阻止组件继承父组件的属性,但是class和style除外
inheritAttrs: false,
data() {
return {
sonMsg: '你好'
}
},
methods: {
changeMsg() {
console.log(this.$attr)
console.log(this.parentMsg);
}
},
props: {
// 可以设置多个类型
parentMsg: [Number, String],
list: {
type: Array,
// 设置默认值的时候必须使用函数,原理和data必须使用函数是一样的
default: function () {
return [{
name: '这个一个默认的名字'
}]
}
},
}
}
}
})
</script>
</body>
</html>
- 注意事项
data和props的区别
data是组件私有的,props是父组件传过来的
data是可以修改的,props是只读的