Reusability component details

1. Reasons for using components

Purpose: Improve code reuse

2. How to use components

  1. Global registration

    Vue.component('my-component', {template:'
            
    I am the content of the component
    '
    }) Advantages: All NUE instances can be used. Disadvantages: Too much permission, low fault toleranceCopy the code
  2. Global registration

    let app = new Vue({
      el: "#app".components: {
        "my-component": {
          template: "
            
    I am the content of the component
    "
    ,}}});Copy the code

Note:

Templates for VUE components are limited by HTML tags in some cases,

For example, a table can only contain < TD > elements, so using components directly in the table is not effective. In this case, components can be mounted using the IS attribute

<table>
	<tbody is="my-component">
	</tbody>
</table>
Copy the code

3. Weird techniques used by components

  1. It is recommended to use lowercase plus (must) child, my-Componnet to name components
  2. The contents of the template must be included in a DOM element, and can be nested
  3. In the definition of the component, options other than template – data,computed,methods
  4. Data must be a method

4. Using props to pass data The father passes data to his son

  1. Use props in the component to receive parameters from the parent component,

    Note: Properties defined in props can be used directly in components

  2. Propps comes from the parent, and data return in the component is the component's own data. In both cases, the scope is the component itself, which can be used directly in template, computed, and Methods

  3. There are two types of props, one is an array of strings, and the other is an object. In this section, we will focus on arrays

  4. You can use vbind to dynamically bind content from the parent component

5. One-way data flow

explain

Passing data through props is a one-way flow, that is, when the parent component changes, it is passed to the child component, but not the other way around.

purpose

The parent component is decoupled as much as possible to prevent the child component from inadvertently modifying the state of the parent component.

Application scenarios

There are two common situations in business that require prop changes

In one case, the parent component passes in an initial value, and the child component stores it as an initial value, which can be used and modified at will in its own scope.

In this case, you can declare another data inside the component data, referencing the parent component’s prop

Step 1: Register components

Step 2: Pass in the parent component’s data and receive it in the child component using props

Step 3: Store the data passed in with the initial value, that is, set up a variable to give it the value

<div id="app">
	<my-comp init-count="666"></my-comp>
</div>
<script>
var app = new Vue({
  el: "#app".components: {
    "my-comp": {
      props: ["init-count"].template: "<div>{{init-count}}</div>".data: function () {
        return {
          count: this.initCount, }; }},}});</script>
Copy the code

In another case, prop is passed in as a raw value that needs to be transformed.

In this case, you can calculate the properties

Step 1: Register components

Step 2: Pass in the parent component’s data and receive it in the child component using props

Step 3: Recalculate the data passed in through the calculation properties

<div id="app">
   <inputtype="text" v-model="width">
    <my-comp :width="width"></my-comp>
  </div>


let app = new Vue({
  el:'#app'.data: {width:' ' 
  },
  components: {'my-comp': {props: ['width'].template:'<div :style="style">{{init-count}}</div>'.computed: {style:function () {
            return{
              width:this.width+'px'.background:'red'}}}}}})Copy the code

Data validation

CamelCased and Kebabcase in vue components

@ In HTML, myMessage and myMessage are identical,

Therefore, you must use kebabCase (dash) naming when using HTML in a component.

Hump !!!!!! is not allowed in HTML

@ In a component, the parent must use a dash to pass data to the child.

In template, you must use the camel’s name, if you name a dash, it will be an error.

@ in a component’s data, references to this.XXX can only be humped. An error is reported if a dash is named.

Conclusion: Use humps except in HTML.

type

  • String
  • Number
  • Boolean
  • Object
  • Array
  • Function
Vue.component ('my-compopent', {props: {/ / Must be a numeric typepropA : Number, / / must be a string or number typepropB : [String , Number], / / Boolean, default if not definedtrue
    propC: {
    type : Boolean ,
    default : true}, / / number, and must passpropD: {
    type: Number ,
    required : true}, / / If it is an array or object, the default value must be a function to returnpropE: {
      type : Array ,
      default : function () {
        return[]; }}, / / a custom validation functionpropF: {
        validator : function (value) {
        return value > 10; }}}})Copy the code

7. Component communication

Component relationship can be divided into father-child component communication, sibling component communication and cross-level component communication

1. Custom events – Child component passes data to parent component

In addition to monitoring DOM events, v-On can also be used for custom events between components.

JavaScript design pattern-observer, dispatchEvent and addEventListener.

The Vue component has a similar pattern. The child uses emit () to emit events, the parent uses emit () to emit events, the parent uses emit () to emit events, and the parent uses on () to monitor the child’s events.

Direct dump code

Step 1: Customize events

Step 2: Fire the event from the child component with $emit. The first parameter is the event name, followed by the data to be passed

Step 3: Accept the custom event with a parameter

<template> <div id="app"> <p> Hello, your current bank balance is {{total}} yuan </p> <btn-compnent @change="handleTotal"></btn-compnent>{{myString  }} </div> </template> <script> export default { name: "App", components: { "btn-compnent": { template: '<div>\ <button @click="handleincrease">+1</button> \ <button @click="handlereduce">-1</button>\ </div>', data: Function () {return (count: 0, myString1: 0, myString2: 0, myString2: 0); }, methods: { handleincrease: function () { this.count += 1; this.$emit("change", this.count, this.myString1); }, handlereduce: function () { this.count--; this.$emit("change", this.count, this.myString2); }, }, }, }, data() { return { total: 0, myString: "", }; }, methods: { handleTotal: function (total, string) { this.total = total; this.myString = string; ,}}}; </script> <style> </style>Copy the code

