Writing in the front

  • Knowledge is power. – Angela
  • Knowledge is power, but more important is the skill to use it. — — bacon
  • This paper mainly introduces the common communication mode between VUE components, boundary situation and the use of slot.

What is componentization?

The VUE component system provides an abstraction that allows us to build large applications using individual reusable components. Any type of application interface can be abstracted into a tree of components. Componentalization can improve development efficiency, facilitate repeated use, simplify debugging steps, improve project maintainability, and facilitate multi-person collaborative development.

Typically an application is organized as a nested tree of components: for example, you might have headers, sidebars, content areas, and so on, each of which contains other components like navigation links, blog posts, and so on. As shown below:

1. Common communication modes of components

  1. Father to Son: Props
  2. Child to Parent: User-defined event
  3. Communication across hierarchies: Event Bus
  4. Communication across levels: Vuex, a state-management mode developed for vue.js applications

1.1 props

/ / the parent component
<Child1 msg="some message from parent"></Child1>

/ / Child1 components
<template>
    <div class="border">I'm child component 1<div>{{msg}}</div>
    </div>
</template>

<script>
export default {
  props: {
    msg: {
      type: String.default: ' '
    }
  },
  data () {
    return{}}}</script>
Copy the code

Results:

1.2 the event

/ / the parent component
<template>
    <div>
        <h2>Component communication</h2>
        <! -- Props props -->
        <Child1 msg="some message from parent"></Child1>
        <! -- Custom event -->
        <Child2 @clickSon="getMsg"></Child2>
        <p>Child2: {{child2Info}}</p>
    </div>
</template>

<script>
import Child1 from './Child1'
import Child2 from './Child2'

export default {
  components: {Child1, Child2},
  data () {
    return {
      child2Info: ' '}},methods: {
    getMsg (info) {
      this.child2Info = info
    }
  }
}
</script>


/ / Child2 components
<template>
    <div @click="$emit('clickSon', 'msg from child2')" class="border">I'm child component 2</div>
</template>

<script>
export default {
  data () {
    return {}
  },
  mounted () {
    this.$bus.$on('send'.(msg) = > {
      console.log('Child1 clicks and the message is :' + msg)
    })
  }
}
</script>
Copy the code

Results:

1.3 Bus

Values can be passed between any two components using an event bus. The event bus leverages the observer pattern of design pattern. Its core implementation is as follows:

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))
    }
  }
}

export default Bus
Copy the code

Usage:

1. Register $bus in main.js

import Vue from 'vue'
import App from './App'
import router from './router'
import Bus from './bus'
Vue.prototype.$bus = new Bus()
Vue has already implemented the event Bus, so we can use the following method to introduce the event Bus
// Vue.prototype.$bus = new Vue()

Vue.config.productionTip = false

new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>'
})
Copy the code

Select * from Child1; select * from Child2; select * from Child1;

Child2

<template>
    <div @click="$emit('clickSon', 'msg from child2')" class="border">I'm child component 2</div>
</template>

<script>
export default {
  data () {
    return {}
  },
  mounted () {
  	// When the component is mounted, it listens for send events and prints messages
    this.$bus.$on('send'.(msg) = > {
      console.log('Child1 clicks and the message is :' + msg)
    })
  }
}
</script>

Copy the code

Child1

<template>
    <div class="border">I'm child component 1<button @click="$bus.$emit('send', 'value sent by child component 1 via bus ')">Trigger event bus</button>
    </div>
</template>
Copy the code

Child2 prints: ‘Child1 clicked on the value sent by bus from child component 1 ‘

1.4 vuex

Vuex is a state management mode developed specifically for vue.js applications. It uses centralized storage to manage the state of all components of an application and rules to ensure that the state changes in a predictable way. Here is not an example ~ next period to do a complete analysis to you. For those who want to learn, visit vuEX Chinese website

2. Boundary situation

In most cases, it is not recommended to use boundary cases, but to replace them with better alternatives. But knowing the boundary case can be a great help in understanding the source package componentized repository. As the website says: In most cases, it’s best not to touch inside another component instance or manually manipulate DOM elements. But there are situations where it’s appropriate to do these things.

2.1 $root — Access the root instance

Within the child component of each new Vue instance, its root instance is accessible via $root Property.

// Vue root instance
new Vue({
  data: {
    foo: 1
  },
  computed: {
    bar: function () { / *... * /}},methods: {
    baz: function () { / *... * /}}})// All child components can access or use this instance as a global store:
// Get the data for the root component
this.$root.foo
// Write data to the root component
this.$root.foo = 2
// Access the computed properties of the root component
this.$root.bar
// Call the root component's method
this.$root.baz()
Copy the code

$2.2 $parent — Accesses the parent component instance

Sibling components communicate via common ancestor bypass

// brother1
this.$parent.$on('foo', handle) 
// brother2
this.$parent.$emit('foo')
Copy the code

2.3 $children — Access all child component instances or child elements

