组件(Component)是Vue.js 最强大的功能之一,它是html、css、js等的一个聚合体。封装性和隔离性非常强。
组件相当于Python中的模块,扩展HTML元素,可以重复使用的代码,使用它就是为了重复使用
例如:一个轮播图需要使用放到很多页面当中使用,一个轮播图有它自己的js、css、html,而组件就可以快捷的做出一个轮播图,有自己的js、css、html放到一起,有自己的逻辑样式这样到哪里都可以使用了,无需在写重复代码
语法
Vue.component('组件名称', { })
,第1个参数是标签名称,第2个参数是一个选项对象。全局组件注册后,任何vue实例都可以用。
组件注意事项:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="div">
<h1>组件</h1>
<button @click="handleClick">点击显示</button>
<hr>
<!--全局组件-->
<child v-if="show==true"></child>
</div>
<script>
var vm = new Vue({
el:'#div',
data:{
show:false,
},
methods:{
handleClick(){
this.show=!this.show
}
}
})
//定义全局组件,一次定义,随时使用
//一但声明完成,就可以在所有的组件中直接使用,无需引入和注册
Vue.component('Child',{
//模版字符串
template:`
<div>
<h1>{{name}}</h1>
<button @click="clickname">点击更改名字</button>
</div>
`,
/*
render 用于直接生成虚拟dom(生成标签)
在工程化中,render中可以直接写jsx,在引入一个babel可以写jsx语法(js的增强版本)
render(h) {
// h(生成的标签名称,标签中有哪些属性(没有属性就是null),子元素是什么)
let vnode = h('h3', { attrs: { name: 'abc', style: 'color:red' } }, '我是一个标签')
return vnode
}
*/
data(){
return{
name:'tom',
}
},
methods:{
clickname(){
this.name='jack'
}
}
})
</script>
</body>
</html>
没有使用工程化时,我们使用浏览器解析标签,所以定义组件不能使用单标签写法,否则组件无法被多次执行,因为但标签写法浏览器在解析的时候觉得有问题,不再执行后续标签。而在工程化中,我们会使用很多包来编译html标签,单标签写法是允许的
单文件局部组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="div">
<child></child>
</div>
<script>
// 创建局部组件,它就是一个对象
// 局部组件,在创建完成后,如果你要给别人使用,一定要在配置中进行对应的配置
var child = {
template:`
<div>
<h1>自定的局部组件</h1>
{{title}}
</div>
`,
data(){
return {
title:'hello world',
}
}
}
var vm = new Vue({
el:'#div',
data:{
},
methods:{
},
//局部组件要加s
components:{
// key就是在使用时的标签名称
// value就是对应的局部组件对象
// child: child
// 简写
child
}
})
</script>
</body>
</html>
直接编写在组件内部的局部组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="div">
<child></child>
<hr>
<!--定义在内部的局部组件需要写在上一层组局的template中-->
<mcq></mcq>
</div>
<script>
var child = {
template:`
<div>
<h1>自定的局部组件</h1>
{{title}}
</div>
`,
data(){
return {
title:'hello world',
}
}
}
//注意根组件与全局组件无任何关联关系,需放在根组件前面执行,否则会报错
//在全局组件内定义局部组件
Vue.component('mcq',{
template:`
<div>
<h1>我是全局组件</h1>
<xxx></xxx>
</div>
`,
data(){
return {}
},
//在内部定义的局部组件
components:{
xxx:{
template:`
<div>
<h2>我是局部组件</h2>
</div>
`,
data(){
return {}
},
}
}
})
var vm = new Vue({
el:'#div',
data:{
},
methods:{
},
//局部组件要加s
components:{
// key就是在使用时的标签名称
// value就是对应的局部组件对象
// child: child
// 简写
child
}
})
</script>
</body>
</html>
组件与组件之间的嵌套使用避免不了数据之间的传递。那么Vue中组件的数据是如何传递的呢?组件间数据传递不同于Vue全局的数据传递,
组件实例的数据之间是孤立的,不能在子组件的模板内直接引用父组件的数据。
如果要把数据从父组件传递到子组件,就需要使用props属性。在Vue中,父子组件的关系可以总结为:prop向下传递,事件向上传递。
父组件通过prop给子组件下发数据,子组件通过事件给父组件发送消息。所以我们也会经常遇到组件之间需要传递数据的时候,大致分为四种情况:
1.通过自定义属性---自定义的变量不能用驼峰,不要与子组件中的变量冲突
父组件里 <child :name"name" ></child>
2. 子组件中引用props,可以指定自定义属性的类型,也可以直接用数组
props:{name:String} // props:['name'] /可以接收多个
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="div">
<h1>组件通信之父传子:自定义属性</h1>
父组件中的名字:{{name}}
<hr>
<global :name="name"></global>
</div>
<script>
Vue.component('global',{
template:`
<div>
<h2>我是global组件</h2>
<h3>父组件传递给子组件的:{{name}}</h3>
</div>
`,
data(){
return{}
},
props:['name',]
})
var vm = new Vue({
el:'#div',
data:{
name:'jack',
},
methods:{},
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="div">
<h1>组件通信之子传父:自定义事件</h1>
父组件接收的名字:{{p_name}}
<hr>
<global @myevent="handleEvent"></global>
</div>
<script>
Vue.component('global',{
template:`
<div>
<h2>我是global组件</h2>
<input type="text" v-model="name">
<button @click="handleSend">点击传递给父组件</button>
</div>
`,
data(){
return{
name:'jack',
}
},
methods:{
handleSend(){
this.$emit('myevent',this.name)
}
}
})
var vm = new Vue({
el:'#div',
data:{
p_name:'',
},
methods:{
handleEvent(name){
console.log('接收到了子组件传递的名字:'+name)
this.p_name=name
}
},
})
</script>
</body>
</html>