1. Vue componentization idea

Componentization provides an abstraction that allows us to develop individual reusable components to build our applications.

Any application is abstracted into a tree of components.

Application of componentization:

  1. As much as possible, break the page down into small, reusable components
  2. This makes our code easier to organize, manage, and more extensible

2. Componentize basic usage details

2.1 Basic steps for registering components

The use of componentization can be divided into three steps:

  1. Create the component constructor
  2. Certified components
  3. Using the component

Let’s write a simple component by following the steps above:


<body>
  <div id="app">// Step 3: Use components in Vue instances<my-cpn></my-cpn>
  </div>
</body>
<script src=".. /vue.js"></script>
<script>
 // Step 1: Create the component constructor
  var cpn = Vue.extend({
    template: ` < div > < h1 > I am a componentized title < / h1 > < p > I am a p cousin of componentization < / p > < / div > `
  })
 // Step 2: Register the component
  Vue.component('my-cpn', cpn)
  
  var vue = new Vue({
    el: '#app'
  })
</script>
Copy the code

2.2 Global components and Local Components

The example above is actually a global component. What is a global component? It can be used in any Vue instance.

What is a local component, as the name implies, is only available in a specific Vue instance. How do you define it? It is as simple as writing its second step of registration inside the Vue instance.

In fact, in our development process, we usually have a single Vue instance, and the most used components are local components

Examples of local components:

 var cpn = Vue.extend({
    template: ` < div > < h1 > I am a componentized title < / h1 > < p > I am a p cousin of componentization < / p > < / div > `
  })
  // Vue.component('my-cpn', cpn)

  var vue = new Vue({
    el: '#app'.components: {mycpn:cpn
    }
  })
Copy the code

2.3 Parent and Child Components

As mentioned earlier, in real development, there is the possibility of nested components within components. Hence the concept of parent-child components.

You can register another component in the parent component and use it directly in the parent component’s template.

Let’s look at the code:

  var cpn1 = Vue.extend({
    template: ` < div > < h1 > I am a componentized title 1 < / h1 > < p > I am a p cousin of componentization < / p > < / div > `
  })
  var cpn2 = Vue.extend({
    template: ` < div > < h1 > I am a componentized title 2 < / h1 > < p > I am a p cousin of componentization < / p > < mycpn1 > < / mycpn1 > < / div > `.components: {mycpn1:cpn1
    }
  })
  var vue = new Vue({
    el: '#app'.components: {
      mycpn2: cpn2
    }
  })
Copy the code

The above code is the use of parent-child components, that is, we use the tag directly, we can achieve our expectations.

But we can only use tags directly in the HTML code because this component is not registered in the VUE instance, only in the parent component.

2.4 Separate writing of components

When we define components above, our components are represented as strings, which makes our code look messy.

So we have a separate way of writing components.

Before I introduce the separate writing of the component, I’ll introduce the following syntactic sugar form created by the previous component instead of extend.

Simply place the extend object argument in the second parameter of the registration operation. The Vue base layer still calls extend to create the component.

Vue.component('mycpn', {template: 'content'})Copy the code

Let me write the following components separately:

1. Use script tags:

Component content:

  <script type="text/x-template" id="test1">
    <div>
      <h1>I'm a componentized title</h1>
      <p>I'm a p cousin of componentization</p>
    </div>
  </script>
Copy the code

Registration:

Vue.component('mycpn', {
    template:'#test1'
})
Copy the code

2. Use the template tag:

Component content:

  <template id="test1">
    <div>
      <h1>I'm a componentized title</h1>
      <p>I'm a p cousin of componentization</p>
    </div>
  </template>
Copy the code

Registration: same as above

3. Componentized data stores data

3.1 Storage of component data

Let me start by asking the question, can the data from the component be placed in a Vue instance?

The answer is no. Why? My understanding here is that a component is a template with a specific function. Therefore, it must have its own place to store data, and if it is in a top-level Vue instance, it loses the original purpose of componentized development.

