Note1:Vue 组件化

108 阅读1分钟

Vue 组件化

组件是可复用Vue 实例

  • 组件的目的是为了复用
  • 组件与 new Vue() 接收相同的选项,例如 datacomputedwatchmethods 以及生命周期钩子等 (仅有的例外是像 el 这样根实例特有的选项。 )

组件间通信

1.父组件-->子组件

  • 通过Props向子组件传递数据(常用)
// 子组件注册 prop
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  }
}
// 父组件把数据作为一个自定义attribute传递进来
<hello-World msg="Welcome to Your Vue.js App"/>
  • $refs(常用)
<!-- 父组件 -->
<template>
	<hello-World msg="Welcome to Your Vue.js App" ref="hw"/>
</template>

<script>
    // 得到子组件
    mounted() {
        this.$refs.hw
     }
</script>
  • $children(不常用,导致组件间耦合性太高)
<!-- 父组件 -->
<template>
	<hello-World msg="Welcome to Your Vue.js App"/>
</template>

<script> 
    mounted() {
        // 得到第一个子组件
         this.$children[0]
     }
</script>

当前实例的直接子组件。需要注意 $children 并不保证顺序,也不是响应式的

2.子组件-->父组件

  • 自定义事件(常用)
// 子组件调用内建的 $emit 方法触发事件 
<button @click="$emit('custom-event')">click</button>
<button @click="$emit('custom-event', 'hello')">click</button>

// 父级组件可以像处理 native DOM 事件一样, 监听子组件实例的任意事件 
<hello-World msg="Welcome to Your Vue.js App" @custom-event="handleEvent"/>
// 自定义事件传过来的值    
handleEvent(msg){
  console.log('父组件', msg);
}

3.兄弟组件

  • 通过共同祖辈组件 $parent$root(不常用,导致组件间耦合性太高)
<!-- child1 -->
<template>
    <button @click="handleClick">click</button>
</template>

<script>
export default {
  name: "Child1",
  methods: {
    handleClick() {
      this.$parent.$emit("msg-from-child1", "hello");
    }
  }
};
</script>

<!-- child2 -->
<script>
created() {
    this.$parent.$on("msg-from-child1", msg => {
      console.log(msg);
    });
 }
</script>

4.祖先和后代之间

  • provide/inject
// 祖先
provide: {
   foo: "bar"
}
// 后代
inject: ["foo"]

provide 和 inject 主要在开发高阶插件/组件库时使用。并不推荐用于普通应用程序代码中。

5.任意两个组件间的通信

  • 事件总线(常用)
class Bus {
  constructor() {
    this.callbacks = {};
  }
  $on(name, fn) {
    this.callbacks[name] = this.callbacks[name] || [];
    this.callbacks[name].push(fn);
  }

  $emit(name, args) {
    if (this.callbacks[name]) {
      this.callbacks[name].forEach(cb => cb(args));
    }
  }
}
Vue.prototype.$bus = new Bus();
//或者
Vue.prototype.$bus = new Vue();
  • Vuex(常用)

插槽slot

作用分发内容

1.匿名插槽

<!-- CustomButton.vue -->
<!-- 子组件 -->
<button type="submit">
    <!-- 匿名插槽 -->
     <slot></slot>
    <!-- 后备内容 -->
   <!--  <slot>Submit</slot>-->
 </button>

<!-- 父组件 -->
<custom-button>save</custom-button>

2.具名插槽

<!-- CustomCard.vue -->
<!-- 子组件 -->
<template>
    <div>
        <header>
            <slot name="header"></slot>
        </header>
        <main>
            <slot></slot>
        </main>
        <footer>
            <slot name="footer"></slot>
        </footer>
    </div>
</template>

<!-- 父组件 -->
 <custom-card>
      <template v-slot:header>
        <h1>header插槽的内容</h1>
      </template>
      <template>
        <p>默认slot的内容</p>
      </template>
      <template v-slot:footer>
        <div>footer插槽的内容</div>
      </template>
</custom-card>

3.作用域插槽

父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。

有时让插槽内容能够访问子组件中才有的数据是很有用的

<!-- SlotComp.vue -->
<!-- 子组件 -->
  <div>
    <slot :user="user"></slot>
  </div>

<!-- 父组件 -->
<slot-comp v-slot="slotProps">{{slotProps.user}}</slot-comp>
<slot-comp v-slot="{user}">{{user}}</slot-comp>