2. Use vmode in components

$emit code. This line of code will actually fire an input event and the parameter after ‘input’ is the value of the property passed to the VModel binding

The vModel is actually a syntactic sugar that does two things behind it

  • V-bind binds a value attribute
  • The V-on directive binds the input event to the current element

To use vModel, do:

  • Receive a value attribute.
  • The input event is raised when a new value is present
<div id="app">
	<p>Hello, your current bank balance is {{total}} yuan</p>
	<btn-compnent v-model="total"></btn-compnent>
</div>

<script>
        var app = new Vue({
  el: "#app".data: {
    total: 0
  },
  components: {
    "btn-compnent": {
      template:
        '
      
\ \ \
'
.data: function () { return { count: 0 }; }, methods: { handleincrease: function () { this.count++; -------- Pay attention. On this line, the emit is the input event ---------this.$emit("input".this.count); }, handlereduce: function () { this.count--; this.$emit("input".this.count); }}}},methods: { /* handleTotal:function (total) { this.total = total; } * /}}); </sciprt>Copy the code

3. Communication between non-parent components

Sometimes two components also need to communicate (not parent-child).

In simple scenarios, an empty Vue instance can be used as the central time bus

Design instances

 <div id="app" >
	<my-acomponent></my-acomponent>
	<my-bcomponent></my-bcomponent>
</div>

 components: {
    "my-acomponent": {
      template:
        
      
< button@click ="handle">
.data: function () { return { aaa: "I'm content from component A"}; },methods: { handle: function () { this.$root.bus.$emit("lala".this.aaa); }},},"my-bcomponent": { template: "<div></div>".created: function () { // The A component listens for the lala event when the instance is created this.$root.bus.$on("lala".function (value) { alert(value); }); }},},Copy the code

The parent chain: this. $parent

Vue.component("child-component", {
  template: .methods: {
    setFatherData: function () {
      this.$parent.msg = "The data has been revised."; }}});Copy the code

A chain: this. $refs

Provides a way to index a child component by adding an index to it with the special attribute ref

let app = new Vue({
  el: "#app".data: {
    / / bus mediation
    bus: new Vue(),
    msg: "The data has not been revised.".formchild: "Not yet."
  },
  methods: {
    getChildData: function () {
      // Use to fetch the contents of the child component ---- $refs
      this.formchild = this.$refs.c.msg; }}});Copy the code

4. Use slot to distribute content

1. What is a slot

In order for components to be composable, we need a way to mix the content of the parent component with the child component’s own template.

This process is called content distribution, and vue.js implements a content distribution API,

Use the special ‘slot’ element as the slot for the original content.

2. Scope for compilation

Before diving into the content distribution API, let’s clarify in which scope the content is compiled. Assume the template is:

<child-component>
	{{ message }}
</child-component>
Copy the code

Should Message be bound to the parent component’s data or to the child component’s data?

The answer is the parent component.

Component scope is simply:

The contents of the parent component template are compiled in the parent component scope;

The content of the subcomponent template is compiled in the subcomponent scope.

3. Usage of slots

The content of the parent component is mixed with the child component to compensate for the view

Mix the content of the parent component with the child component’s own template

Single slot:
<div id="app">
  <my-component>
    <p>I am the content of the parent component</p>
  </my-component>
</div>;
Vue.component("my-component", {
  template:
    "
      
\ \ IF the parent component does not insert content, I will appear as default \ \
"
}); Copy the code
Named slot:
<name-component>
    <h3 slot="header">I am heading</h3>
    <p>I'm the body content</p>
    <p>There are two paragraphs in the body</p>
    <p slot="footer">I'm the bottom message</p>
</name-component>
Copy the code
Vue.component("name-component", {
  template:
    '
      
\
\n'
+ ' <slot name="header">\n' + " \n" + " </slot>\n" + "</div>\n" + '<div class="contatiner">\n' + " <slot>\n" + " \n" + " </slot>\n" + "</div>\n" + '<div class="footer">\n' + ' <slot name="footer">\n' + "\n" + " </slot> \n" + "</div>" + " </div>" }); Copy the code

4. Scope slot

A scoped slot is a special kind of slot,

Replace rendered elements with a reusable template

Get data from child components

The template template is not rendered

Vue.component("my-component", {
  template:
    '< div > \ < slot text = "I am data from the child components" ss = "FDJKFJLSD" name = "ABC" > \ < / slot > \ < / div >'
});

Copy the code

5. Accessslot

Through this. $slots. (NAME)
mounted:function () {
  // Access the slot
  let header = this.$slots.header;
  let text = header[0].elm.innerText;
  let html = header[0].elm.innerHTML;
  console.log(header)
  console.log(text)
  console.log(html)
}
Copy the code

5. Advanced usage of components – Dynamic components

VUE provides us with an element called Component

Used to dynamically mount different components

Implementation: implemented using is features