02-全局组件和局部组件的使用
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<cpn></cpn>
</div>
<script src="../js/vue.js"></script>
<script type="text/javascript">
//ES6 ``
//1创建组件构造器对象
//extend创建一个组件构造器 通常在创建组件构造器时,传入template代表我们自定义组件的模板
//该模板就是在使用组件的地方,要显示的HTML代码
const cpnc = Vue.extend({
template:`
<div>
<h2>我是哈哈哈</h2>
</div>
`
})
//2.注册组件(全局组件 ,意味着可以在多个vue的实例下面使用)
//怎么注册的组件才是局部组件
Vue.component('cpn',cpnc)
const app = new Vue({
el:'#app',
data:{
message:"你好!"
},
component:{
cpn:cpnc
}
})
</script>
</body>
</html>
当我们通过调用Vue.component()注册组件时,组件的注册时全局的
如果我们注册的某个组件时挂载在,某个实例中, 那么就是一个局部组件
03父组件和子组件
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<cpn2></cpn2>
</div>
<script src="../js/vue.js"></script>
<script>
//1.创建第一个组件(子组件)
const cpnc1 = Vue.extend({
template:`
<div>
<h2>我是标题1</h2>
<p>哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈</p>
</div>`
})
//2创建第二个组件构造器(父组件)
const cpnc2 = Vue.extend({
template:`
<div>
<h2>我是标题2</h2>
<p>红红火火恍恍惚惚呵呵哈哈哈呵呵哈哈哈哈哈哈哈呵呵哈哈哈</p>
<cpn1></cpn1>
</div>`,
components:{
cpn1:cpnc1
}
})
//root组件
const app = new Vue({
el:'#app',
data:{
message:"你好!"
},
components: {
cpn2:cpnc2
}
})
</script>
</body>
</html>
组件和组件之间存在层级关系 而其中一种非常重要的关系就是父子组件的关系
父子组件的错误用法,以子标签的形式在Vue实例中使用
因为当子组件注册到父组件的component中时Vue会编译好父组件的模块
该模板的内容已经决定了父组件将要渲染的HTML (相当于父组件中已经有了子组件中的内容了)
是只能在父组件中被识别的
类似这种用法,是会被浏览器忽略的
组件的语法糖注册方式
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<cpn1></cpn1>
<cpn2></cpn2>
</div>
<script src="../js/vue.js"></script>
<script type="text/javascript">
//1.全局组件注册的语法糖
//2.创建组件构造器
// const cpnc1 = Vue.extend()
//2.注册组件
Vue.component('cpn1',{
template:`
<div>
<h2>我是标题1</h2>
<p>哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈</p>
</div>`
})
//注册局部组件的语法糖
//Vue为了简化这个过程,提供了注册的语法糖
//主要是省去了调用Vue.extend()步骤,而是可以直接使用一个对象来代替
const app = new Vue({
el:'#app',
data:{
message:"你好!"
},
components:{
'cpn2':{
template:`
<div>
<h2>我是标题1</h2>
<p>呵呵呵呵</p>
</div>`
}
}
})
</script>
</body>
</html>
Vue为了简化注册方式,提供了语法糖
主要是省去了调用Vue.extend()的步骤,而是可以直接使用一个对象来代替
组件模板的分离写法
刚才,我们通过语法糖简化了Vue组件的注册过程,另外还有一个地方的写法比较麻烦,就是tamplate模板写法
如果我们能将其中的HTML代码抽离出来,然后挂载到对应的组件上,必然结构会变得非常清晰
Vue提供了两种方案来定义HTML模板的内容
1,使用script标签
2,使用template标签
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<cpn></cpn>
</div>
<!-- 1 script标签-->
<!-- <script type="text/x-template" id="cpn">
<div>
<h2>我是标题哈哈哈</h2>
<p>我是内容呵呵呵</p>
</div>
</script> -->
<!-- 2.template标签 -->
<template id="cpn">
<div>
<h2>我是标题哈哈哈</h2>
<p>呵呵呵呵呵</p>
</div>
</template>
<script src="../js/vue.js"></script>
<script type="text/javascript">
Vue.component('cpn',{
template:'#cpn'
})
const app = new Vue({
el:'#app',
data:{
message:"你好!"
}
})
</script>
</body>
</html>
组件中的数据存放问题
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<cpn></cpn>
</div>
<template id="cpn">
<div>
<h2>{{title}}</h2>
<p>呵呵呵呵呵</p>
</div>
</template>
<script src="../js/vue.js"></script>
<script type="text/javascript">
Vue.component('cpn',{
template:'#cpn',
data(){
return{
title:'avc'
}
}
})
const app = new Vue({
el:'#app',
data:{
message:"你好!"
}
})
</script>
</body>
</html>
组件中的数据存放在哪里呢
组件对象也有一个data属性(也可以有methods等属性,下面我们有用到)
只是这个data属性必须是一个函数
而且这个函数返回一个对象,对象内部保存着数据
为什么data是一个函数
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<cpn></cpn>
<cpn></cpn>
<cpn></cpn>
</div>
<template id="cpn">
<div>
<h2>当前计数 {{count}}</h2>
<button @click = 'btn'>+</button>
<button @click = 'btns' v-bind:disabled = "count <= 1">-</button> </button>
</div>
</template>
<script src="../js/vue.js"></script>
<script type="text/javascript">
//1注册组件
Vue.component('cpn',{
template:'#cpn',
data(){
return {
count:0
}
},
methods:{
btn(){
this.count++
},
btns(){
this.count--
}
}
})
const app = new Vue({
el:'#app',
data:{
message:"你好!"
},
})
</script>
</body>
</html>
我们用了计算加减案例来具体说明
首先,如果不是一个函数,Vue就会直接报错
其次,愿意是在于Vue让每个组件对象都返回一个新的对象,因为如果是同一个对象的,组件在多次使用的时候就会受影响
父组件对子组件的传递
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<cpn :mess = 'message' :cmoves = 'moves'></cpn>
</div>
<template id="tam">
<div>
<li v-for = 'item in cmoves'>{{item}}</li>
<h2>{{mess}}</h2>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
//2创建第二个组件构造器(父组件)
//父传子 : props
const cpn = Vue.extend({
template: '#tam',
// props:['cmoves','mess'] //传递数组方式
props:{
//类型的限制
// cmoves:Array,
// mess:String,
//2提供一些默认值,以及必传值
mess:{
type:String,
default:'aaa',
required:true
},
//类型是对象或者数组时,默认值必须是一个函数
cmoves:{
type:Array,
default(){
return {}
}//vue2.5.2以下这样的写法都是不会错
}
}
})
const app = new Vue({
el:'#app',
data:{
message:"你好!",
moves :['海王','海贼王','海尔兄弟']
},
components: {
cpn
}
})
</script>
</body>
</html>
在上衣节中,我们提到了子组件是不能引用父组件或者Vue实例的
但是,在开发中,往往一些数据确实需要从上层传递到下层
比如在一个页面中,我们从服务器请求到了数据
其中一部分数据,并非是我们整个页面的大组件来展示的,而是需要下面的子组件进行展示
这个时候,并不会让子组件再次发送一个网络请求,而是直接让大组件把数据传递给小组件
我们可以通过props向子组件传递数据
通过事件向父组件发送消息