上篇讲得是简单案例开发(开始 Vue 之旅--开发项目(一)),但是我们都知道项目不可能那么简单,会越来越复杂的,这时候我们就要合理的分配,使其项目更加简单明了。
一.组件的分配
重要是这俩种划分,但是不管这么划分其做法是一样的。下面我们以页面区域划分来做介绍
二.页面区域划分---创建新项目
(一)知识点及步骤
app.vue是入口文件 components注册组件
props 组件之间的通讯
①在组件的components文件里,创建新的页面gfooter.vue/gheader.vue
A.这个文件系统默认标签,这会使组件冲突,vue不知道这是默认标签还是组件,所以不会渲染
B.命名尽量不要用“ - ”,否则也会出现错误
尽量在前面加上前缀,比如gfooter.vue (g表示组group)
②在入口文件app.vue模板中引入组件
要在<div id="app"></div>中插入
<gheader></gheader>
<gfooter></gfooter>
<template>
<div id="app">
<gheader></gheader>
<div class="cnt">
中间内容
</div>
<gfooter></gfooter>
</div>
</template>
此时调试出出现如下错误,说明这俩个组件还没有注册
③在<script>里面注册组件
import gheader from './components/gheader.vue'
import gfooter from './components/gfooter.vue'
new Vue({
components:{gheader,gfooter},
})
注意:
(1).import 变量(在app中调用的) form 目录下的文件(可以用gheader.vue或是gheader)
(2). components与data,watch等并列
⑤渲染成功后,就会显示gheader.vue和gfooter.vue页面的内容
(二).事列
在之前的列子中操作
(1).gheader.vue
<template>
<div class="header">
<h1>{{msg}}</h1>
</div>
</template>
<script>
export default {
name: 'header',
data () {
return {
msg: '欢迎 来 vue 页面!'
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
font-weight: normal;
}
.header h1{
background:#f00;
color:#fff;
text-align:center;
width:100%;
}
</style>
(2).gfooter.vue
<template>
<div class="footer">
<p>{{msg}}</p>
</div>
</template>
<script>
export default {
name: 'footer',
data () {
return {
msg: '底部!'
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.footer p{
background:#ccc;
line-height:35px;
font-size:1.2rem;
color:#f00;
}
</style>
(3).app.vue
<template>
<div id="app">
<gheader></gheader>
<div class="index-cnt">
<h1 v-text="title"></h1>
<input v-model="newItem" v-on:keyup.enter="addNew"/>
<ul class="itemslist" >
<li v-for="(item,index) in items" v-bind:class="{active:index == num}"
v-on:click="itemactive(index)">{{item.label}}</li>
</ul>
</div>
<gfooter></gfooter>
</div>
</template>
<script>
import gheader from './components/gheader.vue'
import gfooter from './components/gfooter.vue'
//引入store.js
import Store from './store.js'
export default {
name: 'app',
data: function () {
return {
title: '水果的种类很多,让我们一起添加:',
items:Store.fetch(),
num:0,
newItem:''
}
},
components:{gheader,gfooter},
//watch对象监听的方法
watch:{
items: {
handler: function (items) {
Store.save(items);
},
deep: true
}
},
methods:{
//添加颜色
itemactive:function(index) {
this.num = index;
},
addNew:function(){
//因为列表是数组所以push()
this.items.push({
label:this.newItem
})
this.newItem=" ";//当enter完后,input的值自动消失(双向绑定的原因)
}
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
.itemslist{
text-align:left;
line-height:30px;
}
.active{
color:#f00;
}
</style>
(4).最终效果
(三).参数传递
prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。这是为了防止子组件无意修改了父组件的状态
(1).父组件(app.vue)传参数给子组件(gfooter.vue)
①只要在父组件
<gfooter fathercnt='hello! 这是父级传给子组件的内容'></gfooter>
fathercnt这个变量可以自行定义
②在子组件中
在<script>中传递参数
props: ['fathercnt']
在<template>模板中,引入
<p>{{fathercnt}}</p>
注意:props是数组,同时与与data,watch等并列
(2).子组件(gfooter.vue)传参数给父组件(app.vue)
子组件要把数据传递父组件,就得用自定义事件:
使用v-on绑定自定义事情
a.使用 $on(eventName) 监听事件
b.使用 $emit(eventName) 触发事件
注意:不能用 $on 侦听子组件抛出的事件,而必须在模板里直接用 v-on 绑定
①在app.vue模板中用v-on 绑定
在<template>模板中:
<p>子组件传递过来的参数:{{childwords}}</p>
<gfooter v-on:child-tell-me ="listenToMyBoy"></gfooter>
或是 v-on 简写:@
注意:这个child-tell-me可以自定义
在<script> 中:
methods:{
listenToMyBoy:function(msg){
this.childwords = msg;
}
}
②子组件gfooter.vue要触发事件
在<template>模板中:<button v-on:click="onClick">子组件传值给父组件</button>
在<script> 中:
methods:{
onClick:function(){
this.$emit('child-tell-me',this.msg)
}
}
(3)兄弟间传值 $bus 中转站
新建一个js文件作为兄弟组件间传值的中转站(new 一个vue)bus.js
import Vue from 'vue'
export default new Vue
组件children1把值先传到bus
<template>
<div>
<button @click="dataToBrother">toBrother</button>
</div>
</template>
<script>
import bus from '../eventBus/bus'
export default {
name: "children1",
data(){
return {
toBrother:''
}
},
methods:{
dataToBrother(){
bus.$emit('toBrother',this.toBrother)
}
}
}
</script>
组件children2从bus接收值
<template>
<div>
<h1>{{dataFromBrother}}</h1>
</div>
</template>
<script>
import bus from '../eventBus/bus'
export default {
name: "children2",
data(){
return {
dataFromBrother:''
}
},
created(){
bus.$on('toBrother',(data)=>{
this.dataFromBrother = data;
})
}
}
(4)provide和inject
这对选项是一起使用的。以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。组件得引入层次过多,我们的子孙组件想要获取祖先组件得资源,那么怎么办呢,总不能一直取父级往上吧,而且这样代码结构容易混乱。这个就是这对选项要干的事情。
provide:是一个对象,或者是一个返回对象的函数。里面呢就包含要给子孙后代的东西,也就是属性和属性值。
inject:一个字符串数组,或者是一个对象。属性值可以是一个对象,包含from和default默认值。
father组件、children组件分别如图
使用及展示如下(多层级也可以传递):
(5)$parent和$children
利用$children可以直接获取子组件的实例,利用$parent则可以直接获取到父组件的实例
代码:简单vue2开发