1、vue组件
????????什么是组件: 组件的出现,就是为了拆分Vue实例的代码量的,能够让我们以不同的组件,来划分不同的功能模块,将来我们需要什么样的功能,就可以去调用对应的组件即可。
组件化和模块化的不同:
模块化:是从代码逻辑的角度进行划分的;方便代码分层开发,保证每个功能模块的职能单一。
组件化:是从UI界面的角度进行划分的;前端的组件化,方便UI组件的重用。
2、全局组件定义方式
????????(1)、使用 Vue.extend 配合 Vue.component 方法;
? ? ? ? (2)、直接使用 Vue.component 方法;
? ? ? ? (3)、将模板字符串,定义到script标签中,同时,需要使用 Vue.component 来定义组件;
????????(4)、将模板字符串,定义到template标签中,同时,需要使用 Vue.component 来定义组件。
<!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="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id='app'>
<login></login>
</div>
<!-- <script id="login" type="x-template">
<h2>😀😀😀😀</h2>
</script> -->
<template id="login">
<!-- 在组件中 只能有一个根标签 -->
<!-- 组件的名字 不能和h5已有的标签同名 -->
<div>
<h3>😡😡😡😡😡</h3>
<h4>😳😳😳😳😳</h4>
<h5>😊😊😊😊😊</h5>
</div>
</template>
<script>
/* // 声明组件的方法一
// 先全局声明
var login = Vue.extend({
template: '<h1>登录</h1>'
});
// 再全局注册
Vue.component('login',login); */
/* // 声明组件的方法二
Vue.component('login',{
template: '<h2>😴😴😴😴😴</h2>'
}); */
//生声明组件的方法三
// 在相应的script标签中书写组件内容
Vue.component('login',{
template: '#login',
});
// 声明组件的方法四
Vue.component('login',{
template: '#login',
})
const vm = new Vue({
el: '#app',
data: {
},
methods: {
},
created(){
},
beforeMount(){
},
mounted(){
},
beforeUpdate(){
},
updated(){
},
})
</script>
</body>
</html>
3、在组件中渲染数据或者添加方法
? ? ? ? 在构件的组件中,添加data方法和methods对象,用于承载数据和方法。
<!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="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id='app'>
<button @click="flag = !flag">😏😏😏😏😏</button>
<!-- <component is="mine"></component> -->
// 通过三元运算符 判断显示哪个组件
<component :is="flag?'login':'mine'"></component>
</div>
// 创建组件
<template id="login">
<div>
<button @click="add(4)">🥺🥺🥺🥺🥺</button>
{{msg}}
</div>
</template>
// 创建组件
<template id="mine">
<div>
😹😹😹😹😹
</div>
</template>
<script>
Vue.component('mine',{
template: '#mine',
});
Vue.component('login',{
template: '#login',
// 组件下的数据
data(){
return {
msg: '😇😇😇😇😇',
}
},
// 组件下的方法
methods:{
add(n){
this.msg = this.msg.repeat(n);
}
}
})
const vm = new Vue({
el: '#app',
// 父元素的数据
data: {
flag: true,
},
methods: {
},
created(){
},
beforeMount(){
},
mounted(){
},
beforeUpdate(){
},
updated(){
},
})
</script>
</body>
</html>
值得注意的是组件中的data属性必须定义为一个方法并返回一个对象,这样可以消除数据间的影响
4、使用components属性定义局部子组件
????????和之前的过滤器函数与自定义指令类似,通过在实例化vue对象平级的属性data和methods后添加components。
const vm = new Vue({
el: '#app',
data: {
},
methods: {
},
components: {
// 组件名
'my-header': {
// 创建组件的id
template: '#myHeader',
}
},
created(){
},
beforeMount(){
},
mounted(){
},
beforeUpdate(){
},
updated(){
},
});
5、给组件添加动画效果
? ? ? ??mode="out-in"的动画属性只能对组件起作用,而且transition标签下也只能有一个根元素
<!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="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<style>
.v-enter,.v-leave-to{
transform: translateX(200px);
}
.v-enter-active,.v-leave-active{
transition: all 1s;
}
.v-enter-to,.v-leave{
transform: translateX(0px);
}
</style>
</head>
<body>
<div id='app'>
<button @click="flag = !flag"> 点我登录</button>
<transition mode="out-in">
<!-- <component :is="flag?'login':'mine'"></component> -->
<login v-if="flag"></login>
<mine v-else></mine>
</transition>
</div>
<template id="login">
<div>
<button @click="add(3)">🥺🥺🥺🥺🥺</button>
{{msg}}
</div>
</template>
<template id="mine">
<div>
😹😹😹😹😹
</div>
</template>
<script>
// 定义组件
Vue.component('mine',{
template:"#mine",
})
Vue.component('login',{
template:"#login",
// 为什么组件中的data属性必须定义为一个方法并返回一个对象
// 数据隔离
data(){
return{
msg:'😇😇😇😇😇',
}
},
beforeCreate(){
console.log(1);
},
created(){
console.log(2);
},
beforeDestroy(){
console.log('beforeDestroy');
},
destroyed(){
console.log('destroyed');
},
methods: {
add(n){
this.msg = this.msg.repeat(n);
},
},
})
const vm = new Vue({
el: '#app',
data: {
flag: true,
},
methods: {
},
created(){
},
beforeMount(){
},
mounted(){
},
beforeUpdate(){
},
updated(){
},
})
</script>
</body>
</html>
6、slot插槽
????????插槽就是子组件中的提供给父组件使用的一个占位符,用<slot></slot> 表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的<slot></slot>标签。
? ? ? ? 分为:具名插槽和默认插槽。
<!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="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.staticfile.org/axios/0.18.0/axios.min.js"></script>
<style>
ul{
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
li{
list-style: none;
width: 18%;
}
li img{
width: 100%;
}
</style>
</head>
<body>
<div id='app'>
<!-- <h2>免费课程</h2> -->
<course :type="type" page-size="10">
<template v-slot:header>
免费
</template>
默认
</course>
<!-- <h2>精品课程</h2> -->
<course type="boutique" >
<template v-slot:header>
精品
</template>
默认
</course>
<!-- <h2>折扣课程</h2> -->
<course type="discount" >
<template v-slot:header>
折扣
</template>
默认
</course>
</div>
<template id="course">
<div>
<!-- 具名插槽 -->
<h2><slot name="header"></slot>课程</h2>
<ul>
<li v-for="item in courseList">
<img :src="item.coverFileUrl" alt="">
<div>{{item.courseTitle}} </div>
<div> {{item.learningNum}}</div>
<div>免费 </div>
</li>
</ul>
<!-- 默认插槽 -->
<slot></slot>
</div>
</template>
<script>
Vue.component('course',{
template:"#course",
data(){
return{
courseList:[]
}
},
// 接受传值
props:{
// 自己定义接受
type:String,
// size:Number,
// pageSize:Number,
// 定义多个数据类型
// pageSize:[Number,String],
// 设置默认值
pageSize:{
type:[Number,String],
// default:5
default(){
return 5
}
}
},
methods:{
getCourseList(type='free',pageSize=5,pageNum=1){
let form = new URLSearchParams()
form.append('type',type)
form.append('pageSize',pageSize)
form.append('pageNum',pageNum)
return axios.post('http://1.117.81.216:8086/weChat/applet/course/list/type',form);
}
},
created(){
this.getCourseList(this.type,this.pageSize,1).then(res=>{this.courseList = res.data.rows})
},
})
const vm = new Vue({
el: '#app',
data: {
type:'free'
},
methods: {
},
})
</script>
</body>
</html>
?????????父级的填充内容如果指定到子组件的没有对应名字插槽,那么该内容不会被填充到默认插槽中。如果子组件没有默认插槽,而父级的填充内容指定到默认插槽中,那么该内容就“不会”填充到子组件的任何一个插槽中。如果子组件有多个默认插槽,而父组件所有指定到默认插槽的填充内容,将“会” “全都”填充到子组件的每个默认插槽中。
|