Vue组件基础
基本示例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../lib/vue.js"></script>
</head>
<body>
<!-- 第一步:定义模板 -->
<template id="counter">
<div>
<button @click="count++">click me {{count}} times</button>
</div>
</template>
<!-- 第三步:使用组件 -->
<div id="app">
<counter></counter>
</div>
<script type="text/javascript">
// 第二步:定义、注册组件
Vue.component('counter', {
data() {
return {
count: 0
}
},
template: '#counter'
});
new Vue({
el: '#app'
});
</script>
</body>
</html>
注意:定义的组件名的命名规则不能使用驼峰命名,多个单词之间要用 -
符号隔开。
组件的复用
<div id="app">
<counter></counter>
<counter></counter>
<counter></counter>
</div>
定义的组件后,可以任意次地复用,每个组件独立地维护着自己的 data
数据
data必须是函数
data 不能像这样直接提供一个对象,这样的话,多个相同地组件会共用同一份数据。
data: {
count: 0
}
data 必须是一个函数,才能保证每个组件间的 data 是独立的。
通过 Prop 向子组件传递数据
prop 是你可以在组件上注册的自定义 attribute,格式为:
Vue.component('my-component', {
props: ['title'],
template: '<h3>{{title}}</h3>'
})
从上面代码中可以看出,在组件实例中,你可以像访问 data 中的值一样访问你自定义的 prop
在使用这个组件时,你可以像这样把数据作为一个自定义 attribute 传递进来:
<my-component title="hello"></my-component>
<my-component title="world"></my-component>
但实际地应用中往往是把 data 中的数据动态地传递给 prop。
<body>
<div id="app">
<my-component v-for="item in list" :key="item.id" :title="item.title"></my-component>
</div>
<script type="text/javascript">
Vue.component('my-component', {
props: ['title'],
template: '<h3>{{title}}</h3>'
});
new Vue({
el: '#app',
data() {
return {
list: [
{ id: 1, title: 'hello' },
{ id: 2, title: 'world' },
{ id: 3, title: '你好,世界' },
]
}
}
});
</script>
</body>
父组件向子组件传递数据:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../lib/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<template id="children">
<div>
<!-- 第二步:在子组件中可以像使用data中的数据一样使用props中的属性 -->
<h3>父组件传过来地值:-------{{count}}</h3>
</div>
</template>
<div id="app">
<!-- 第四步:在使用子组件时,通过属性绑定的方式把父组件的 fathercount值 传递给自组件的 count属性 -->
<my-component :count="fathercount"></my-component>
</div>
<script type="text/javascript">
Vue.component('my-component', {
// 第一步:在子组件的props数组中,定义一个count属性(这里的属性是指子组件的属性),
// 用于接收父组件传过来的值
props: ['count'],
template: '#children'
});
new Vue({
el: '#app',
data() {
return {
// 第三步:在父组件data中定义一个值fathercount,用来传递给子组件
fathercount: 1
}
}
});
</script>
</body>
</html>
子组件向父组件传递数据
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../lib/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<template id="children">
<div>
<h3>父组件传过来地值:-------{{count}}</h3>
<!-- 第二步:在子组件模板中定义一个按钮,给按钮添加一个点击事件,点击事件正常调用子组件的方法 -->
<button type="button" @click="tranToFather">传值给父组件</button>
</div>
</template>
<div id="app">
<!-- 第一步:通过 v-on 给子组件添加一个自定义的事件 show-love,
只要子组件的自定义事件 show-love 触发了,就会调用父组件的方法 getLove -->
<my-component :count="fathercount" v-on:show-love="getLove"></my-component>
</div>
<script type="text/javascript">
Vue.component('my-component', {
props: ['count'],
template: '#children',
methods: {
tranToFather() {
// 第三步:子组件的这个方法通过 $emit 触发自定义的事件 show-love,并把额外的参数传递出去
// this 指向的时当前实例 vm
this.$emit('show-love', 'I love you!')
}
}
});
new Vue({
el: '#app',
data() {
return {
fathercount: 1
}
},
methods: {
// 第四步:父组件的 getLove 方法会接收到子组件自定义事件传出来的额外参数
getLove(param) {
console.log(param);
}
}
});
</script>
</body>
</html>
第二种写法:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../lib/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<template id="children">
<div>
<h3>父组件传过来地值:-------{{count}}</h3>
<button type="button" @click="tranToFather">传值给父组件</button>
</div>
</template>
<div id="app">
<my-component :count="fathercount" ref="children"></my-component>
</div>
<script type="text/javascript">
Vue.component('my-component', {
props: ['count'],
template: '#children',
methods: {
tranToFather() {
this.$emit('show-love', 'I love you!')
}
}
});
new Vue({
el: '#app',
data() {
return {
fathercount: 1
}
},
methods: {
// 如果子组件传过来的值有多个,可以使用 getLove(...params) 来接收
getLove(param) {
console.log(param);
}
},
mounted() {
this.$refs.children.$on('show-love', this.getLove);
}
});
</script>
</body>
</html>
官方文档上放大字体的例子:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../lib/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<template id="children">
<div>
<p>{{item.content}}</p>
<button @click="largeText">放大字体</button>
</div>
</template>
<div id="app" :style="{ fontSize: fontSize + 'px' }">
<my-component v-for="item in list" :key="item.id" :item="item" v-on:large-text="fatherLarge"></my-component>
</div>
<script type="text/javascript">
Vue.component('my-component', {
template: '#children',
props: ['item'],
methods: {
largeText() {
this.$emit('large-text', 4);
}
}
});
new Vue({
el: "#app",
data() {
return {
fontSize: 10,
list: [
{ id: 1, content: '长风破浪会有时,直挂云帆济沧海' },
{ id: 2, content: '非淡泊无以明志,非宁静无以致远' }
]
}
},
methods: {
fatherLarge(param) {
this.fontSize += param;
}
}
});
</script>
</body>
</html>
组件模板必须有一个根元素
动态组件
使用 <component>
元素再加上 is
属性可以实现在不同的组件之间切换:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../lib/vue.js" type="text/javascript" charset="utf-8"></script>
<style type="text/css">
ul {
padding: 0;
margin: 0;
}
li {
list-style: none;
display: inline-block;
}
button {
width: 50px;
height: 30px;
font-size: 15px;
}
.content {
width: 200px;
border-radius: 1px;
border: 1px solid #555;
}
</style>
</head>
<body>
<div id="app">
<div class="container">
<ul>
<li v-for="item in list"><button @click="select(item)">{{item}}</button></li>
</ul>
<div class="content">
<component :is="active"></component>
</div>
</div>
</div>
<script>
Vue.component('tab1', {
template: `
<div>
<h3>Java</h3>
</div>
`
});
Vue.component('tab2', {
template: `
<div>
<h3>JavaScript</h3>
</div>
`
});
Vue.component('tab3', {
template: `
<div>
<h3>Nodejs</h3>
</div>
`
});
new Vue({
el: '#app',
data() {
return {
active: 'tab1',
list: ['tab1', 'tab2', 'tab3']
}
},
methods: {
select(item) {
this.active = item;
}
}
});
</script>
</body>
</html>