1. 组件概念
什么是组件化
把页面上可重用的部分封装为组件,从而方便项目的开发和维护,体现了封装的思想。
组件化的好处
提高了前端代码的复用性和灵活性,提升了开发效率和后期的可维护性。
组件开发三要素(prop,自定义事件,slot)
prop用于定义组件的属性。
自定义事件用于触发组件的事件。
slot用于组件功能的扩展。
使用组件的三个步骤
1)定义组件(创建组件)
2)注册组件
3)使用组件(编写组件标签)
2. 基本使用
1)定义组件
使用Vue.extend(options)创建,其中options和new Vue(options)中的options基本一样。
区别点:
- 不写el;
- data必须写成函数;
- 使用template配置组件结构。
2)注册组件
- 局部注册:在new Vue中增加components选项
- 全局注册:Vue.component(‘组件名’,组件)
3)使用组件
将组件名作为标签名,直接在页面元素位置编写即可。
非单文件组件(基本不用)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>关注微信公众号【程序员战羽】</title>
<script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<!-- 关注微信公众号【程序员战羽】,获取更多技术文章 -->
<div id="app1">
<!-- 3、使用组件 -->
<my-mp></my-mp>
</div>
<hr >
<div id="app2">
<!-- 3、使用组件 -->
<my-mp></my-mp>
<!-- 报错 -->
<!-- <my-blog></my-blog> -->
</div>
<hr >
<div id="app3">
<!-- 3、使用组件 -->
<my-blog></my-blog>
</div>
<script type="text/javascript">
//1、定义组件
const mp = Vue.extend({
template:`
<div><p>本人微信公众号名称【{{name}}】</p>
<p>{{des}}</p>
<button @click="showName">显示微信公众号名称</button></div>
`,
data() {
return {
name:'程序员战羽',
des:'主要分享java相关技术栈知识,欢迎关注!!!'
}
},
methods:{
showName(){
alert(this.name)
}
}
})
//1、定义组件
const myBlog = Vue.extend({
template:`
<div><p>本人csdn博客【{{blogName}}】</p>
<p>{{blogDes}}</p>
</div>
`,
data() {
return {
blogName:'和光同其尘',
blogDes:'坚持输出原创文章,欢迎关注!!!'
}
},
})
//2、注册组件
//全局注册
Vue.component('my-mp',mp)
const app1 = new Vue({
el:'#app1'
})
const app2 = new Vue({
el:'#app2'
})
const app3 = new Vue({
el:'#app3',
components:{ //局部注册
'MyBlog':myBlog,
// myBlog
}
})
</script>
</body>
</html>
组件嵌套
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>关注微信公众号【程序员战羽】</title>
<script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<!-- 关注微信公众号【程序员战羽】,获取更多技术文章 -->
<div id="app">
</div>
<script type="text/javascript">
//1、定义MyMp组件
const myMp = Vue.extend({
name:'my-mp',
template:`
<div><h2>本人微信公众号名称【{{name}}】</h2>
<p>{{des}}</p>
</div>
`,
data() {
return {
name:'程序员战羽',
des:'主要分享java相关技术栈知识,欢迎关注!!!'
}
}
})
//定义my-blog组件
const myBlog = Vue.extend({
name:'my-blog',
template:`
<div><h2>本人csdn博客【{{blogName}}】</h2>
<p>{{blogDes}}</p>
<my-mp></my-mp>
</div>
`,
data() {
return {
blogName:'和光同其尘',
blogDes:'坚持输出原创文章,欢迎关注!!!'
}
},
//注册组件
components:{
myMp
}
})
//定义app组件
const app = Vue.extend({
template:`
<div>
<my-blog></my-blog>
</div>
`,
//注册组件
components:{
myBlog
}
})
//创建vm
new Vue({
template:'<app></app>',
el:'#app',
//注册组件
components:{app}
})
</script>
</body>
</html>
单文件组件(常使用这种写法)
举例如下:
整体项目结构如图
MyBlog.vue文件
<template>
<div>
<p>本人csdn博客【{{blogName}}】</p>
<p>{{blogDes}}</p>
</div>
</template>
<script>
export default {
name:'MyBlog',
data(){
return {
blogName:'和光同其尘',
blogDes:'坚持输出原创文章,欢迎关注!!!'
}
}
}
</script>
<style>
p{
font-size: 2em;
text-align: center;
}
</style>
MyMp.vue文件
<template>
<div>
<p>本人微信公众号名称【{{name}}】</p>
<p>{{des}}</p>
<button @click="showName">显示微信公众号名称</button>
</div>
</template>
<script>
export default {
// name属性:当前组件名称(建议:每个单词的首字母大写)
name:'MyMp',
data(){
return {
name:'程序员战羽',
des:'主要分享java相关技术栈知识,欢迎关注!!!'
}
},
methods: {
showName(){
alert(this.name)
}
},
}
</script>
App.vue文件
<template>
<div>
<MyBlog></MyBlog>
<MyMp></MyMp>
</div>
</template>
<script>
//引入组件
import MyBlog from './MyBlog.vue'
import MyMp from './MyMp.vue'
export default {
name:'App',
components:{
MyBlog,
MyMp
}
}
</script>
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>组件基本使用_改进写法</title>
</head>
<body>
<!-- 准备一个容器 -->
<div id="app"></div>
<script type="text/javascript" src="../../js/vue.js"></script>
<script type="text/javascript" src="./main.js"></script>
</body>
</html>
main.js
import App from './App.vue'
new Vue({
el:'#app',
template:`<App></App>`,
components:{App},
})
3. 组件间传值
父组件向子组件传数据(props)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>父组件向子组件传值</title>
<script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<!--
父向子传值(prop)
父组件: div #app
子组件:title-component、hobbys-component
-->
<div id="app">
<!-- 静态传值 -->
<!-- <title-component title="我的微信公众号【程序员战羽】,爱好是:"></title-component> -->
<!-- v-bind动态传值(单个值) -->
<title-component v-bind:title="title"></title-component>
<!-- v-bind动态传值(数组) -->
<hobbys-component v-for="hobby in hobbies" v-bind:hobby="hobby" v-bind:key="hobby.id"></hobbys-component>
<!-- <hobbys-component></hobbys-component> -->
</div>
<script>
// 子组件(所需要的数据title由父组件提供)
var titleComponent = {
props: ["title"],
template: `<p>{{title}}</p>`
}
//子组件(所需要的数据hobby由父组件提供)
var hobbysComponent = {
template: `
<p>{{hobby}}</p>
`,
props: ["hobby"],
data() {
return {}
}
}
// var hobbysComponent = {
// // 数据是自身提供的 (hobbies)
// template: `<ul><li v-for='hobby in hobbies' v-bind:key='hobby.id'>{{hobby}}</li></ul>`,
// data() {
// return {
// hobbies: ['爬山', '看电视剧']
// }
// }
// }
const app = new Vue({
el: "#app",
components: {
"hobbys-component": hobbysComponent,
"title-component": titleComponent
},
data: {
title: "我的微信公众号【程序员战羽】,爱好是:",
hobbies: ['爬山', '看电视剧'],
}
})
</script>
</body>
</html>
子组件向父组件传数据($emit)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>子组件向父组件传值</title>
<script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<!--
子向父传值:使用事件传值$emit
父组件:div #app
-->
<div id="app">
<!-- v-bind:通过prop给子组件传递desc的初始值 -->
<!-- v-on监听:子组件通过$emit给父组件传递新的desc的值 -->
<div>
<update-desc v-bind:desc='desc' v-on:change-desc="onChangeDesc"></update-desc>
<!-- 此种方式不用写vue实例中的methods方法 -->
<!-- <update-desc v-bind:desc='desc' v-on:change-desc="desc=$event"></update-desc> -->
</div>
</div>
<script>
// 子组件
Vue.component('update-desc', {
props: ['desc'],
template: `
<div>
<h3>{{ desc }}</h3>
<button v-on:click='$emit("change-desc","本人csdn博客是【和光同其尘】")'>
修改描述
</button>
</div>
`
})
const app = new Vue({
el: "#app",
data: {
desc: "本人微信公众号是【程序员战羽】"
},
methods: {
onChangeDesc: function(value) {
// 将chinesename换成传递过来的数据
this.desc = value
}
}
})
</script>
</body>
</html>