Vue组件学习、组件通信

Vue组件学习、组件通信

    • 1. 了解组件
          • 组件的特点:
    • 2. 创建组件
        • 2.1. 使用vue-cli创建vue项目
        • 2.2 全局定义组件
        • 2.3 局部定义组件
    • 3. 组件间通信/交互/传值
        • 1. 父组件与子组件之间的通信
        • 2. 兄弟组件之间的通信
        • 3. 非关系组件之间的通信
    • 4.单向数据流(数据更改的方法)

1. 了解组件

组件(Component)是 Vue.js 最强大的功能之一。

组件可以扩展 HTML 元素,封装可重用的代码。

组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树:
Vue组件学习、组件通信_第1张图片

组件是可复用的 Vue 实例,且带有一个名字:在以下例子中是 。它们与 new Vue 接收相同的选项,例如 data、computed、watch、methods 以及生命周期钩子等。仅有的例外是像 el 这样根实例特有的选项没有。

<div id="components-demo">
  <button-counter>button-counter>
div>
组件的特点:
  • 组件可以进行无数次的复用
  • 组件的data必须是一个函数,确保每一个实例可以维护一份data返回的对象的独立拷贝,使得任何一个组件的改变不会影响到其他被复用的组件。
    举个例子:Header.vue组件同时被a.vue和b.vue复用,data写成函数形式能让Header.vue在每一个页面中的引用形成一个独立的复用,在a.vue中修改Header的data值,不会对b.vue中的Header造成影响。这就是我们必须要把组件的data写成函数形式的原因,确保组件的独立复用,数据深拷贝。

2. 创建组件

2.1. 使用vue-cli创建vue项目

(见vue-cli手脚架创建vue项目详细步骤)

2.2 全局定义组件

  1. 创建vue文件,找到项目下的components目录,在这里创建组件,我创建好了Footer.vue,Header.vue
    Vue组件学习、组件通信_第2张图片
  2. 找到main.js文件,全局注册组件Vue.component(‘component-a’, { /* … */ })
    Vue组件学习、组件通信_第3张图片
    注册:
import Vue from 'vue'
import App from './App.vue'
// 引入组件路径
import Header from '@/components/Header'
import Footer from '@/components/Footer'
// 全局注册组件 vue.component()
Vue.component('Header',Header)
Vue.component('Footer',Footer)

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
}).$mount('#app')

2.3 局部定义组件

  1. 创建vue文件,找到项目下的components目录,在这里创建组件,我创建好了Footer.vue,Header.vue
    Vue组件学习、组件通信_第4张图片

  2. 创建好vue文件之后,在app中全局注册,在app.vue中的script标签引入,注册的组件只能在当前app.vue中使用。

script>
import Header from './components/Header.vue'
import Footer from './components/Footer.vue'

export default {
  name: 'App',
  //局部注册
  components: {
    Header,
    Footer,
  }}
</script>

3. 组件间通信/交互/传值

组件间通信分类可以分成:

  1. 父组件与子组件之间的通信
  2. 兄弟组件之间的通信
  3. 非关系组件之间的通信
    Vue组件学习、组件通信_第5张图片

1. 父组件与子组件之间的通信

1. 父组件传给子组件:

props传递数据:子组件设置props属性,定义接收父组件传递过来的参数

props的两种定义格式:

props:[]  //定义为数组,数组中每一项都是变量
props:{}  //定义为对象,可以指定数据传递的类型,是否是必须的,指定默认值等等

静态传参:参数名=“参数值”
动态传参:参数名前加冒号,:参数名=“参数值”,

创建Father.vue父组件:

<template>
  <div>
    <h1>{{msg}}h1>
    <hr>
    <Child :msg="msgData">Child>
  div>
template>
<script>
  // 引入子组件
  import Child from './Child.vue';
  export default{
    components:{
      Child,
    },
    data(){
      return{
        msg:'我是父组件',
        msgData:"父组件数据123"
      }
    }
  }
script>

定义子组件Child.vue:props:[] 格式

<template>
  <div>
    {{msg}}---{{visible}}---{{num}}
  </div>
