Vue 组件
官方资源
https://cn.vuejs.org/v2/guide/components.html
https://cn.vuejs.org/v2/guide/components-registration.html
什么是组件
组件系统是 Vue 的一个重要概念,因为它是一种抽象,允许我们使用小型、独立和通常可复用的组件构建大型应用。通常一个应用会以一棵嵌套的组件树的形式来组织:
例如,你可能会有页头、侧边栏、内容区等组件,每个组件又包含了其它的像导航链接、博文之类的组件。
组件定义
组件是可复用的 Vue 实例,且带有一个名字。把这个组件作为自定义元素来使用。组件的好处是写一次可以进行任意次数的复用。
全局组件
直接使用 Vue.component()
方法定义组件,这种组件叫做全局组件
例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue 组件</title>
<!--这里因为方便,我直接使用cdn方式引入-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<!-- 使用组件 -->
<!-- 将组件名直接当做标签名在html代码中使用即可 -->
<mytemp></mytemp>
<!-- 组件可以进行任意次数的复用 -->
<mytemp></mytemp>
</div>
</body>
<script>
// 定义一个名为 mytemp 的新组件
Vue.component('mytemp',{
// template属性的值,作为组件的内容
// vue 会把这个值替换到html中并会被浏览器渲染
template:"<h2>我是一个组件</h2>"
})
var app = new Vue({
el: '#app',
})
</script>
</html>
效果
上面代码中我们直接使用 Vue.component()
方法定义了组件,而这个 mytemp
组件可以用在所有 vue 实例中,
这种组件被称为 全局组件
局部组件
在具体的某个vue实例中,也可以定义组件,但是组件仅会在具体的 vue 实例中起作用,这种组件被称为 局部(私有)组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue 组件</title>
<!--这里因为方便,我直接使用cdn方式引入-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<!-- 使用组件 -->
<!-- 将组件名直接当做标签名在html代码中使用即可 -->
<mytemp></mytemp>
</div>
<div id="app2">
<!-- 不可用 -->
<mytemp></mytemp>
</div>
</body>
<script>
var app = new Vue({
el: '#app',
// app 的私有组件,其他实例对象不可用
//components 是固定的属性
components: {
mytemp: {
template: "<h2>我是一个局部组件</h2>",
}
}
})
var app2 = new Vue({
el: '#app2',
})
</script>
</html>
效果
使用注意
-
组件名如果是驼峰法命名,使用组件时要将大写字母改为小写,并且在前面加上
-
-
组件中的tamplate属性必须有一个唯一的根元素,否则会报错
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue 组件</title>
<!--这里因为方便,我直接使用cdn方式引入-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<!-- 使用组件 -->
<!-- 将组件名直接当做标签名在html代码中使用即可 -->
<my-temp></my-temp>
<!-- 单标签方式使用 -->
<my-temp/>
</div>
<div id="app2">
<!-- 不可用 -->
<my-temp></my-temp>
</div>
</body>
<script>
var app = new Vue({
el: '#app',
// app 的私有组件,其他实例对象不可用
components: {
// 驼峰法命名
myTemp: {
// 必须有唯一的根标签,多标签报错
template: "<div><h2>我是一个组件</h2><h3>df</h3></div>",
}
}
})
var app2 = new Vue({
el: '#app2',
})
</script>
</html>
组件的使用
下面是使用组件来布局
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue 组件</title>
<!--这里因为方便,我直接使用cdn方式引入-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
.top {
width: 100%;
height: 80px;
background-color: #ccc;
}
.left {
margin-top: 20px;
width: 800px;
height: 600px;
background-color: #ccc;
float: left;
}
.right {
margin-top: 20px;
width: 400px;
height: 600px;
background-color: #ccc;
float: right;
}
</style>
</head>
<body>
<div id="app">
<tops></tops>
<lefts></lefts>
<rights></rights>
</div>
</body>
<script>
var app = new Vue({
el: '#app',
components:{
tops:{
template:'<div class="top">我是顶</div>'
},
lefts:{
template:'<div class="left">我是左</div>',
},
rights:{
template:'<div class="right">我是右</div>'
}
}
})
</script>
</html>
效果
组件中的数据及方法
组件是带有名字的可复用的 Vue 实例 ,所以它们与 new Vue
实例对象接收相同的参数选项 data
、computed
、watch
、methods
, 但 el
例外;
虽然组件和实例对象可以接收相同的参数选项,但在具体使用中,vue实例对象的 data
与组件中的 data
还是有差异的, 在我们自己写的组件中,data 必须是一个函数
一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回的对象;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue 组件</title>
<!--这里因为方便,我直接使用cdn方式引入-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<my-temp></my-temp>
</div>
</body>
<script>
var app = new Vue({
el: '#app',
components: {
myTemp: {
// 一个组件的 data 选项必须是一个函数
data:function(){
// 将 数据 装入 对象 返回
return {msg:'我是data选项'}
},
// 其他选项的使用不受影响
methods:{
cli(){
alert(123);
}
},
template: "<div @click='cli'>{{msg}}</div>",
}
}
})
</script>
</html>
vue实例也是组件
通过new Vue()
可以得到一个实例对象,其实这个实例对象就是一个特殊的组件,也有 template
参数,也可以当做组件来使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue 组件</title>
<!--这里因为方便,我直接使用cdn方式引入-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
{{msg}}
</div>
</body>
<script>
var app = new Vue({
el: '#app',
data:{msg:'数据'},
template:'<h2>组件</h2>'
})
</script>
</html>
你会发现插值没用了,这是因为
上面的代码中直接为Vue 实例对象传入了 template
参数,那么 vue 会使用template
中的数据替换 el
选中的整个 DOM 节点 , 因此 data
选项中的的数据也不会绑定,因为在绑定数据之前,整个 DOM 节点包括节点中 {{msg}}
都会被替换;如果想让数据正常绑定,我们可以在 template 数据中加入 {{msg}}
例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue 组件</title>
<!--这里因为方便,我直接使用cdn方式引入-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
{{msg}}
</div>
</body>
<script>
var app = new Vue({
el: '#app',
data:{msg:'数据'},
template:'<h2>组件{{msg}}</h2>'
})
</script>
</html>
组件之间传值
https://cn.vuejs.org/v2/guide/components.html
组件作用域
注意:组件与组件之间都拥有自己独立的作用域,类似于闭包,他们的data数据不会共享
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue 组件</title>
<!--这里因为方便,我直接使用cdn方式引入-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<mytemp></mytemp>
</div>
</body>
<script>
var app = new Vue({
el: '#app',
data:{msg:'数据'},
components:{
mytemp:{
template:'<h2>data:{{msg}}</h2>'
}
}
})
</script>
</html>
运行上面的代码,你会发现,组件 mytemp
并不能获取实例中 data
的数据,这是因为组件与组件之间都拥有各自独立的作用域;
通过 Prop 向子组件传递数据 *
vue 在组件中提供了props
选项,props 接受一个在组件中自定义属性的值;
例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue 组件</title>
<!--这里因为方便,我直接使用cdn方式引入-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<!--使用组件并自定义属性和属性值-->
<mytemp cc="makalo最帅"></mytemp>
</div>
</body>
<script>
var app = new Vue({
el: '#app',
data:{msg:'数据'},
components:{
mytemp:{
template:'<h2>data:{{cc}}</h2>',
//接收组件自定义属性值
props:['cc'],
}
}
})
</script>
</html>
知道了props的用法后,怎么才能将vue实例对象中的数据传入组件中呢?我们可以借助 v-bind
指令来进行传值;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue 组件</title>
<!--这里因为方便,我直接使用cdn方式引入-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<mytemp v-bind:cc="msg" v-bind:kk="msg2"></mytemp>
</div>
</body>
<script>
var app = new Vue({
el: '#app',
data:{
msg:'数据',
msg2:'数据二'
},
components:{
mytemp:{
template:'<h2>data:{{cc}}<br>{{kk}}</h2>',
props:['cc','kk'],
}
}
})
</script>
</html>