目录
一、组件基础
二、组件的嵌套关系
1. 基础架构
2. 嵌套
三、组件注册方式
1. 局部注册:
2. 全局注册:
四、组件传递数据
1. 基础架构
2. 传递多值
3. 动态传递数据
五、组件传递多种数据类型
1. Number
2. Array
3. Object
六、组件传递Props的校验
1. 默认值
2. 必选项
一、组件基础
组件最大的优势就是可复用性。
当使用构建步骤时,我们一般将vue组件定义在一个单独的.vue文件当中,这就被叫做单文件组织(SFC)
组件组成结构 ----> 在components文件当中新建文件MyApp.vue
<template>
<div class="container">{{ message }}</div>
</template>
<script>
export default{
data(){
return{
message:'组件基础组成'
}
}
}
</script>
<!-- 让当前样式只在当前组件中生效 ,如果不加scoped那么.container将会是全局样式在任何组件当中使用-->
<style scoped>
.container{
font-size: 30px;
color: red;
}
</style>
组件引用结构-----在App.vue当中设置如下属性:
<script>
//第一步引入组件
import MyApp from './components/MyApp.vue';
export default{
//第二步:注册组件
components:{
MyApp
}
}
</script>
<template>
<!--第三步:显示组件-->
<MyApp/>
</template>
二、组件的嵌套关系
组件允许我们将UI划分为独立的、可重用的部分,并且可以对每个部分进行单独的思考。在实际应用中,组件常常被组织成层层嵌套的树状结构
这和我们嵌套HTML元素的方式类似,Vue实现了自己的组件模型,使我们可以在每个组件内封装自定义内容与逻辑。
新建pages文件夹,并创建以下文件‘
1. 基础架构
Header.vue
<template>
<h3>Header</h3>
</template>
<style scoped>
h3{
width: 100%;
height: 120px;
border: 4px solid #333;
text-align: center;
line-height: 100px;
box-sizing: border-box;
}
</style>
在App.vue当中注册
<script>
import Header from './components/Header.vue';
export default{
data(){
},
components:{
Header
}
}
</script>
<template>
<Header/>
</template>
Main.vue:
<template>
<div class="main">
<h4>Main</h4>
</div>
</template>
<style scoped>
.main{
float: left;
width: 60%;
height: 400px;
border: 4px solid #333;
text-align: center;
line-height: 100px;
box-sizing: border-box;
}
.main h4{
text-align: center;
background-color: beige;
}
</style>
Aside.vue:
<template>
<div class="aside">
<h4>Aside</h4>
</div>
</template>
<style scoped>
.aside{
float: right;
width: 30%;
height: 400px;
border: 4px solid #333;
text-align: center;
line-height: 100px;
box-sizing: border-box;
}
</style>
2. 嵌套
新建Article.vue:
<template>
<h5>Article</h5>
</template>
<style>
h5{
width:80%;
margin:0 auto;
text-align: center;
line-height: 50px;
box-sizing: border-box;
margin-top: 20px;
background:#999;
}
</style>
在main.vue里引用article.vue
<template>
<div class="main">
<h4>Main</h4>
<Article/>
<Article/>
</div>
</template>
<script>
import Article from './Article.vue';
export default{
components:{
Article
}
}
</script>
<style scoped>
.main{
float: left;
width: 60%;
height: 400px;
border: 4px solid #333;
text-align: center;
line-height: 100px;
box-sizing: border-box;
}
.main h4{
text-align: center;
background-color: beige;
}
</style>
新建item.vue:
<template>
<h5>Item</h5>
</template>
<style scoped>
h5{
width:80%;
margin: 0 auto;
text-align: center;
line-height: 100px;
box-sizing: border-box;
margin-top: 10px;
background:#999;
}
</style>
在aside.vue里引用item.vue:
<template>
<div class="aside">
<h4>Aside</h4>
<Item/>
<Item/>
</div>
</template>
<script>
import Item from './Item.vue';
export default{
components:{
Item
}
}
</script>
<style scoped>
.aside{
float: right;
width: 30%;
height: 400px;
border: 4px solid #333;
text-align: center;
line-height: 100px;
box-sizing: border-box;
}
</style>
最终效果:
三、组件注册方式
一个Vue组件在使用前需要先被“注册”,这样Vue才能在渲染模板时找到其对应的实现。组件注册有两种方式:全局注册和局部注册
1. 局部注册:
前边讲的方案就是局部注册
2. 全局注册:
我们这里使用Header.vue来进行全局注册,
①:那么首先在App.vue当中取消局部注册。
②:在main.js当中设置全局注册方式
③:最终在哪里需要就在哪里引入
全局注册虽然很方便,但有以下几个问题:
1.全局注册,但并没有被使用的组件无法在生产打包时被自动移除(也叫“tree-shaking”)。如果你全局注册了一个组件,即使它并没有被实际使用,它仍然会出现在打包后的JS文件中
2.全局注册在大型项目中使项目的依赖关系变得不那么明确。在父组件中使用子组件时,不太容易定位子组件的实现。和使用过多的全局变量一样,这可能会影响应用长期的可维护性
局部注册需要使用components选项。
四、组件传递数据
组件与组件之间不是完全独立的,而是有交集的,那就是组件与组件之间是可以传递数据的传递数据的解决方案就是props
1. 基础架构
首先我们新建一个Parent.vue:
<template>
<h3>Parent</h3>
</template>
<script>
export default{
data(){
return{
}
}
}
</script>
其次我们再新建Child.vue
<template>
<h3>Child</h3>
</template>
<script>
export default{
data(){
return{
}
}
}
</script>
我们让Parent.vue给Child.vue传值,不过在此之前我们先让Parent成为Child的父组件。
2. 传递多值
也可以传递多个值
3. 动态传递数据
注意事项:
props 传递数据,只能从父级传递到子级,不能反其道而行
五、组件传递多种数据类型
通过props传递数据,不仅可以传递字符串类型的数据,还可以是其他类型,例如:数字、对象、数组等。但实际上任何类型的值都可以作为props的值被传递。
1. Number
parent.vue:
<template>
<h3>Parent</h3>
<Child :title="message" :age="age"></Child>
</template>
<script>
import Child from './Child.vue'
export default{
data(){
return{
message:"我是动态的数据!!!",
age:20
}
},
components:{
Child
}
}
</script>
Child.vue:
<template>
<h3>Child</h3>
<p>{{ title }}</p>
<p>{{ age }}</p>
</template>
<script>
export default{
data(){
return{
}
},
props:["title","age"]
}
</script>
2. Array
parent.vue:
<template>
<h3>Parent</h3>
<Child :title="message" :age="age" :names="names"></Child>
</template>
<script>
import Child from './Child.vue'
export default{
data(){
return{
message:"我是动态的数据!!!",
age:20,
names:["张三","李四","王五"]
}
},
components:{
Child
}
}
</script>
child.vue:
<template>
<h3>Child</h3>
<p>{{ title }}</p>
<p>{{ age }}</p>
<ul>
<li v-for="(item,index) of names" :key="index">{{ item }}</li>
</ul>
</template>
<script>
export default{
data(){
return{
}
},
props:["title","age","names"]
}
</script>
3. Object
parent.vue:
<template>
<h3>Parent</h3>
<Child :title="message" :age="age" :names="names" :userInfo="userInfo"></Child>
</template>
<script>
import Child from './Child.vue'
export default{
data(){
return{
message:"我是动态的数据!!!",
age:20,
names:["张三","李四","王五"],
userInfo:{
name:"admin",
age:20
}
}
},
components:{
Child
}
}
</script>
child.vue:
<template>
<h3>Child</h3>
<p>{{ title }}</p>
<p>{{ age }}</p>
<ul>
<li v-for="(item,index) of names" :key="index">{{ item }}</li>
</ul>
<p>{{ userInfo.name }}</p>
<p>{{ userInfo.age }}</p>
</template>
<script>
export default{
data(){
return{
}
},
props:["title","age","names","userInfo"]
}
</script>
六、组件传递Props的校验
Vue组件可以更细致地声明对传入的props的校验要求。
以下例子为接收 String 类型传输 number 控制台警告:
<script>
import ComponentB from './ComponentB.vue';
export default{
data(){
return{
title:20
}
},
components:{
ComponentB
}
}
</script>
<style>
</style>
<template>
<h3>ComponentA</h3>
<ComponentB :title="title"/>
</template>
<template>
<h3>ComponentB</h3>
<p>{{ title }}</p>
</template>
<script>
export default{
data(){
return{
}
},
props:{
title:{
type:String
}
}
}
</script>
可以接收多种类型
props:{ title:{ type:[String,Number,Array,Object] } }
1. 默认值
模拟情况:传递数据的时候并没有真实传递。
数字和字符串可以直接default,但是如果是数组和对象,必须通过工厂函数返回默认值。
<template>
<h3>ComponentA</h3>
<ComponentB :title="title" :age="age" :names="names"/>
</template>
<script>
import ComponentB from './ComponentB.vue';
export default{
data(){
return{
title:"测试",
//age:20,
//names:["Tom","Bob"]
}
},
components:{
ComponentB
}
}
</script>
________________________________________________________________________________
<template>
<h3>ComponentB</h3>
<p>{{ title }}</p>
<p>{{ age }}</p>
<ul>
<li v-for="(name,index) of names" :key="index">{{ name }}</li>
</ul>
</template>
<script>
export default{
data(){
return{
}
},
props:{
title:{
type:[String,Number,Array,Object]
},
age:{
type:Number,
default:0
},
//数字和字符串可以直接default,但是如果是数组和对象,必须通过工厂函数返回默认值
names:{
type:Array,
default(){
return ["xxx"]
}
}
}
}
</script>
2. 必选项
没有传值就会提示警告。
<template>
<h3>ComponentA</h3>
<ComponentB :title="title" :age="age" :names="names"/>
</template>
<script>
import ComponentB from './ComponentB.vue';
export default{
data(){
return{
// title:"测试",
age:20,
names:["Tom","Bob"]
}
},
components:{
ComponentB
}
}
</script>
<template>
<h3>ComponentB</h3>
<p>{{ title }}</p>
<p>{{ age }}</p>
<ul>
<li v-for="(name,index) of names" :key="index">{{ name }}</li>
</ul>
</template>
<script>
export default{
data(){
return{
}
},
props:{
title:{
type:[String,Number,Array,Object],
required:true
},
age:{
type:Number,
default:0
},
//数字和字符串可以直接default,但是如果是数组和对象,必须通过工厂函数返回默认值
names:{
type:Array,
default(){
return ["xxx"]
}
}
}
}
</script>
注意:
props 是只读的,不允许修改父元素传递过来的数据。
<template> <h3>ComponentB</h3> <p>{{ title }}</p> <p>{{ age }}</p> <ul> <li v-for="(name,index) of names" :key="index">{{ name }}</li> </ul> <button @click="update">update</button> </template> <script> export default{ data(){ return{ } }, props:{ title:{ type:[String,Number,Array,Object], required:true }, age:{ type:Number, default:0 }, //数字和字符串可以直接default,但是如果是数组和对象,必须通过工厂函数返回默认值 names:{ type:Array, default(){ return ["xxx"] } } }, methods:{ update(){ console.log(this.title); this.title="新数据" } } } </script>