一、Vue组件
什么是组件:组件的出现,就是为了拆分Vue实例的代码量的,能够让我们以不同的组件,来划分不同的功能模块。将来我们需要什么样的功能,就可以去调用对应的组件即可。
**重点:
**组件化和模块化的不同:
模块化:是从代码逻辑的角度进行划分的;方便代码分层开发,保证每个功能模块的职能单一
(高内聚,低耦合) 原理:
高内聚: 功能以及连接比较高的放在同一个js文件中,低耦合:让两个js文件互不影响
组件化:是从Ul界面的角度进行划分的;前端的组件化,方便UI组建的重用
全局组件定义的四种方式:
1、使用 Vue.extend 配合 Vue.component 方法:
<body>
<!-- 第一种方法 -->
<div id='app'>
<!-- 函数调用的是自定义的名字 -->
<login123></login123>
</div>
<script>
//login999是变量的声明
var login999 = Vue.extend({
template:'<h1>登录</h1>'
})
// Vue.component 两个参数 参数1、自定义名字 参数2、声明的变量
Vue.component('login123',login999)
const vm = new Vue({
el: '#app',
data: {
},
methods: {
}
})
</script>
</body>
2、直接使用 Vue.component 方法:
<body>
<!-- 全局定义的第二种方法 -->
<!-- 直接使用 Vue.component -->
<div id='app'>
<!-- 自定义的名字放在html中当标签使用 -->
<login></login>
</div>
<script>
// 两个参数 参数1、自定义名字(调用也是他) 参数2、一个对象里面有一个参数 template
Vue.component('login',{
template:'<h1>请登录</h1>'
})
const vm = new Vue({
el: '#app',
data: {
},
methods: {
}
})
</script>
</body>
3、将模板字符串,定义到script标签种,同时,需要使用 Vue.component 来定义组件:
<body>
<!-- 全局定义的第三种方法 -->
<div id='app'>
<!-- 自定义名字的调用 -->
<name123></name123>
</div>
<!-- 模板类型 type='x-template' 定义标识符 id="tmpl" 产生关联 -->
<script id="name" type="x-template">
<div><a href="#">登录跳转</a></div>
</script>
<script>
// 两个参数:1、自定义名字 2、对象 对象里面有一个模板参数主要是与模板类型里面的id='name'建立联系
Vue.component('name123',{
template:'#name'
})
const vm = new Vue({
el: '#app',
data: {
},
methods: {
}
})
</script>
</body>
4、重点(常用)Vue.component(‘自定义名字’,{}) 可以定义 全局的还是私有的
注意:不能将HTML5的标签当作id ,只能包含一个根标签
注意:组件中的DOM结构,有且只能有唯一的根元素(Root Element)来进行包裹!
<body>
<!-- 全局定义 -->
<!-- <div id='app'>
自定义的名字
<name></name>
</div>
<template id="name">
<div>
11111
<div>22222</div>
<div>33333</div>
</div>
</template> -->
<div id="app1">
<name1></name1>
</div>
<template id="name1">
<div>11111
<div>22222</div>
<div>33333</div>
</div>
</template>
<script>
// Vue.component('name',{
// template:'#name'
// })
const vm = new Vue({
el: '#app1',
data: {
},
methods: {
},
// 私有定义
components:{
name1:{
template:'#name1'
}
}
})
</script>
</body>
5、组件化展示数据和响应事件
- 在组件中,data需要被定义为一个方法
- 在子组件中,如果将模板字符串,定义到了script标签中,
- 那么,要访问子组件身上的data属性中的值,需要使用this来访问;
【重点】为什么组件中的data属性必须定义为一个方法并返回一个对象
解释:数据隔离
避免组件被复用时,数据存在引用关系
使用component标签,来引用组件,并通过:is属性来指定要加载的组件:
<style>
#app{
width: 600px;
margin: auto;
}
.v-enter{
transform: translateX(500px);
}
.v-enter-to{
transform: translateX(0);
}
.v-enter-activeP{
transition: all 2s;
}
.v-leave{
transform: translateX(0);
}
.v-leave-to{
transform: translateX(-500px);
}
.v-leave-active{
transition: all 2s;
}
</style>
</head>
<body>
<div id='app'>
<button @click="flag">{{msg1}}</button>
<!-- mode:只能用于组件 -->
<!-- 使用component标签,来引用组件,并通过:is属性来指定要加载的组件: -->
<!-- <component :is="flag?'login':'mine'"></component> -->
<!-- <name123>{{msg1}}</name123> -->
<transition mode="in-out">
<!-- <name v-if="flag1"></name> -->
<!-- <div v-if="flag1">1</div> -->
<!-- <div v-else="flag1">2</div> -->
<component :is="flag1? 'name':'name123'"></component>
<!-- <name v-if="flag1"></name>
<name123 v-else></name123> -->
</transition>
<transition mode="out-in">
<!-- <name v-if="flag1"></name> -->
<!-- <div v-if="flag1">1</div> -->
<!-- <div v-else="flag1">2</div> -->
<component :is="flag1? 'name':'name123'"></component>
</transition>
<transition mode="in-out">
<name v-if="flag1"></name>
</transition>
<!-- <name123>{{msg1}}</name123> -->
</div>
<!-- 动画效果 -->
<template id="name">
<div>
<button @click="add(1)">添加</button>
<div>熬夜天数{{num}}</div>
<div>{{msg}}</div>
</div>
</template>
<tempalte id="name123">
<div>
减少
</div>
</tempalte>
<script>
Vue.component('name123',{
template:'#name123'
})
Vue.component('name',{
template:'#name',
// 在组件中,data需要被定义为一个方法
// 在子组件中,如果将模板字符串,定义到了script标签中,
// 那么,要访问子组件身上的data属性中的值,需要使用this来访问;
// 【重点】为什么组件中的data属性必须定义为一个方法并返回一个对象
// 解释:数据隔离
data(){
return{
msg:'今天不能睡!!',
num: null,
}
},
methods:{
add(number1){
if(this.num < 10){
this.num+=number1
}else{
alert('催死!!!')
}
}
}
})
const vm = new Vue({
el: '#app',
data: {
flag1:true,
msg1:'今晚早点睡'
},
methods: {
flag(){
this.flag1 = !this.flag1
}
}
})
</script>
6、组件化数据请求以及插槽的使用
mode:“out-in” 只能应用于组件,而HTML标签使用则不生效
插槽的使用
slot默认插槽
所谓具名插槽,顾名思义就是起了名字的插槽。有时我们需要多个插槽,例如当我们想使用某种通用模板:
例如:slot name = “name” 具名插槽(定义一个名字)
插槽是什么?
插槽就是子组件中的提供给父组件使用的一个占位符,用 表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的标签。简单理解就是子组件中留下个“坑”,父组件可以使用指定内容来补“坑”。以下举例子帮助理解。
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- <script src="https://unpkg.com/vue-router@3.0.0/dist/vue-router.js"></script> -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<style>
ul{
display: flex;
flex-wrap: wrap;
justify-content: space-around;
width: 1200px;
margin: auto;
}
li{
list-style: none;
width: 18%;
}
img{
width: 100%;
}
h2{
text-align: center;
}
</style>
</head>
<body>
<div id='app'>
<course :type="type" page-size='10' page-num='1'>
<!-- 具名插槽 -->
<template v-slot:header>
<h2>头部</h2>
</template>
<template v-slot:footer>
<h2>底部</h2>
</template>
</course>
<course :type="type1" page-size='5' page-num='1'></course>
<course :type="type2" page-size='5' page-num='1'></course>
</div>
<template id="course_num">
<div>
<!-- 默认插槽 -->
<slot></slot>
<!-- 具名插槽 -->
<slot name="header"></slot>
<ul>
<li v-for="(item,index) in list" :key="item.courId">
<img :src="item.coverFileUrl" alt="">
<div>{{item.courseTitle}}</div>
<div>共{{item.learningNum}}人</div>
<div v-if="item.isFree==1">免费</div>
</li>
</ul>
<slot name="footer"></slot>
</div>
</template>
<script>
Vue.component('course',{
template:'#course_num',
props:{
//可以定义多种类型
// 自定义参数
type:String,
pageSize:[Number,String],
pageNum:[Number,String]
// pageNum:{
// type:Number,
// // default(){
// // return 20
// // }
// }
},
data(){
return {
list:[],
}
},
methods:{
getList(type,pageSize,pageNum){
var url = new URLSearchParams()
url.append('type',type)
url.append('pageSize',pageSize)
url.append('pageNum',pageNum)
return axios.post('http://wkt.shangyuninfo.cn/weChat/applet/course/list/type',url)
}
},
created(){
console.log(this.type);
this.getList(this.type,this.pageSize,this.pageNum).then(res=>{
console.log(res);
this.list = res.data.rows
})
}
})
const vm = new Vue({
el: '#app',
data: {
type:'free',
type1:'boutique',
type2:'discount',
},
methods: {
}
})
</script>
</body>
7、方法事件对象
<body>
<div id='app'>
<!-- 方法事件对象 $event -->
<button @click="add(1,$event)">添加</button>
{{num}}
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
num:6,
},
methods: {
add(num1,event){
this.num+=num1
console.log(event);
}
}
})
</script>