Vue _ Tutorial version 04 components

Posted by TexasMd91 on Fri, 29 Oct 2021 15:09:11 +0200

catalogue

1, Vue components

1.1 overview

1.2. Global registration

1.3 partial registration

1.4 value transfer between components

1.5 dynamic components

2, Component slot

2.1. Single slot

2.2 named slot

2.3. Scope slot

1, Vue components

1.1 overview

assembly   (Component) is one of the most powerful functions of Vue.js. It is a polymer of html, css, JS, etc.

 

1.2. Global registration

Vue.component ('component name ', {})   

The first parameter is the label name, and the second parameter is an option object.

After the global component is registered, any Vue instance can be used.

Component considerations:

  • structure   Most of the options passed in during Vue instance can be used in the component, with one exception: data    Must be a function, and this function requires an object to be returned (because the object is a reference type)
  • The component template must be a single root element
  • The content of a component template can be a template string

 

<div id="app">
<!-- After the global component is registered, it is called directly -->
<hello></hello>
</div>
<script>
// Global component registration - defined once, available globally
// In vue2.x, it is recommended that our components use lowercase (the initial letters are not case sensitive)
// The component is a small hump name, username = > converted to lowercase = > user name
// data must be a function that returns an object
// Vue.component('name ', {configuration})
let cmp = Vue.component('hello', {
  data() {
	return {
	  title: 'hello Global component'
	}
  },
  // Template (string template) / render (close to the native json object) = > Vue it is a virtual dom(json object)
  // The input parameter in render is the h variable by default. It is built and replaced. After replacement, it does not support jsx
  // template: `<div>{{ title }}</div>`
  render(h) {
	return h(
	  'div',
	  { attrs: { name: 'aaa' } },
	  [
		h('h3', {}, this.title),
		h('h3', {
		  on: {
			click: () => {
			  console.log('click22222', this.title)
			}
		  }
		}, '22222'),
		h('h3', {}, '3333'),
	  ])
  }
});
const vm = new Vue({
  el: '#app',
  data: {
  }
})
</script>

1.3 partial registration

Its Vue can only be registered at the current time   Used in an instance through a   Vue instance / component instance option components registers components that are only available in their scope

1.4 value transfer between components

1.4.1. Value transfer from parent component to child component

  • Parent component to   attribute   Bind values to child components in the form of
  • Subcomponents by using properties   props   Receive (props) is one-way bound (read-only property): when the property of the parent component   When changes occur, they will be transmitted to sub components, but not vice versa)

<div id="app">
<!-- The parent of the child component passes values to the child component through custom attributes -->
<child :age="age" :setagefn="setagefn"></child>
<!-- <child></child> -->
</div>

<script>
// assembly
const Child = {
  data() {
	return {
	  title: 'I am a local component'
	}
  },
  // props: one-way data flow. The modified data can only be modified through the parent component, and the child component is notified to update
  // props: defines the name and type of the attribute defined by the parent component to the child component
  // props object | array
  // The scheme of array is to use it for yourself
  // props: ['age'],
  // When encapsulating a common component, be sure to capitalize the object type
  props: {
	// age: Number
	age: {
	  type: Number,
	  // Multiple types = > union type
	  // type: [Number, String],
	  // This attribute must exist. true must be passed, and false can not be passed
	  // required: true,
	  // The default value is written directly for normal types, and callback functions are used for reference types
	  default: 10,
	  // Custom validator
	  validator: (v) => {
		if (v >= 160) {
		  return false
		}
		return true
	  }
	},
	user: {
	  type: Object,
	  /* default: () => {
		return { name: 'Zhang San '}
	  } */
	  // Returns an object
	  default: () => ({ name: 'Zhang San' })
	},
	setagefn: Function
  },
  mounted() {
	// Use the function passed in by the parent component to modify the data
	this.setagefn(101)
  },
  template: `<div>{{title}}  --- {{age}} -- {{user.name}}</div>`
}

// Root component
const vm = new Vue({
  el: '#app',
  data: {
	age: 100
  },
  // key is the tag name used in html and the value component object
  components: { child: Child },
  methods: {
	setagefn(arg) {
	  this.age = arg
	}
  }
})
</script>

  1.4.2 value transfer from child component to parent component

<div id="app">
<child :age="age" @onsetage="setage"></child>
</div>

<script>
// Subcomponents
const Child = {
  data() {
	return {
	  title: 'I am a local component'
	}
  },
  props: {
	age: Number
  },
  template: `<div @click="incr">{{title}}  --- {{age}}</div>`,
  methods: {
	incr() {
	  // props unidirectional data flow
	  // this.$emit('name of custom event ', [... Parameter])
	  // Add a custom event to the current component
	  this.$emit('onsetage', 10)
	}
  }
}
// Root component
const vm = new Vue({
  el: '#app',
  data: {
	age: 100
  },
  // key is the tag name used in html and the value component object
  components: { child: Child },
  methods: {
	setage(num) {
	  this.age += num
	}
  }
})
</script>

