注册组件
- 组件使用的三个步骤
- 创建组件构造器
- 注册组件
- 使用组件
<div id='app'>
<my-cpn></my-cpn> ///使用组件
</div>
<script>
const myComponent = Vue.extend({
template:`
<div>
<h2>标题</h2>
<p>我是段落</p>
</div>
`
}); //创建组件构造器(第一步)
Vue.component('my-cpn',myComponent);//注册组件(第二步)
var app = new Vue({
el:'#app',
})
</script>
上述步骤解析
- Vue.extend()
- 调用的是Vue.extend()创建的是一个组件构造器
- 通常在创建组件构造器时,传入template代表我们自定义的组件
- 该模板就是在使用组件的地方,要显示HTML代码
- Vue.component()
- 调用Vue.component是将刚才的组件构造器注册成为一个组件,并且给呀一个组件的标签名称
- 需要连个参数:注册组件的标签名和组件构造器的名字
- 组件必须挂载在vue实例下,否则不生效
全局和局部组件
上述通过Vue.component()注册组件时,组件的注册是全局的;该组件可以再任意Vue实例下使用
如果我们注册的组件是挂载在某个实例下,那就是局部组件
- 全局组件
<div id='app'>
<my-cpn></my-cpn>
</div>
<script>
const cpnC = Vue.extend({
template: `
<div>
<h2>标题</h2>
<div>
`
}),
Vue.component('mu-cpn',cpnC);
const app = new Vue({
el:'#app',
})
</script>
- 局部组件
<div id='app'>
<my-cpn></my-cpn>
</div>
<script>
var cpnC = Vue.extend({
template:`
<div>
<h2>标题</h2>
<div>
`
});
const app = new Vue({
el:'#app',
conponents:{
my-cpn:cpnC,
}
})
</script>
父组件和子组件
组件和组件之间存在层级关系
<div id='app'>
<myone></myone>
<mytwo></mytwo>
</div>
<script>
const myone-c = Vue.extend({
template:`
<div>
<p>正文内容</p>
</div>
`
}); //创建子组件构造器
const mytwo-c = Vue.extend({
template:`
<div>
<h2>标题</h2>
</div>
`,
components:{
myone:myone-c,
}
}); //创建父组件构造器,并在父组件中,注册子组件
var app = new Vue({
el:'#app',
components:{
mytwo:mytwo-c //vue实例中,注册父组件
}
})
</script>
- 错误用法:以字标签的形式在vue实例中使用
- 子组件注册到父组件中的components时,Vue会编译好父组件的模块
- 该模块的内容已经决定了父组件将要渲染的HTML
<myone></myone>
是只能在父组件中识别的,这种用法或被浏览器忽略
注册组件语法糖
可以省去Vue.extend()步骤,直接使用对象来代替
- 全局组件
Vue.component('my-cpn',{
template:`
<div>
<h2>我是标题1</h2>
<p>我是内容, 哈哈哈哈</p>
</div>
`
});
- 局部组件
const app = new Vue({
el:'#app',
components:{
'my-cpn':{
template:`
<div>
<h2>我是标题1</h2>
<p>我是内容, 哈哈哈哈</p>
</div>
`
}
}
})
模板的分离写法
Vue提供了两种方案来定义HTML模块,使HTML模块能分离出来,然后挂载到对应的组件上
- 使用
<script>
标签 - 使用
<template>
标签
//script标签必须是text/x-tempalte类型
<script type='text/x-tempalte' id='cpn'>
<div>
<h2>我是标题</h2>
<p>我是内容,哈哈哈</p>
</div>
</script>
//template标签
<tempalte id='cpn'>
<div>
<h2>我是标题</h2>
<p>我是内容,哈哈哈</p>
</div>
</tempalte>
Vue.component('myone',{
template:'#cpn'
});
const app = new Vue({
el:'#app'
})
组件中的数据
- 组件访问vue实例数据
- 组件是一个单独功能模块的封装,有自己的数据data
- 但是我们不能直接访问vue实例中的data数据,因为vue组件应该有自己保存数据地方
- 组件数据的存档
- 组件对象也有一个data属性(也可以有methods等属性)
- 是指这个data属性必须是一个函数,并且函数返回一个对象,对象内部保存着数据
Vue.component('cpn',{
template:'#cpn',
data(){
retuen {
title:'abc'
}
}
})
组件数据为什么是函数?
首先,如果不是函数,Vue直接就会报错
其次,Vue让每个组件对象都返回一个新的对象
组件中数据传递
- 父级向子级传递
- 子组件不能引用父组件或者vue实例的数据
- 开发中,需要数据从上层传递到下层,这时候,就需要让父组件将数据传递给子组件
- 父子组件之间如何通信?
- 父组件通过
props
向子组件传递数据 - 子组件通过
事件
向父组件发送消息
- 父组件通过
props基本用法
- 使用props来声明需要从父级接收到的数据
- props的两种传值方式
- 方式一:字符串数组,数组中的字符串就暗示传递时的名称
- 方式二:对象,对象可以设置传递时的类型,也可以设置默认值
实例
<div id='app'>
<myone-c :one='messenge'></myone-c>
</div>
<tempalte id='myone'>
<div>{{messenge}}</div>
</template>
const app = new Vue({
el:'#app',
data:{
messenge:'天气不错',
},
components:{
'myone-c':{
template:'#myone',
props:['one']
}
}
})
子级向父级传递
- props用于父组件想子组件传递数据,还有一种是子组件传递数据或者事件到父组件中
- 我们用自定义事件来完成
- 什么时候需要自定义事件呢
- 当子组件需要向父组件传递数据;
- 之前学习的v-on不仅仅用来监听DOM事件,还可以用于组件之间的自定义事件
- 自定义事件的流程
- 在子组件中,使用
$emit
来触发事件 - 在父组件中,使用v-on来监听子组件事件
- 在子组件中,使用
- 什么时候需要自定义事件呢
<div id="app">
<cpn @increment='changeTotal' @decrement='changeTotal'></cpn>
<h2>点击次数:{{total}}</h2>
</div>
<template id="children">
<div>
<button type="button" name="button" @click="increment">+1</button>
<button type="button" name="button" @click="decrement" :disabled="counter <= 0 ">-1</button>
</div>
</template>
<script type="text/javascript">
const app = new Vue({
el:'#app',
data:{
total:0
},
methods:{
changeTotal(counter){
this.total = counter;
}
},
components:{
'cpn':{
template:'#children',
data(){
return {
counter:0
}
},
methods:{
increment(){
this.counter++;
this.$emit('increment',this.counter);
},
decrement(){
this.counter--;
this.$emit('decrement',this.counter);
}
}
}
}
})
</script>