Skip to content
  • props

    子组件接收到后不能改变父组件传递的数据的指向,当父组件重新渲染时,数据会被覆盖。

    js
    <Foo :msg="msg"></Foo>
    
    export default {
    
      // 简写
      props:['msg']
      
      // 完整写法
      props:{
          msg:{
              type: String, // 限制类型
              type: [String, Number, Object], // 限制类型
              required: true, // 必要性
              default: '默认值', // 默认值为基本数据类型
              default: () => [], // 默认值为数组
              default: () => ({}) // 默认值为对象
          }
      },
    }
  • sync修饰符

    实现了父组件向子组件传递的数据的双向绑定

    js
    <Child :msg.sync="msg"></Child>
    
    export default {
    
      props:['msg'],
      
      mounted () {
      
        // 子组件修改数据
      this.$emit('update:msg', 'world')
      }
    }
  • v-model

    和sync修饰符类似,实现了父组件向子组件传递的数据的双向绑定

    js
    <Foo v-model="msg"></Foo>
    
    export default {
    
      props:['msg'],
      
      model: {
      
        // 定义修改时emit的事件名,默认为input
        event: 'updateMsg'
      }
      
      mounted () {
      
        // 子组件修改数据
        // this.$emit('input', 'world')
      this.$emit('updateMsg', 'world')
      }
    }
  • ref

    标签中直接写 ref="xxx"

    通过this.$refs.xxx获取

    给html内置标签打ref,获取到的是真实的DOM节点

    给组件标签打ref,获取到的是组件实例

    js
    <Foo ref="foo"></Foo>
    
    export default {
      mounted () {
      const foo = this.$refs.foo
        foo.someData // 使用子组件的数据
        foo.someMethod() // 调用子组件的方法
      }
    }
  • $emit / v-on

    子组件通过派发事件的方式给父组件传递或触发父组件的某些操作

    js
    // Foo.vue
    <button @click="$emit('sendMsg', 'hello')">按钮</button>
    
    // App.vue
    <Foo @sendMsg="recvMsg"></Foo>
    
    export default {
        components: {
          Foo
        },
    
        methods: {
          recvMsg (msg) {
            console.log(msg)
          }
        }
      }
  • $attrs / $listeners

    多层嵌套组件传递数据时,如果只是传递数据,而不做中间处理的话可以用这个,比如父组件向孙子组件传递数据

    $attrs:父标签中写的属性,不包括class、style以及props中接收的数据

    $listeners:父标签中绑定的事件,不包括.native修饰符的事件

    // App.vue 父组件
    <Foo :name="name" :age="age"></Foo>
    
    // Foo.vue 子组件
    <Bar v-bind="$attrs" msg=“hello”></Bar>
    
    export default {
      props: ['name'],
      
      mounted () {
        console.log(this.$attrs) // { age: 18 },因为name写进了props中
      }
    }
    
    // Bar.vue 孙组件
    export default {
      mounted () {
        console.log(this.$attrs) // { age: 18, msg: "hello" }
      }
    }
  • $children / $parent

    $children:获取到一个所有子组件(不包含孙子组件)的 VC实例组成的数组,可以拿到子组件中所有数据和方法等

    $parent:获取到父组件的VC实例,可以拿到父组件中所有数据和方法等

    // App.vue
    <Foo></Foo>
    
    export default {
        components: {
          Foo
        },
        
        data () {
          return {
            name: 'Tom'
          }
        },
        
        methods: {
          sayName () {
    
          }
        },
        
        mounted () {
          console.log(this.$children[0].age) // 18
          console.log(this.$children[0].sayAge) // ƒ sayAge() {}
        }
    }
    
    // Foo,vue
    export default {
      data () {
        return {
          age: 18
        }
      },
      methods: {
        sayAge () {
    
        }
      },
      mounted () {
        console.log(this.$parent.name) // 'Tom'
        console.log(this.$parent.sayName) // ƒ sayName() {}
      }
    }
  • provide / inject (依赖注入)

    provide:祖先组件向所有后代组件注入依赖

    inject:在任何后代组件中都可以直接拿来用

    要注意的是 provide 和 inject 的绑定并不是响应式的,除非传入的就是一个可监听的对象

    // App.vue
    <Foo></Foo>
    
    export default {
        components: {
          Foo
        },
        
        data () {
          return {
            name: 'Tom'
          }
        },
        
        methods: {
          sayName () {
    
          }
        },
        
        // 对象形式,只能注入自定义数据,因为没有this
        provide: {
          constant: 'constant',
          // sayName: this.sayName, // 找不到
          // name: this.name, // 找不到
        }
    
    	// 返回一个对象的函数形式,可以注入data和method等
        provide () {
            return {
                constant: 'constant',
                sayName: this.sayName,
                name: this.name,
            }
        }
    }
    
    // Foo.vue
    export default {
        inject: ['constant', 'sayName', 'name'],
    
        mounted () {
            console.log(this.constant)  
            console.log(this.sayName)  
            console.log(this.name)
        }
    }
  • EventBus

    父子、兄弟、跨级组件都可以完成通信

    // 事件总线,单独抽取成bus.js
    import Vue from "vue"
    
    const $bus = new Vue()
    
    export default $bus
    
    // App.vue
    import $bus from './bus'
    
    export default {
    	methods: {
            handler () {
                $bus.$emit('sendMsg', 'hello')
            }
        },
    }
    
    // Foo.vue
    import $bus from '../bus'
    
    export default {
      mounted () {
        $bus.$on('sendMsg', (msg) => {
          console.log(msg)
        })
      },
      
      beforeDestroy() {
     	$bus.$off('sendMsg')
      },
    }
    
    // 全局事件总线,main.js中注册
    // 方法一
    import Vue from 'vue'
    import App from './App.vue'
    
    Vue.prototype.$bus = new Vue() // 注册全局事件总线
    
    new Vue({
      render: h => h(App),
    }).$mount('#app')
    
    // 方法二
    new Vue({
      beforeCreate () {
        Vue.prototype.$bus = this
        // Vue.prototype.$bus = new Vue()
      },
      
      render: h => h(App),
    }).$mount('#app')
  • Vuex

    父子、兄弟、跨级组件都可以完成通信

  • $root

    获取当前组件实例所属根组件的实例(main.js),如果当前组件实例没有父实例,则实例将会是它自己

  • slot

    将子组件的数据传给父组件,由父组件决定使用哪些数据

    // Foo.vue
    <slot :age="age"></slot>
    
    // App.vue
    <Foo v-slot="{ age }">
      {{ age }}
    </Foo>

父子组件通信:

  • props
  • ref
  • .sync
  • v-model
  • $emit / v-on
  • $children / $parent
  • $attrs / $listeners
  • Vuex

兄弟组件通信:

  • Vuex
  • EventBus
  • $parent

跨层级组件通信:

  • Vuex
  • EventBus
  • provide/inject
  • $attrs / $listeners
  • $root