1.4.3 event bus  

Value transfer between non parent and child components or between components at more levels. Value transfer between components is managed through a separate event center in Vue.

  • Establish a unified event center

const bus = new Vue( ) 

  • The data party is passed and triggered by an event    bus.$emit(   Method name, passed data)
  • Receiving data party, in the life cycle function, through    bus.$on(   Method name, [params]  ) To monitor
  • Destruction event, at the data receiving party, through    Bus. $off (method name)    Unable to listen to data after destruction

1.4.4,Ref

ref is used to register reference information for elements or child components. Reference information will be registered in the parent component  $ refs object. If it is used on an ordinary DOM element, the reference points to the DOM element; if it is used on a child component, the reference points to the component instance

#On ordinary dom elements

<p ref="p">hello</p>

#On sub assembly

<child-comp ref="child"></child-comp>

#Call

this.$refs. Reference name

ref works in normal dom tags

  ref works on custom components

  

 8.4.5,parent / children / root

Gets a collection of parent or child component objects

<div id="app">
  <h3>new Vue -- {{msg}}</h3>
  <app></app>
</div>
<script>
  const Child = {
    data() {
      return {
        msg: ''
      }
    },
    mounted() {
      // Get the root component of the current component. The root component has only one new Vue
      // console.log(this.$root)
      this.$root.msg = 'I am child To modify your data'
      // Get an array
      // console.log(this.$root.$children)
      /* this.$root.$children.forEach(child => {
        if (child.msg) {
          child.msg = 'abc'
        }
      }) */
      // The son gets the father
      this.$parent.msg = 'Sub to modify'
    },
    template: `<div>
      <h3>I am Child</h3>
      </div>`
  }
  const App = {
    data() {
      return {
        msg: 'app'
      }
    },
    components: {
      Child
    },
    template: `<div>
      <h3>I am App -- {{msg}}</h3>
      <child></child>
      </div>`
  }

  // new Vue
  const vm = new Vue({
    el: '#app',
    data: {
      msg: ''
    },
    components: {
      App
    }
  })
</script>

1.4.6,provide / inject

Publishing and injection are generally used in component encapsulation

  

<div id="app">
  <h3>new Vue -- {{msg}}</h3>
  <app></app>
</div>

<script>
  const Child = {
    // Inject published data
    inject: ['username', 'fn'],
    data() {
      return {
        msg: ''
      }
    },
    mounted() {
      // console.log(this.fn)
      this.fn()
    },
    template: `<div>
      <h3>I am Child -- {{username}}</h3>
      </div>`
  }

  const App = {
    data() {
      return {
        msg: 'app'
      }
    },
    components: {
      Child
    },
    template: `<div>
      <h3>I am App -- {{msg}}</h3>
      <child></child>
      </div>`
  }

  // new Vue
  const vm = new Vue({
    el: '#app',
    // Publish a piece of data that is shared among the descendants
    /* provide: {
      username: 'Zhang San '
    }, */
    provide() {
      return {
        username: this.msg,
        fn: this.fn
      }
    },
    data: {
      msg: 'Li Si'
    },
    components: {
      App
    },
    methods: {
      fn() {
        console.log('fn')
      }
    }
  })
</script>

1.4.7, $attrs and $listeners

$attrs accepts all attributes that are not set through props

$listeners is an event that accepts custom events from all parent components to child components. You didn't send it through $emit

<div id="app">
  <h3>new Vue -- {{msg}}</h3>
  <app name='Zhang San' age='20' @fn="fn"></app>
</div>

<script>
  const Child = {
    // props: ['age'],
    data() {
      return {
        msg: ''
      }
    },
    mounted() {
      console.log(this.$attrs)
      // console.log(this.$listeners)
      // this.$listeners.fn('123')
    },
    template: `<div>
      <h3>I am Child</h3>
      </div>`
  }
  // App this component is equivalent to the Child component protective shell (high-order component -- high-order function)
  const App = {
    data() {
      return {
        msg: 'app',
        attrs: null
      }
    },
    created() {
      // Deep replication
      this.attrs = { ...this.$attrs }
      if (this.attrs.age >= 20) this.attrs.age = 'secrecy'
    },
    components: {
      Child
    },
    methods: {
      fn(value) {
        console.log(value)
      }
    },
    // < child name = 'Zhang San' age ='20 '@ FN = "FN" > < / child >
    // <child v-bind="$attrs"></child>
    template: `<div>
      <h3>I am App -- {{msg}}</h3>
      <child v-bind="attrs"></child>
      </div>`
  }

  // new Vue
  const vm = new Vue({
    el: '#app',
    data: {
      msg: 'Li Si'
    },
    components: { App },
  })
</script>

1.5 dynamic components

By using reserved  < The component > element is dynamically bound to its is feature, so that multiple components can use the same mount point and switch dynamically

<component v-bind:is="currentView"></component>