</template>
<script>
  export default{
    props:["msg","visible","num"],
    data(){
      return{
        
      }
    }
  }
</script>

定义子组件Child.vue:props:{} 格式

<template>
  <div>
    {{msg}}---{{visible}}
    <br>
    --------
    {{num}}-----{{typeof num}}
    <br>
    --------
    {{ages}}
    
  div>
template>
<script>
import { stringify } from 'qs';

  export default{
    // props:["msg","visible","num"],

    props:{
      msg:{
        type:String,
        //必传项
        required:true,
        // 设置默认值 如果父组件没有传该值,则使用默认值
        default(){
          return "hello"
        }
      },
      num:Number,
      visible:Boolean,
      ages:{
        type:Array,
        //自定义校验器规则
        validator(val){
          return val>18
        }
      }
      // msg,
      // num,
      // visible
    },
    data(){
      return{
        
      }
    }
  }
script>

2. 子组件传给父组件

$emit():由子组件发射事件(自定义事件)

$emit(‘事件名’,‘参数值’)

Father.vue:

<template>
  <div>
    <h1>{{msg}}</h1>
    <hr>
    <Child @my-event="handler"></Child>
  </div>
</template>
<script>
  // 引入子组件
  import Child from './Child.vue';
  export default{
    components:{
      Child,
    },
    data(){
      return{
        msg:'我是父组件',
        msgData:"父组件数据123"
      }
    },
    methods:{
      handler(a){
        console.log(a);
        this.msg=a
      }
    }
  }
</script>

Child.vue:

<template>
  <div>
    <button @click="toSend">向Father发送数据</button>
  </div>
</template>
<script>
  export default{
    data(){
      return{
        subMsg:"把123给你"
      }
    },
    methods:{
      toSend(){
        this.$emit('my-event',this.subMsg)
      }
    }
  }
</script>

2. 兄弟组件之间的通信

兄弟之间通信用EventBus,创建一个事件时间总线,兄弟组件之间通过 e m i t 触发自定义事件, emit触发自定义事件, emit触发自定义事件,emit第二个参数为传递的值,另一个兄弟组件通过$on监听自定义的事件。
这里在src下创建了一个事件总线eventBus.js:

import Vue from 'vue';
export default new Vue()

创建兄弟组件Header.vue和Footer.vue,两者都要引入事件总线

Header.vue:

<template>
  <div>
    {{msgH}}
    <button @click="handler">传值给Footer</button>
  </div>

</template>
<script>
  //引入事件总线
  import Bus from '../eventBus.js'
  console.log(Bus,'事件总线');
  export default{
    data(){
      return{
        msgH:"头部组件",
        Footer:"这是兄弟组件Footer"
      }
    },
    methods:{
      handler(){
        //兄弟组件传值
        // 1.兄弟组件使用$emit 发射事件 携带参数
        // console.log(this.Footer);
        Bus.$emit('toFoot',this.Footer)
      }
    }
  }
</script>

Footer.vue:

<template>
  <div>
    {{msgF}}
  </div>
</template>
<script>
// 引入事件总线
  import Bus from '../eventBus.js'
  import FooterChild from './FooterChild.vue'
  export default{
    components:{
      FooterChild
    },
    data(){
      return{
        msgF:"底部组件"
      }
    },
    created(){
      Bus.$on('toFoot',(a)=>{
        console.log(a,'这是Header传给我的值');
      })
    }
  }
</script>

3. 非关系组件之间的通信

provide和inject:

  • 在祖先组件上定义provide属性,返回传递的值
  • 在后代组件上接收组件传递过来的值
    祖先组件:
 // 祖先组件使用provide方法提供传递的数据
  provide(){
    return {
      "msg":this.msg,
      'a':this.a
    }
  }

子孙组件:

 inject:['msg','a']

4.单向数据流(数据更改的方法)

上层的数据流向下层。
在父组件给子组件传值的时候,父组件可以改子组件的数据,但是子组件不可以更改父组件的数据。

你可能感兴趣的:(Vue,vue.js,前端)