angular中的指令和vue的组件很像,而vue中的指令是用来对节点进行操作的
angular的指令里包含了template
,但是vue将它单独的抽了出来,称为组件(compontent)。
全局组件
全局组件是直接在Vue
构造函数上扩充组件,在实例化Vue对象的时候会添加到对象中,所以任何Vue
的实例对象都可以使用这个组件。
<!--组件以dom元素的形式出现-->
<mycmp></mycmp>
<script>
// 创建模版
let tpl = Vue.extend({
template: '<h1>我是一个全局组件</h1>'
});
// 注册组件
Vue.component('mycmp', tpl);
new Vue({}).$mount('#app');
</script>
简写方式:
Vue.component('mycmp', {
template: '<h1>我是一个全局组件</h1>'
});
局部组件
局部组件是在Vue
实例里添加组件,只对当前Vue
实例有效
<mycmp></mycmp>
<script>
let tpl = Vue.extend({
template: '<h1>我是一个局部组件</h1>'
});
new Vue({
components: {
// mycmp就是自定义组件的名称
mycmp: tpl
}
}).$mount('#app');
</script>
简写方式:
new Vue({
components: {
mycmp: {
template: '<h1>我是一个局部组件</h1>'
}
}
}).$mount('#app');
使用template标签作为模版
template是用于存放html代码的一个模版。
angular中的template
可以是一个url(templateUrl
)也可以是一个字符串。
用字符串去写html代码有2个弊端
- 可读性差
- 写的累
用url去指定一个template有3个弊端
- 增加请求次数,给服务器造成不必要的压力
- 性能差(使用ajax发送请求,获取文件的内容,把文件读取出来,然后插入文档中)
- 多文件管理起来复杂
可以使用template标签包裹住组件的html代码
template标签不是vue的特性,而是h5新增的标签。
<body id="app">
<!-- 需要渲染的地方 -->
<mytpl></mytpl>
</body>
<!-- 组件的模版,只需要指定一个id即可,最好写在vue的作用域外(#app) -->
<template id="mytpl">
<h1>我是template标签模版!</h1>
</template>
<script>
new Vue({
components: {
mytpl: {
// 可以传选择器!
template: '#mytpl'
}
}
}).$mount('#app');
</script>
组件的作用域
组件有一个自己的作用域,不能直接访问data
和methods
属性内的字段。
<!--结果:我是组件里面的data-->
<mycmp></mycmp>
<script>
new Vue({
data: {
msg: '我是data'
},
components: {
mycmp: {
// 这个data是一个函数,返回一个对象
data (){
return {
msg: '我是组件里面的data'
}
},
template: '<h1>{{msg}}</h1>'
}
}
}).$mount('#app');
</script>
让外界传递值进来 props属性
props是一个数组,里面的元素是节点属性名称,需要定义多个自定义节点属性就往后面添加。
<mycmp outside-msg="外来的数据"></mycmp>
<script>
new Vue({
data: {
msg: '我是Vue实例的data'
},
components: {
mycmp: {
data (){
return {
msg: '我是组件里面的data'
}
},
props: ['outsideMsg'],
template: '<h1>{{outsideMsg}}</h1>'
}
}
}).$mount('#app');
</script>
props的命名规则:可以使用驼峰命名法,但是在
template
属性中必须要使用驼峰命名法
!而在外界使用组件的时候用-
代替驼峰命名法。为了统一,在定义组件的时候(props和template)统一使用驼峰命名法,使用组件的时候用-
代替。如果不使用-
代替会报错:
利用props访问Vue实例的data
一开始已经说过,组件只能访问自己的data
,但是通过props
是可以获取父级中的data
<!--输出:我是Vue实例的data-->
<!--注意,需要使用v-bind(:号是缩写)才可以获取Vue实例的data属性中的字段-->
<mycmp :outside-msg="msg"></mycmp>
<script>
new Vue({
data: {
msg: '我是Vue实例的data'
},
components: {
mycmp: {
data (){
return {
msg: '我是组件里面的data'
}
},
props: ['outsideMsg'],
template: '<h1>{{outsideMsg}}</h1>'
}
}
}).$mount('#app');
</script>
组件嵌套(父子组件)
说的通俗点,就是在components
里面再写一个components
,调用里面的组件是需要注意的(可以无限嵌套)。
<father></father>
<!--父组件的模版-->
<template id="father_tpl">
<div style="width: 100px; height: 100px; background-color: skyblue;">
<!--子组件只能在父组件中使用-->
<child></child>
</div>
</template>
<script>
new Vue({
components: {
'father': {
template: '#father_tpl',
components: {
'child': {
template: '<p>我是里面的组件</p>',
}
}
}
}
}).$mount('#app');
</script>
动态绑定组件
如果你细心的话,可能会注意到在注册全局组件的时候用的是component
,而注册局部组件的时候是用components
,这个s
意味着局部组件是可以注册多个的。通过components
组件可以动态的获取这些自定义组件。
以往使用组件都是以标签的形式出现,动态绑定组件是使用
components
组件,在组件中添加一个is
节点属性。(注意,components
是vue中内置的组件)
<component is="mycmp1"></component>
<script>
new Vue({
components: {
'mycmp1': {
template: '<h1>我是组件1</h1>'
},
'mycmp2': {
template: '<h1>我是组件2</h1>'
}
}
}).$mount('#app')
</script>
保留内容 slot
有些情况下需要在组件的内部保留 原标签的它的子标签或内容,但是默认情况下 原标签和它的子标签都会被移除掉,如:
<mycmp>
<!--在组件里面的所有内用都会被替换!-->
<p>我是需要保留的内容1</p>
<p>我是需要保留的内容2</p>
</mycmp>
使用slot
可以保留这部分内容
<mycomp>
<p slot="top">这段文本不能给替换</p>
<p slot="btm">这段文本也不能给替换</p>
</mycomp>
<!--组件模版-->
<template id="tpl">
<slot name="top"></slot>
<p>我是组件</p>
<slot name="btm"></slot>
</template>
<script>
new Vue({
components: {
mycomp: {
template: '#tpl'
}
}
}).$mount('#app');
</script>
如果只要保留一个内容,
<slot>
可以不需要name
节点属性,slot
也不需要指定值