<script>

  var vm = new Vue({

    el: '#root',

    data: {

      currentView: 'home'

    },

    components: {

      home,

      posts

    }

  })

</script>

  • keep-alive

If you keep the switched component in memory, you can keep its state or avoid re rendering.

<keep-alive>

        <component :is="currentView"></component>

</keep-alive>

<script>

  var vm = new Vue({

    el: '#root',

    data: {

      currentView: 'posts'

    },

    components: {

      home,

      posts

    }

  })

</script>

<div id="app">
  <!-- <button @click="tab=true">child1</button>
  <button @click="tab=false">child2</button>
  <hr>
  <child1 v-if="tab"></child1>
  <child2 v-if="!tab"></child2> -->

  <button @click="cmp='child1'">child1</button>
  <button @click="cmp='child2'">child2</button>
  <hr>
  <!-- 
    keep-alive It can be used in [dynamic component] and [routing] to maintain the status of components(Cache current component)
    Specify the components that need to be cached include
    Specify components that do not need to be saved exclude   Choose one of the following two configurations
  -->
  <keep-alive :include="['child1']">
    <component :is="cmp"></component>
  </keep-alive>
</div>

<script>
  const Child1 = {
    name: 'child1',
    data() {
      return {
        username: ''
      }
    },
    created() {
      console.log('child1 - created')
    },
    // The life cycle of the two components used only when dynamic components are used and keep alive is used
    activated() { // The current dynamic component is activated
      console.log('activated')
    },
    deactivated(){
      console.log('deactivated')
    },
    template: `<div>
      <h3>I am Child1</h3>
      <input type="text" v-model="username" />
      </div>`
  }
  const Child2 = {
    name: 'child2',
    data() {
      return {
        username: ''
      }
    },
    created() {
      console.log('child2 - created')
    },
    template: `<div>
      <h3>I am Child2</h3>
      <input type="text" v-model="username" />
      </div>`
  }

  const vm = new Vue({
    el: '#app',
    data() {
      return {
        // tab: true
        cmp: 'child1'
      }
    },
    components: {
      child1: Child1,
      child2: Child2
    }
  })
</script>

  

2, Component slot

The biggest feature of components is reusability, and good use of slots can greatly improve the reusability of components

2.1. Single slot

When the child component template has only one slot without attributes, the entire content fragment passed in by the parent component will be inserted into the slot   DOM position and replace the slot label itself.

2.2 named slot

Sometimes we need multiple slots to complete the corresponding data custom display.

One without   The < slot > exit of name will have the implied name "default".

since   Updated since 2.6.0. Obsolete use slot s

# Subcomponents
<div class="container">
  <header> 
<slot name="header"></slot>
  </header>
  <main>
    <slot></slot>
  </main>
</div>

# Parent component
<app-layout>
    // Old writing
    <h1 slot="header">Here may be a page title</h1>
// neographism
// V-slots can only be added on < template >
// Abbreviation: V-slot: header = = #header
	<template v-slot:header>
    	<h1>Here may be a page title</h1>
 	</template>

  <p>A paragraph of the main content.</p>
</app-layout>

2.3. Scope slot

A scope slot is a special type of slot used as a   Reusable template (which can be passed data) to replace the rendered elements. In the sub component, just pass the data to the slot, just like you will   prop is passed to the component

<div id="app">
    <child :users='users'>
      <!-- 
        vue2.6 before
       -->
      <!-- <h6 slot="action" slot-scope="row" @click="pdel(row)">Delete it</h6> -->
      <!-- 
         vue2.6 after
        -->
      <!-- <template v-slot:action="row">
        <h3 @click="pdel(row)">delete</h3>
      </template> -->
      <template #action="row">
        <h3 @click="pdel(row)">delete</h3>
      </template>
    </child>
  </div>

  <script type="text/template" id="userhtml">
    <div>
      <table width="600" border="1">
        <tr>
          <th>ID</th>
          <th>full name</th>
          <th>operation</th>
        </tr>
        <tr v-for="(item,index) in users" :key="item.id">
          <td>{{item.id}}</td>
          <td>{{item.name}}</td>
          <td>
            <!-- adopt slot Data transmission, this slot Is a scope slot -->
            <slot name="action" :info="item">
              <button @click="del(index)">delete</button>
            </slot>
          </td>
        </tr>
      </table>
    </div>
  </script>
  <script>
    const child = {
      props: ['users'],
      name: 'child',
      template: '#userhtml',
      methods: {
        del(index) {
          console.log(index)
        }
      }
    }

    const vm = new Vue({
      el: '#app',
      data() {
        return {
          users: [
            { id: 1, name: 'Zhang San' },
            { id: 2, name: 'Li Si' },
            { id: 3, name: 'Wang Wu' },
          ]
        }
      },
      components: { child },
      methods: {
        pdel(row) {
          console.log(row.info)
        }
      }

    })
  </script>

Topics: Front-end Vue