开始 Vue 之旅--开发项目(二)vue组件通信

        上篇讲得是简单案例开发(开始 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开发

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值