Without further ado, we can try:

 <div id="app">
    <mycom></mycom>
  </div>
  <template id="mypom">
    <h2>{{title}}</h2>
  </template>
</body>
<script src=".. /vue.js"></script>
<script>
   new Vue({
     el:'#app'.data: {title:'ha ha'
     },
     components: {mycom: {template:'#mypom'}}})Copy the code

The results are not displayed, so we conclude that the data in the component cannot be placed in the Vue instance.

In fact, the storage of our component data exists in the data attribute of the extend parameter object. Vue officially stipulates that the data attribute must be a function, and the return value must be an object, storing the required data inside the object.

Let’s look at the code:

Vue.component('mycom',{template:'#mypom', data(){return {title:' I am the title '}}})<template id="mypom">
    <h2>{{title}}</h2>
  </template>
Copy the code

So have we considered the question of why the component’s data property must be a data that returns an object? Then look at:

3.2 Why must a component be a function data

First of all, vUE components are mostly used for reuse, so every time it is reused, it will use our data attribute. If data is an object at this time, there will be a problem when we reuse components. Data in one component changes, so data in all components will change. So vUE’s bottom layer adds this setting to the data property.

Of course, this property can also be encountered during development, which can expose the object and then introduce it to achieve consistency of all component data.

Let’s look at a very simple example:

Write a counter component

 Vue.component('mycom', {
    template: '#mypom'.data() {
      return {
        message: 0}},methods: {
      add() {
        this.message++
      },
      decre() {
        this.message--
      },
    },
  })
Copy the code

Use:

<div id="app">
    <mycom></mycom>
    <mycom></mycom>
    <mycom></mycom>
    <mycom></mycom>
  </div>
Copy the code

And then we see that each component is independent, and that’s because, this is due to the data property being a function. Therefore, they do not share data within an object.

But it’s also easy if we have this need for one move, all moves.

  var obj={
    message: 0
  }
  Vue.component('mycom', {
    template: '#mypom'.data() {
      return obj
    },
    methods: {
      add() {
        this.message++
      },
      decre() {
        this.message--
      },
    },
  })
Copy the code

That’s what we want to do.

4. Parent and child component communication

Now that we know the concept of parent-child components, another problem arises. Imagine a scenario, if we now have a demand of network request, but our interface using the modular way, first of all, to be sure our network operation request must be made in the outermost components, but if we child components need to request to the parent component of some data, so at this time. The concept of parent-child component communication is that we cannot implement the corresponding network request in each component, which is certainly not feasible.

The following figure shows a mode flow of component communication

4.1 the father the son

One use scenario for father to son is what we talked about above.

Parent – to – child is done primarily by a props property.

Let’s go straight to some code:

 var cpm = {
    template: '#cpm'.props: ['cmovies'.'cmessages'],}new Vue({
    el: '#app'.data: {
      movies: ['1' movie.'the movie 2'.'3'].messages: 'message'
    },
    components: {
      mycon:cpm  
    }
  })
Copy the code

In the JAVASCRIPT code, we customize two of our own parameters via the props property. And our parent component uses a Vue instance.

Look again at use:

  <div id="app">
    <mycon :cmovies='movies' :cmessages='messages'></mycon>
  </div>
  <template id="cpm">
     <div>
      <ul>
        <li v-for='item in cmovies'>{{item}}</li>
      </ul>
    </div>
  </template>
Copy the code

The value of the Vue instance (parent component) is then passed to the value of the props property via v-bind. The prop property in the component now has a value.

Manual line — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — –

In addition to using arrays in props, we can also assign to objects. And it gives you more flexibility in validating its data, setting defaults, and so on. This is also a situation that is often used in development.

Examples are as follows:

props:{
      cmovies: {type:Array.default: ['no value'].required:true
      },
      cmessages: {type:String.default:'ha ha',}}Copy the code

4.2 the father

