一、组件化的基本使用
组件构造基本步骤
1.创建组件构造器对象
2.注册组件
3.使用组件
代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="../js/vue.js"></script>
<div id="app">
<!--3.使用组件-->
<my-cpn></my-cpn>
<my-cpn></my-cpn>
</div>
<!--下面的这个标签组件不会解析,因为必须放在vue实例里面-->
<my-cpn></my-cpn>
<script>
//ES6中可以使用 ` `来定义字符串,而且能换行定义
//1.创建组件构造器对象
const cpnC = Vue.extend({
template:`<div>
<h2>hhhhh</h2>
<p>xxxxxx</p>
</div> `
});
//2.注册组件
Vue.component('my-cpn',cpnC);
const app = new Vue({
el: '#app',
data: {
message: 'helloWorld!'
}
});
</script>
</body>
</html>
全局组件和局部组件
全局组件,意味着可以在多个vue实例下使用。
局部组件,只能在对应注册的实例中使用。
代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="../js/vue.js"></script>
<div id="app">
<cpn></cpn>
<cpn></cpn>
<cpn></cpn>
<cpn></cpn>
</div>
<div id="app2">
<!-- <cpn></cpn>
<cpn></cpn>
<cpn></cpn>
<cpn></cpn> -->
</div>
<script>
//1.创建一个组件构造器
const cpnC=Vue.extend({
template:`
<div>
<h2>我是哈哈</h2>
<p>我是内容</p>
</div>
`
});
//2.全局组件,意味着可以在多个vue实例下使用
//Vue.component('cpn',cpnC);
//??怎末注册的组件才是局部组件。只要去相应的vue实例里面注册就是了
const app = new Vue({
el: '#app',
data: {
message: 'helloWorld!'
},
components:{
cpn:cpnC
}
});
const app2 = new Vue({
el: '#app2',
data: {
message: 'helloWorld!'
}
});
</script>
</body>
</html>
上面组件只在app中注册了,所以只能再app这个实例中使用,而不能再app2中使用。
组件的语法糖注册方法
代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="../js/vue.js"></script>
<div id="app">
<cpn></cpn>
<cpn2></cpn2>
</div>
<script>
//之前我们是这样来创建组件的
//1.创建一个组件构造器
/* const cpnC=Vue.extend({
template:`
<div>
<h2>我是哈哈</h2>
<p>我是内容</p>
</div>
`
}); */
//2.全局注册组件
/* Vue.component('cpn',cpnC); */
//下面简写语法
//全局注册组件语法糖,可以直接将extend中的内容拿过来
Vue.component('cpn',{
template:`
<div>
<h2>我是哈哈ha</h2>
<p>我是内容</p>
</div>
`
});
const app = new Vue({
el: '#app',
data: {
message: 'helloWorld!'
},
//局部注册组件语法糖
components:{
'cpn2':{
template:`
<div>
<h2>我是哈哈ha</h2>
<p>我是内容hhhh</p>
</div>
`
}
}
});
</script>
</body>
</html>
父组件和子组件
代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="../js/vue.js"></script>
<div id="app">
<cpn2></cpn2>
<cpn1></cpn1>
</div>
<script>
//1.创建第一个组件构造器(子组件)
const cpnC1 = Vue.extend({
template:`
<div>
<h2>我是内容1</h2>
<p>我是段落1<p>
</div>
`
});
//2.创建第二个组件构造器(父组件)
const cpnC2 = Vue.extend({
template:`
<div>
<h2>我是内容2</h2>
<p>我是段落2<p>
<cpn1></cpn1>
</div>
`,
//在这里可以进行组件一(子组件)的注册,然后我们就可以在上边定义模板的时候使用组件一了
components:{
cpn1:cpnC1
}
});
const app = new Vue({
el: '#app',
data: {
message: 'helloWorld!'
},
//进行组件二(父组件)的局部注册(注意:这里如果没有对cpn1进行局部注册是不能在这个vue实例里面用的,还是只能在组件二里面使用)
components:{
cpn2:cpnC2,
cpn1:cpnC1
}
});
</script>
</body>
</html>
二、组件通信
父组件传子组件
关键字:props
代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="../js/vue.js"></script>
<template id="cpn">
<!--在这个模板里就只能用自己定义在props中的变量名-->
<div>
<p>{{cmessage}}</p>
<ul>
<li v-for=" item in childmovies">{{item}}</li>
</ul>
</div>
</template>
<div id="app">
<!--这样就完成了父组件向子组件传递的作用,此时props中的两个变量都有了内容-->
<!--这里注意一定要用v-bind,不然他会把后边的movies当成字符串来传给自己-->
<cpn v-bind:childmovies="movies" :cMessage="message"></cpn>
</div>
<script>
//父传子通过 props
const cpn={
template:'#cpn',
//这是数组写法,props还有很多写法
//props:['childmovies','cmessage'],
props:{
//类型限制,单独这样写
//childmovies:Array,
//cmessage:String,
//还可提供默认值,另一种写法,对象写法
cmessage:{
//类型限制
type:String,
//默认值,当没设置父组件的数组传过来,就使用
default:"aaaaa",
//表示这个值必须传,不传会报错
required:true
},
childmovies:{
type:Array,
//default:["saber","acher"]//如果是数组,用这样的方法来写默认值会报错
//所以如果类型是对象或者数组就需要用函数的形式来设置默认值
default(){
return ["saberxxx","acher"]
}
}
},
data(){
return { }
}
}
const app = new Vue({
el: '#app',
data: {
message: "helloWorld!",
//下面这个数据是不能给子组件用的,但如果我们要把这数据拿给子组件去展示又怎末办呢
movies:['海王','欧拉']
},
components:{
cpn
}
});
</script>
</body>
</html>
子组件传父组件
关键字:$emit
代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="../js/vue.js"></script>
<!--子组件模板-->
<template id="cpn">
<div>
<h2>
{{cinfo}}
</h2>
<button v-for="item in categories" @click="btnClick(item)">{{item.name}}</button>
</div>
</template>
<!--父组件-->
<div id="app">
<!--父组件通过v-on 来监听接受,再通过父组件定义的一个方法来处理-->
<!--注意这里的方法虽然没加括号但不是默认传递的event事件而是转递了item这个对象-->
<cpn :cinfo="info" @itemclick="cpnClick"></cpn>
</div>
<script>
//子组件
const cpn={
template:'#cpn',
data(){
return {
categories:[
{id:'aaa',name:'hot',age:18},
{id:'bbb',name:'slow',age:19},
{id:'ccc',name:'cho',age:20}
]
}
},
props:{
cinfo:{
type:Object,
default(){
return {};
}
}
},
methods: {
btnClick(item){
//这里演示了下点击事件,但是我们要怎样告诉父组件这个事件?
console.log(item.name);
//通过这样来告知父组件,通过这种方式发射事件, 这之后还可以添加一个参数 这里是item,
this.$emit('itemclick',item);
}
},
}
//父组件
const app = new Vue({
el: '#app',
data: {
message: 'helloWorld!',
info:{
name:'zhangheng',
age:18,
height:1.88
}
},
components:{
cpn
},
methods: {
//测试接受,并打印下item对象
cpnClick(item){
console.log(typeof item);
console.log("子组件你是不是点击了下",item);
}
},
});
</script>
</body>
</html>
三、组件访问
父访问子
关键字:$children和$refs
代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="../js/vue.js"></script>
<template id="cpn">
<div>
<h2>我是子组件</h2>
</div>
</template>
<div id="app">
<cpn></cpn>
<cpn ref="aaa"></cpn>
<button @click="btnClick">点击一下</button>
</div>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'helloWorld!'
},
methods:{
btnClick(){
//1.$children的讲解
//这里的this.$children创建的是一个数组,可以通过这种方式来访问子组件中的属性或者一些方法
//this.$children[0].showMessage();
//console.log(this.$children);
for(let c of this.$children){
//console.log(c.name);
c.showMessage();
}
//2.$refs的讲解,对象类型,默认是一个空对象。当有组件标签上加上了ref="xxx",这时这个对象才会返回这个组件的一些属性
//console.log(this.$refs);
//console.log(this.$refs.aaa.name);
//this.$refs.aaa.showMessage();
}
},
components:{
cpn:{
template:'#cpn',
data(){
return {
name:'我是子组件的name'
}
},
methods: {
showMessage(){
console.log("showMessage");
}
},
}
}
});
</script>
</body>
</html>
子访问父
关键字:$parent
代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="../js/vue.js"></script>
<template id="cpn">
<div>
<h2>我是子组件</h2>
<button @click="btnClick">按钮</button>
</div>
</template>
<div id="app">
<cpn></cpn>
</div>
<script>
const app = new Vue({
el: '#app',
data: {
message: '我是父的helloWorld!'
},
components:{
cpn:{
template:'#cpn',
methods: {
btnClick(){
console.log(this.$parent.message);
}
},
}
}
});
</script>
</body>
</html>