The parent component can communicate with the children by accessing the children. Note: Children access child components for parent-child communication. Note: Children access child components for parent-child communication. Note: Children does not guarantee child order.

  // parent 
  this.$children[0].xx = 'xxx'
Copy the code

2.4 $refs — Access child component instances or child elements

Gets the child node reference

// parent
<HelloWorld ref="hw"/>

mounted() { 
	this.$refs.hw.xx = 'xxx'
}
Copy the code

2.5 Provide/Inject — Dependency injection

Can realize the transmission of values between ancestors and descendants

// Ancestor element
provide() {
	return {foo: 'foo'}}/ / offspring
<template>
    <div class="border">
        <p>{{foo}}</p>
    </div>
</template>

<script>
export default {
  inject: ['foo']}</script>
// You can also set aliases in descendant elements to prevent naming conflicts
 inject: {
    bar: {
      from: 'foo'<p>{{bar}}</p>Copy the code

3. Non-prop features

Used for intergenerational transmission, only one generation.

3.1 $attrs

Contains property bindings (except class and style) that are not recognized (and retrieved) as prop in the parent scope. When a component does not declare any prop, all parent-scoped bindings (except class and style) are included, and internal components can be passed in via V-bind =”$attrs” — useful when creating higher-level components.

// Ancestor component
 <Child2 msg="some message from parent"></Child2>
 
/ / Child2 components
<template>
    <div>
      <Grandson v-bind="$attrs"/>
    </div>
</template>

<script>
import Grandson from './Grandson'
export default {
  components: {Grandson},
  data () {
    return{}}}</script>

// Grandchild component
<template>
    <div class="border">
        <div>The grandson components</div>
        <div>$attr :{{MSG}}</div>
    </div>
</template>

<script>
export default {
  props: {
    msg: {
      type: String}}}</script>

Copy the code

Results:

3.2 $listeners

Passthrough event

// Ancestor component
 <Child2 @clickSon="getMsg"></Child2>
  methods: {
   getMsg (info) {
     console.log(info)
   }
 }
 
/ / Child2 components
<template>
    <div>
      <Grandson v-on="$listeners"/>
    </div>
</template>

<script>
import Grandson from './Grandson'
export default {
  components: {Grandson},
  data () {
    return{}}}</script>

// Grandchild component
<template>
    <div class="border" @click="$emit('clickSon', 'msg from grandSon')">
        <div>The grandson components</div>
    </div>
</template>
Copy the code

4. The slot

Slot syntax is a content distribution API implemented by Vue for composite component development. It is widely used in the development of common component library.

4.1 Anonymous Slot

// Layout
<div class="body">
  <slot></slot>
</div>

// parent
<Layout>
	<! -- Anonymous slot -->
	<template>The best time to plant a tree is ten years ago, and then now!</template>
</Layout>
Copy the code

4.2 Named Slot

// Layout
<div class="header">
  <slot name="header"></slot>
</div>

// parent
<Layout>
	<template v-slot:header>Welcome to the vUE world of the little girl picking up code</template>
</Layout>
Copy the code

4.3 Scope slot

// Layout
<div class="footer">
  <slot name="footer" :childValue="footerContent"></slot>
</div>

// parent
<Layout>
	<template v-slot:footer="value">{{value.childValue}}</template>
	<! Object deconstruction -->
    <! -- <template v-slot:footer="{childValue}">{{childValue}}</template> -->
</Layout>
Copy the code

The complete code is as follows:

The parent component

<template>
  <div>
    <h2>slot</h2>
    <! - slot - >
    <Layout>
      <! -- named slot -->
      <template v-slot:header>Welcome to the vUE world of the little girl picking up code</template>
      <! -- Anonymous slot -->
      <template>The best time to plant a tree is ten years ago, and then now!</template>
      <! -- Scope slot -->
      <template v-slot:footer="value">{{value.childValue}}</template>
       <! Object deconstruction -->
       <! -- <template v-slot:footer="{childValue}">{{childValue}}</template> -->
    </Layout>
  </div>
</template>

<script>
import Layout from './Layout.vue'
export default {
  name: 'Slot'.components: {
    Layout
  }
}
</script>
Copy the code

Layout components

<template>
  <div>
    <div class="header">
      <slot name="header"></slot>
    </div>
    <div class="body">
      <slot></slot>
    </div>
    <div class="footer">
      <slot name="footer" :childValue="footerContent"></slot>
    </div>
  </div>
</template>

<script>
export default {
  data () {
    return {
      footerContent: 'Complacency is the enemy of study. If you want to learn anything seriously, you must never start with complacency.'}}}</script>

<style scoped>
.header {
  background-color: rgb(252.175.175);
}
.body {
  display: flex;
  background-color: rgb(144.250.134);
  min-height: 100px;
  align-items: center;
  justify-content: center;
}
.footer {
  background-color: rgb(114.116.255);
}
</style>

Copy the code

The effect is as follows:

These are the essential knowledge for componentized development. Please write the small pieces by hand with me after you get


The end~