The usage scenarios of the father is also a lot of, I simulate a scene, if we do a mall category pages now, but our data request operation is still in the top of the parent component, when the user clicks on a particular option, the child components we need to give yourself to the parent component of the index in order to ask the parent component for which the data.

The implementation here actually uses this.$emit(‘ event name ‘, content) on the child component to emit a custom event to the parent component, which the parent receives via V-ON and then handles with the method:

The code implementation is as follows:

  <template id="cpm">
    <div>
      <button v-for='item in categories' @click='btnclick(item)'>{{item.name}}</button>
    </div>
  </template>
Copy the code

Set of code

var cpm = {
    template: '#cpm'.data() {
      return {
        categories: [{id: "aaa".name: 'hot' },
          { id: "bbb".name: 'mobile phone' },
          { id: "ccc".name: 'electronics'}}},],methods: {
      btnclick(item){
        this.$emit('btnclick',item)
      }
    },
  }
Copy the code

The above code is where we fire events to the parent component.

 <div id="app">
    <mycon @btnclick='requestbuttonevent'></mycon>
  </div>
Copy the code

You then use the component to define a custom event within the scope of the parent component.

new Vue({
    el: '#app'.components: {
      mycon: cpm
    },
    methods: {
      requestbuttonevent(e){
        console.log('Parent component methods',e); }}})Copy the code

The parent component instance can receive the data from our child component, e in the code, and we can proceed with our subsequent requests and other operations.

5. Slot

Slots exist because we might have a few different little functions in a component, and then we can use those little functions as slots

5.1 Common Use

Define a slot in template

  <template id="cpn">
    <div>
      <h2>Title 2</h2>
      <slot></slot>
    </div>
  </template>
Copy the code

Use:

 <div id="app">
    <mycpn></mycpn>
    <mycpn>
      <button>slot</button>
    </mycpn>
    <mycpn></mycpn>
  </div>
Copy the code

In addition, we can set a default value for it, and then display the default value if it is imported directly into the slot. If it does not need to be overridden, it can be overridden when using it.

5.2 Use of named slots

What is a named slot, is to give a name value to the slot, and then we can identify our slot when we use it, avoid some reuse errors and so on.

Let’s look at an example, requirement: We now have a component with three slots and each with default values, how do I change one of them when I use it?

Component code:

  <template id="cpn">
    <div>
      <slot name='left'><span>On the left</span></slot>
      <slot name='middle'><span>In the</span></slot>
      <slot name='right'><span>right</span></slot>
    </div>
  </template>
Copy the code

Replace middle with Button:

  <div id="app">
    <mycpn><button slot="middle">search</button></mycpn>
  </div>
Copy the code

5.3 Scope slot

Before we look at scope slots we must understand one thing:

Everything in the parent template will be compiled in the parent scope, and everything in the child template will be compiled in the child scope

That is, under normal circumstances, the parent cannot access the child’s data, so when we use slots there are specific actions that require the parent to use the child’s data.

Usage scenario: The scope slot can be used when the slot has handled the business for us, but when we want to use the slot again but want to do different things to the business based on the original data

In a nutshell: The parent component reprocesses the business in the slot, but the data is provided by the child component

We examine the following code:

  new Vue({
    el:'#app'.components: {mycpn: {template:'#cpn'.data() {
          return {
            language: ['a'.'b'.'c'.'d'.'e']}},}}})Copy the code

The component myCPN is defined in the Vue instance, which acts as the parent component.

<template id="cpn">
    <div>
      <slot :nba='language'>
        <ul>
          <li v-for='item in language'>{{item}}</li>
        </ul>
      </slot>
    </div>
  </template>
Copy the code

Define the template and bind a custom property to the slot for the data we want to expose.

<div id="app">
    <mycpn></mycpn>
    <mycpn>
      <template slot-scope="slot">
        <span>{{slot.nba.join('-')}}</span>
      </template>
    </mycpn>
  </div>
Copy the code

Accept the value of the slot attribute using the slot-scope=”slot” fixed format, and then use slot directly. Data manipulation