组件化
创建组件构造器 vue.extend()
注册组件vue.component()
使用组件
基本使用过程
<body>
<div id='cpn'>
<!-- 使用组件 -->
<my_cpn></my_cpn>
</div>
<script>
// 构造组件
const my_cpn=Vue.extend({
template:`
<div>
<h1>标题</h1>
<p>内容</p>
<p>内容</p>
</div>
`
})
//注册组件
Vue.component('my_cpn',my_cpn)
const cpn=new Vue({
el:'#cpn'
})
</script>
</body>
全局组件与局部组件
<!--全局组件注册-->
<script>
// 构造组件
const my_cpn=Vue.extend({
template:`
<div>
<h1>标题</h1>
<p>内容</p>
<p>内容</p>
</div>
`
})
//注册组件
Vue.component('my_cpn',my_cpn)
const cpn=new Vue({
el:'#cpn'
})
</script>
<!--局部组件注册,只能在某个vue实例下应用-->
const cpn=new Vue({
el:'#cpn',
components:{
my_cpn:my_cpn
}
})
父组件与子组件
在父组件的components中对子组件进行注册
必须先写子组件再写父组件
<script>
// 构造组件
const my_cpn1=Vue.extend({
template:`
<div>
<h1>标题1</h1>
<p>内容1</p>
<p>内容1</p>
</div>
`
})
const my_cpn2=Vue.extend({
template:`
<div>
<h1>标题2</h1>
<p>内容2</p>
<p>内容2</p>
<my_cpn1></my_cpn1>
</div>
`,
//在父组件的components中对子组件进行注册
components:{
my_cpn1:my_cpn1
}
})
const cpn=new Vue({
el:'#cpn',
components:{
my_cpn2:my_cpn2,
}
})
</script>
语法糖注册组件
//构造组件
const my_cpn=Vue.extend({
template:`
<div>
<h1>标题</h1>
<p>内容</p>
<p>内容</p>
</div>
`
})
//注册组件
Vue.component('my_cpn',my_cpn)
语法糖写法
Vue.component('my_cpn',{
template:`
<div>
<h1>标题</h1>
<p>内容</p>
<p>内容</p>
</div>
`
})
组件数据
需要注意的是,组件的data属性必须是一个函数,而且这个函数返回的一个的对象,对象内部保存着数据。
<template id="my_cpntpl">
<div>
<h1>{{title}}</h1>
</div>
</template>
Vue.component('my_cpn',{
template:"#my_cpntpl",
data(){
return{
title:'标题1'
}
}
})
是函数的原因:因为组件可能存在复用现象,而对象共用,会造成数据问题。函数在每一次调用的时候,都会生成新的对象
父子组件通信
通过props向子组件传递数据
1.字符串数组,数组中的字符串就是传递时的名称
2.对象,对象可以设置传递时的类型,也可以设置默认值等。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="parent">
<!-- 子组件使用v-bind将父组件中的数据进行绑定 -->
<child_cpn :c_message="message" :c_movies="movies"></child_cpn>
</div>
<!-- 定义子组件模板 -->
<template id="child">
<div>
<p>{{c_message}}</p>
<ul>
<li v-for="item in c_movies">{{item}}</li>
</ul>
</div>
</template>
<script>
// 子组件通过props属性,将父组件中传递来的数据进行储存
//props可以是数组也可以是对象 对象写法中还可以对属性进行判定
//props:{c_movies:Array,c_message:String}
Vue.component('child_cpn',{
template:'#child',
props:['c_movies','c_message']
})
//父组件存放数据 这里将vue实例看作父组件
const p_c=new Vue({
el:'#parent',
data:{
movies:["海王",'海贼王','海绵宝宝','海尔兄弟'],
message:"hello"
}
})
</script>
</body>
</html>
Vue.component('child_cpn',{
template:'#child',
props:{
//类型是对象或者数组,默认值必须是一个函数
c_movies:{type:Array,default(){return []}},
//默认值aaa required:这个参数必须要
c_message:{type:String,default:"aaa",required:true}
}
})
通过事件向父组件发送消息
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<title></title>
</head>
<body>
<div id="childtoparent">
<!-- 监听该事件 所使用的函数没有传参数,就会自己传itemclick的事件,即之前的item -->
<child cpn @itemclick="parentreceive"></child>
</div>
<template id="child_template">
<div>
<button v-for="item in categories" @click="childclick(item)">{{item.name}}</button>
</div>
</template>
<script>
const child={
template:"#child_template",
data(){
return{
categories:[
{id:"01",name:"热门推荐"},
{id:"02",name:"手机数码"},
{id:"03",name:"家居用品"},
{id:"04",name:"电脑办公"},
]
}
},
methods:{
childclick(item){
//向itemclick 发送item 需要在父组件监听该事件
this.$emit("itemclick",item)
}
}
}
Vue.component("child",child)
const childtoparent=new Vue({
el:'#childtoparent',
methods:{
parentreceive(item){
console.log(item)
}
}
})
</script>
</body>
</html>
父子组件访问
父组件访问子组件
使用 c h i l d r e n 或 者 children或者 children或者refs(推荐使用$refs)
<body>
<div id='app'>
{{message}}
<!--绑定子组件的时候,需要对子组件增加ref参数,便于后续取用-->
<cpn ref='aaa'></cpn>
<button @click="btnclick">按钮</button>
</div>
<template id='cpn'>
<div>子组件</div>
</template>
<script>
const cpn={
template:'#cpn',
methods:{
showmessage(){
console.log("子组件的函数")
}
}
}
Vue.component('cpn',cpn)
const app=new Vue({
el:'#app',
data:{
message:"hello"
},
methods:{
btnclick(){
//采用$refs.ref属性名.方法进行调用
this.$refs.aaa.showmessage()
}
}
})
</script>
</body>
子组件访问父组件
使用 p a r e n t 或 者 parent或者 parent或者root
this.$parent.属性 访问父组件属性、方法、数据
this.$root.属性 访问根组件属性、方法、数据
slot插槽的使用
增加组件的扩展性
<div id='app'>
<div>{{message}}</div>
<cpn><button>采用插槽实现的按钮</button></cpn>
<cpn><div>采用插槽填写的文字</div></cpn>
</div>
<!-- 组件模板 -->
<template id='cpn'>
<div>
<h2>我是组件</h2>
<!-- 定义插槽 -->
<slot><div>可以存放插槽的默认值</div></slot>
</div>
</template>
<script>
// vue实例,注册组件
const app=new Vue({
el:'#app',
data:{message:"hello"},
components:{
cpn:{
template:"#cpn"
}
}
})
</script>
具名插槽
给多个slot起名字,方面后续选用
采用name属性对模板中slot进行定义
<template id='cpn'>
<div>
<h2>我是组件</h2>
<!-- 定义插槽 -->
<slot name='1'><div>可以存放插槽的默认值</div></slot>
<slot name='2'><p>可以存放插槽的默认值</p></slot>
</div>
</template>
使用的时候定义哪一个slot
<cpn><button slot="1">采用插槽实现的按钮</button></cpn>
作用域插槽
父组件替换插槽的标签但是内容由子组件提供
例子:子组件包括有一组数据,但是需要以不同的形式进行展示,
<body>
<div id='app'>
<div>{{message}}</div>
<cpn></cpn>
<cpn>
<!-- v-slot="slot"接受数据 -->
<template v-slot="slot">
<span v-for="item in slot.data">{{item+" "}}</span>
</template>
</cpn>
</div>
<!-- 组件模板 -->
<template id='cpn'>
<div>
<h2>我是组件</h2>
<!-- 定义插槽 :data属性使数据能够被父组件使用-->
<slot :data="nation">
<ul>
<li v-for="item in nation">{{item}}</li>
</ul>
</slot>
</div>
</template>
<script>
// vue实例,注册组件
const app=new Vue({
el:'#app',
data:{message:"hello"},
components:{
cpn:{
template:"#cpn",
data(){
return{
nation:["china","england","american"]
}
}
}
}
})
</script>
</body>