组件基础使用
一、Vue的组件-第一个实例
组件是可复用的Vue实例,它们与 new Vue 接收相同的选项,即一种自定义模板;
为了能在模板中使用,这些组件必须先注册以便 Vue 能够识别。这里有两种组件的注册类型:全局注册和局部注册。
使用Vue.component进行全局注册
<div id="app">
<mycomponent></mycomponent>
</div>
<script src="../js/vue.js"></script>
<script>
// 声明一个组件 第一个参数是组件名称,第二个是具体参数
Vue.component('mycomponent', {
template: '<h1>Hello</h1>'
})
</script>
这里不能使用大写字母,最开始使用的myComponent,页面渲染失效;
组件的名字使用驼峰命名,在使用组件的时候必须大写改为小写,然后用 “-” 链接。
在渲染失败的时候,标签名称可以看到变成了全部小写
第二种创建组件的方式
在第一种方式中,template的内容使用字符串的方式写在js中,没有提示很容易写错;可以使用< template >的方式在html中进行声明,然后利用id进行注册。
<div id="app" v-cloak>
<my-second></my-second> // 命名要小写
</div>
<template id="test"> // 在html中使用<template> 定义组件
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
</template>
<script src="./vue.js"></script>
<script>
Vue.component('mySecond', { // 定义全局组件
template: '#test' // 使用id引入组件
})
new Vue({
el: '#app',
data: {
a: 1,
}
})
</script>
定义私有组件
私有组件-一个Vue实例中使用的组件
<div id="app" v-cloak>
<my-private-com></my-private-com>
</div>
<template id="private">
<span>这是一个私有的组件</span>
</template>
<script>
// 私有组件
new Vue({
el: '#app',
data: {
a: 1,
},
components: {
myPrivateCom: {
template: '#private'
}
}
})
</script>
二、组件中的data和methods
data属性和methods的使用
组件中的data需要显示的返回对象而不能是一个具体的数据
- 组件中的data返回的是一个对象
- 组件中的methods和实例中定义相同
- 基础页面:
<div id="app">
<my-com></my-com>
</div>
<template id="first">
<h1>这是 一个测试组件</h1>
</template>
<script src="./vue.js"></script>
<script>
new Vue({
el: '#app',
data: {},
components: {
myCom: {
template: '#first'
}
}
})
</script>
- 属性添加
修改html如下:
<template id="first">
<div>
<h1>这是 {{ name }}一个测试组件</h1> <!-- 组件中返回的数据对象 -->
<button @click="onclick">点击</button> <!-- 绑定方法 -->
</div> <!-- 同样的一个组件只能有一个root -->
</template>
<script>
new Vue({
el: '#app',
data: {},
components: {
myCom: {
template: '#first',
data: function() { // 定义data属性
return { // 返回对象
name: 'righteye' // 具体的数据部分
}
},
methods: { // 定义方法,和在实例中类似
onclick() {
console.log("按钮被点击")
}
}
}
}
})
</script>
为什么组件中的data要返回对象
Q: 为什么组件中的data属性要返回对象?
A:组件的意义是重用,表示我们可以在html中定义多个相同的组件,那么同一个组件模板中的动态属性应该是相互独立的,因此需要返回对象将数据保存在不同的实例对象中。
三、使用props向子组件传值
Prop 是你可以在组件上注册的一些自定义 attribute。当一个值传递给一个 prop attribute 的时候,它就变成了那个组件实例的一个 property。
2.1 第一个实例:传递单值
<div id="app">
<mycomponent com_val="Java"></mycomponent>
</div>
<script src="../js/vue.js"></script>
<script>
// 声明一个组件 第一个参数是组件名称,第二个是具体参数
Vue.component('mycomponent', {
props: ['com_val'],
template: '<h3>{{com_val}}</h3>'
})
let vue = new Vue({
el: '#app',
})
</script>
2.2 遍历数组获取值
<div id="app">
<mycomponent v-for="item in items" :com_val="item"></mycomponent>
</div>
<script src="../js/vue.js"></script>
<script>
// 声明一个组件 第一个参数是组件名称,第二个是具体参数
Vue.component('mycomponent', {
props: ['com_val'],
template: '<h3>{{com_val}}</h3>'
})
let vue = new Vue({
el: '#app',
data: {
items: ['Java', 'Python', 'Go', 'C++']
}
})
</script>
2.3 单个根元素
<div id="app">
<mycomponent com_val="Java" title="入门Vue"></mycomponent>
</div>
<script src="../js/vue.js"></script>
<script>
// 声明一个组件 第一个参数是组件名称,第二个是具体参数
Vue.component('mycomponent', {
props: ['com_val', 'title'],
template: ` // 这里使用 飘 号,能够写多行
<div class="mycomponent"> // 指定一个父标签进行包裹
<h3>{{com_val}}</h3>
<div>{{title}}</div>
</div>
`
})
let vue = new Vue({
el: '#app',
})
</script>
官网里说不进行父元素包裹:Vue 会显示一个错误,并解释道 every component must have a single root element (每个组件必须只有一个根元素)。
// 多个根元素,此时会报错
<h3>{{com_val}}</h3><div>{{title}}</div>
当props中属性增多的时候,对于标签中的代码会显的很冗余,因此可以使用下面的写法:
<div id="app">
<mycomponent v-for="item in items" :post="item"></mycomponent>
</div>
<script src="../js/vue.js"></script>
<script>
// 声明一个组件 第一个参数是组件名称,第二个是具体参数
Vue.component('mycomponent', {
props: ['post'],
template: `
<div class="mycomponent">
<li>{{post.id}}</li>
<li>{{post.title}}</li>
<li>{{post.coment}}</li>
<br>
</div>
`
})
let vue = new Vue({
el: '#app',
data: {
items: [
{id: 1, title: 'Java入门', coment: 'Java语法'},
{id: 2, title: 'Go入门', coment: 'Go语法'},
{id: 3, title: 'C++入门', coment: 'C++语法'}
]
}
})
</script>
四、插槽
在使用Html的时候,对于页面的某些数据会是动态出现的,官方的例子:
查看其它的实例,可以感觉使用插槽是代替了其它省略的内容部分;该内容可以包括:文本,Html或者组件
在对一个数组进行遍历的时候,只是使用v-for遍历然后渲染到html中,会产生一些间隙;其实我还没感受很深对这个插槽
<div id="app" >
<h1>这是标题</h1>
<ul v-for="item in items">
<li>{{item}}</li>
</ul>
</div>
使用插槽后:
<div id="app" >
<todo>
<todo-title slot="todo-title" :title="title"></todo-title>
<todo-hobby slot="todo-hobby"
v-for="item in items"
:hobby="item"></todo-hobby>
</todo>
</div>
<script src="../js/vue.js"></script>
<script>
Vue.component("todo", {
template: `
<div>
<strong>Error!</strong>
<slot name="todo-title"></slot>
<ul>
<slot name="todo-hobby"></slot>
</ul>
</div>
`
}),
Vue.component("todo-title", {
props: ['title'],
template: `<h1>{{title}}</h1>`
}),
Vue.component("todo-hobby", {
props: ['hobby'],
template: `<li>{{hobby}}</li>`
})
let vue = new Vue({
el: "#app",
data: {
title: "语言分类",
items: ['Java', 'Python', 'Go']
}
})
</script>
五、自定义事件发布
基础样例
从子组件中传值给父组件
- 基础模板
<div id="app">
<div>这是父组件: {{ msg }}</div>
<my-com1 v-on:func="show"></my-com1> // 定义一个自定义的事件
</div>
<template id="com1">
<div>
<div>这是子组件</div>
<button >调用父组件的方法</button>
</div>
</template>
<script>
new Vue({
el: '#app',
data: {
msg: ''
},
methods: {
show(data) { // 父组件中定义显示的方法
console.log(data)
this.msg = data;
}
},
components: {
myCom1: {
template: '#com1',
data() {
return {
name: 'righteye' // 要将这个数据传回父组件
}
},
methods: {
}
}
}
})
</script>
思路:在子组件中触发时间,然后将name利用$emit 调用 子组件中的 func 自定义函数
使用插槽
继续上面的例子,现在想对数据进行双向绑定,能够动态的增加删除数据;但是组件实例和模板中的方法是不能相互调用的,因此引入了自定义事件发布,使用this.$emit(‘自定义事件名称’, 参数)
<div id="app" >
<todo>
<todo-title slot="todo-title" :title="title"></todo-title>
<todo-hobby slot="todo-hobby"
v-for="(item, index) in items"
:hobby="item" :index="index"
@remove="removeItems(index)"></todo-hobby>
</todo>
</div>
<script src="../js/vue.js"></script>
<script>
Vue.component("todo", {
template: `
<div>
<strong>Error!</strong>
<slot name="todo-title"></slot>
<ul>
<slot name="todo-hobby"></slot>
</ul>
</div>
`
}),
Vue.component("todo-title", {
props: ['title'],
template: `<h1>{{title}}</h1>`
}),
Vue.component("todo-hobby", {
props: ['hobby', 'index'],
template: `
<li>{{hobby}} <button @click="remove(index)">删除</button></li>
`,
methods: {
remove(index) {
this.$emit('remove', index);
}
}
})
let vue = new Vue({
el: "#app",
data: {
title: "语言分类",
items: ['Java', 'Python', 'Go']
},
methods: {
removeItems(index) {
console.log(index)
this.items.splice(index, 1);
}
}
})
</script>
总结
先对组件的使用进行快速入门;查看官网组件部分还有组件间的传值操作,后期进行补充