7. 单文件组件的使用
组件有两种:普通组件、单文件组件
普通组件的缺点:
- html代码是作为js的字符串进行编写,所以组装和开发的时候不易理解,而且没有高亮效果。
- 普通组件用在小项目中非常合适,但是复杂的大项目中,如果把更多的组件放在html文件中,那么维护成本就会变得非常昂贵。
- 普通组件只是整合了js和html,但是css代码被剥离出去了。使用的时候的时候不好处理。
将一个组件相关的html结构,css样式,以及交互的JavaScript代码从html文件中剥离出来,合成一个文件,这种文件就是单文件组件,相当于一个组件具有了结构、表现和行为的完整功能,方便组件之间随意组合以及组件的重用,这种文件的扩展名为“.vue”,比如:"Home.vue"。
-
创建组件
在组件中编辑三个标签,编写视图、vm对象和css样式代码。
7.1 template 编写html代码的地方
<template>
<div id="Home">
<span @click="num--" class="sub">-</span>
<input type="text" size="1" v-model="num">
<span @click="num++" class="add">+</span>
</div>
</template>
7.2 script编写vue.js代码
<script>
export default {
name:"Home",
data: function(){
return {
num:0,
}
}
}
</script>
7.3 style编写当前组件的样式代码
<style scoped>
.sub,.add{
border: 1px solid red;
padding: 4px 7px;
}
</style>
7.4 完成案例-点击加减数字
创建Homes.vue
<template>
<div class="add_num">
<span @click="num++">+</span>
<input type="text" size="2" v-model="num">
<span @click="num--">-</span>
</div>
</template>
<script>
export default{
name:"AddNum",
data: function(){
return {
num: 0,
}
}
}
</script>
<style scoped>
.add_num{
font-size: 32px;
}
</style>
在App.vue组件中调用上面的组件
<template>
<div id="Home">
<span @click="num--" class="sub">-</span>
<input type="text" size="1" v-model="num">
<span @click="num++" class="add">+</span>
</div>
</template>
<script>
export default {
name:"Home",
data: function(){
return {
num:0,
}
}
}
</script>
<style scoped>
.sub,.add{
border: 1px solid red;
padding: 4px 7px;
}
</style>
在开发vue项目之前,需要手动把 App.vue的HelloWorld组件代码以及默认的css样式,清楚。
上面的代码效果:
7.4 组件的嵌套
有时候开发vue项目时,页面也可以算是一个大组件,同时页面也可以分成多个子组件.
因为,产生了父组件调用子组件的情况.
例如,我们可以声明一个组件,作为父组件
在components/创建一个保存子组件的目录HomeSon
在HomeSon目录下,可以创建当前页面的子组件,例如,是Menu.vue
// 组件中代码必须写在同一个标签中
<template>
<div id="menu">
<span>{{msg}}</span>
<div>hello</div>
</div>
</template>
<script>
export default {
name:"Menu",
data: function(){
return {
msg:"这是Menu组件里面的菜单",
}
}
}
</script>
然后,在父组件中调用上面声明的子组件。
最后,父组件被App.vue调用.就可以看到页面效果.
效果:
7.5 传递数据
父组件的数据传递给子组件
例如,我们希望把父组件的数据传递给子组件.
可以通过props属性来进行数据传递.
传递数据三个步骤:
-
在父组件中,调用子组件的组名处,使用属性值的方式往下传递数据
<Menu :mynum="num" title="home里面写的数据"/> # 上面表示在父组件调用Menu子组件的时候传递了2个数据: 如果要传递变量[变量可以各种类型的数据],属性名左边必须加上冒号:,同时,属性名是自定义的,会在子组件中使用。 如果要传递普通字符串数据,则不需要加上冒号:
-
在子组件中接受上面父组件传递的数据,需要在vm组件对象中,使用props属性类接受。
<script> export default { name:"Menu", props:["mynum","title"], data: function(){ return { msg:"这是Menu组件里面的菜单", } } } </script> // 上面 props属性中表示接受了两个数据。
-
在子组件中的template中使用父组件传递过来的数据.
<template> <div id="menu"> <span>{{msg}},{{title}}</span> <div>hello,{{mynum}}</div> </div> </template>
效果:
步骤流程:
使用父组件传递数据给子组件时, 注意一下几点:
-
传递数据是变量,则需要在属性左边添加冒号.
传递数据是变量,这种数据称之为"动态数据传递"
传递数据不是变量,这种数据称之为"静态数据传递"
-
父组件中修改了数据,在子组件中会被同步修改,但是,子组件中的数据修改了,是不是影响到父组件中的数据.
这种情况,在开发时,也被称为"单向数据流"
子组件传递数据给父组件
-
在子组件中,通过
this.$emit()
来调用父组件中定义的事件.<template> <div> <p>Post的子组件</p> <h2>{{fnum}}</h2> <p>data={{data}}</p> <p>fnum={{fnum}}</p> <div><input type="text" v-model="fnum"></div> </div> </template> <script> export default { name: "PostSon", // 父组件传递数据给子组件: 1. 在父组件中调用子组件的组件名称标签上面声明属性和传递值,2. 在子组件中通过props进行接收 props:["data","fnum"], // 接受父组件中传递过来的数据 // 子组件传递数据给父组件[事件的方式进行传递]: watch:{ fnum(){ console.log(this.fnum); // this.$emit("父元素的自定义事件","要传递的数据"); // 通过this.$emit()方法,子组件可以把数据传递给父组件 this.$emit("postparentdata",this.fnum); } } } </script> <style scoped> </style>
-
父组件中声明一个和子组件中
this.$emit("自定义事件名称")
对应的事件属性。<template> <div> <h1>num={{num}}</h1> <Son data="我是付组件里面的内容" :fnum="num" @postparentdata="getsondata"></Son> </div> </template>
-
父组件中,声明一个自定义方法,在事件被调用时,执行的。
<script> import Son from "./PostSon" export default { name: "Post", data(){ return { num: 100, } }, components:{ Son:Son, }, methods:{ getsondata(message){ console.log("父组件"+message); this.num = message; } } } </script>