1. Vue component lifecycle diagram

2. Component lifecycle functions

  • An empty instance object has just been initialized with default lifecycle functions and default events, but nothing else has been created.
  • If you want to call methods in methods or manipulate data in data, you can only do so in an Created lifecycle function at first
// 1. Instance creation phase
new Vue({
    el: "#app".// In beforeCreate, the data in data and methods are not initialized yet
    beforeCreate () {}, 	// Indicates that this function is executed before the instance is fully created
    // In Created,data and methods are already initialized
    created () {} 				// indicates that this function is executed after the instance is created
  
})

// Note: Look at the Vue life cycle legend, which shows that Vue starts compiling the template, executes the instructions in Vue code, and finally generates a compiled final template string in memory. It then renders the string into the DOM in memory. At this point, the template is only rendered in memory. The template is not mounted to a real page.

Copy the code
// 2. Runtime: Components mount and update

new Vue({
    el: "#app".// In beforeMounted execution, the elements in the page are not actually replaced, just some template strings that were written before
    beforeMounted () {}, 	// The template is compiled before the component is mounted, but not yet rendered to the page
    
    // Indicates that the template has been compiled, the template in memory has actually been rendered to the page, and the rendered page can be seen
    // Mounted is the last life-cycle function created during instance creation.
    // The instance has been fully created, and if nothing else is done, the instance is still in memory
    // Note: If you want to use plug-ins to manipulate a DOM node on a page, you need to do so in the mounted life cycle
    mounted () {} 				// After the component is mounted
    
    // This is the component creation phase, followed by the component execution phase
    // At the time of execution of this lifecycle function, the data displayed in the page is still old, but the data in data is up to date,
    // The page has not been synchronized with the latest data
    beforeUpdate () {} 		// Indicates that the current interface has not been updated, and the data must be updated
    // View the Vue life cycle legend, which means that the latest DOM tree is re-rendered in memory based on the latest data in data
    // The latest in-memory DOM tree is re-rendered to the real page after the update. This completes the data from the data(model layer).
    // Updates to the view layer
    updated () {} 				// Indicates that the current page is in sync with the data and is up to date
})
Copy the code
// 3. Component destruction phase
new Vue({
    el: "#app".// When the lifecycle function is executed. All data and methods, filters, instructions, and so on are available on the instance, and no destruction has actually been performed
    beforeDestroy () {}, 	// Indicates that the component is about to be destroyed when the Vue instance and data instruction etc. are still available
  	// By the time the lifecycle function is executed, data and methods, filters, directives, etc. in the component are no longer available
    destroyed(){} 				// Indicates that the component has been completely destroyed, and the component data is no longer available
})
Copy the code

The lifecycle functions activated and deactivated are available only when the component instance is keep-alive. When kePP-alive is wrapped, the route component is switched. When the file is switched to the wrapped component, the wrapped component invokes activated everywhere in the active state. When another component is switched to another component, the wrapped component invokes deactivated in the active state.

3. Global and local components

3.1 Global Components

  • Global components: Global components are defined outside the new Vue constructor and can be used in other Vue instances.

  • Note: When using Vue.com Ponent to define global components, the component name is hump. When referencing components, change the capital hump to lowercase letters and use a – connection between two words

<! ---->
<body>
  <! -- All vue instances can be accessed within the scope specified by el -->
  <div id="app">
    <button-counter></button-counter>
  </div>
  <div id="ppa">
    <button-counter></button-counter>
  </div>
  <! This is not accessible because components created by Component must be used within the element specified by vue instance EL.
  <! -- Vue.component named buttonCounter, in reference to the need to write button-counter; It is best to use all lowercase - link ->
  <button-counter></button-counter>
  <script>
    Vue.component("buttonCounter", {
      data: () = > {
        return {
          count: 0}; },template:
      '<button v-on:click="count++">You clicked me {{ count }} times.</button>'});var vm1 = new Vue({
      el: "#app"});var vm2 = new Vue({
      el: "#ppa"});</script>
</body>
Copy the code

3.2 Local components

  • Local components: mounted directly to the vue instance in the constructorcomponentsAttributes; Components is an object that accepts a set of custom local components
<body>
  <div id="app">
    <local-counter></local-counter>
  </div>
  <! Because local-counter is a local component, it can only be used within the EL scope of vm1 instances -->
  <div id="ppa">
    <local-counter></local-counter>
  </div>
  <script>
    // local-counter is a custom local component name that corresponds to an object that is its construction option
    var vm1 = new Vue({
      el: "#app".components: {
        "local-counter": {
          template:
          '<button v-on:click="count++">You clicked me {{ count }} times.</button>'.data: function () {
            return {
              count: 0}; }},}});var vm2 = new Vue({
      el: "#ppa"});</script>
</body>
Copy the code

4. Parent and child components

  • The essence of parent-child component relationships: as long as one component is in the other component’s template or in the instance’s EL binding tag.
<! -- Parent-child component relationship -->
<body>
    <! -- div#app is a template for the parent component -->
    <div id="app">
        <cpn></cpn>
    </div>
    <script>
        // The CPN template is the child CPN template, and the CPN component is replaced by the entire CPN template content during rendering
        Vue.component('cpn', {
            template: '
       

I am a child component

'
,})var vm = new Vue({ el: '#app'.data() { return { messageInfo: 'I'm message from the parent component'}}})
</script> </body> <! --> < span style = "max-width: 100%; <div id="app"> <cpn1></cpn1> </div> <script>Vue.component('cpn1', {template: '); Vue.component('cpn1', {template: '); Vue.component('cpn1', {template: ')<div> <h1>I'm CPn1 heading 1</h1> <cpn2></cpn2> </div>`, }) Vue.component('cpn2', { template: `<div> <h1>I'm CPn2 heading 2</h1> </div>`, }) var vm = new Vue({ el: '#app', }) </script> Copy the code
// 
<div id="app">
  <cpn1></cpn1>
</div>
<script>
  var cpnConstructor = Vue.extend({
    template: '

I am CPn2 heading 2

'
}) // var cpn2 = { // template: '

I'm cpn2 heading 2

'
// }; Vue.component('cpn1', { template: '
< H1 > I am CPn1 title 1 < cpn2>
'
.components: { cpn2: cpnConstructor // We can place extend constructors or cpn2 option objects}})var vm = new Vue({ el: '#app',})
</script> Copy the code

5. Parent and child component communication

  • backgroundAlthough the child component is nested in the template of the parent component, the child component cannot access the data of the parent component, and the parent component cannot access the data of the child component. So parent-child data interaction needs to communicate.
  • The most common application is when component A uses component B in its template. Of course, they need to communicate with each other: a parent component might want to send data to a child component, which might want to inform the parent about what’s happening inside it.
  • Pay attention to:
1.Prop is unidirectional: when a property of the parent component changes, it passes to the child component, but not vice versa. This is to prevent the child from inadvertently changing the parent's state, because for a value of the reference type passed, that is, a prop receives an object or an array, then the parent points to the same block of memory, and internal changes in the child affect the parent.2.If a prop needs to be modified by a sub-component, a copy of the prop can be made within the sub-componentCopy the code

5.1 Parent component passes to child component

  • Parent component to child component: passpropsProperties andvm.$attrsattribute
  • Naming summary: HTML features are case insensitive. So, camelCase prop needs to be converted to its counterpart when using a template other than a stringXXX - CCC (short line separated naming); Use hump in JS and dash in HTML
// Example 1: statically use props, statically pass vue, note that property separators cannot be camel case<div id="app">
  <cpn1 my-message="vue"></cpn1>
</div>
<script>
  Vue.component('cpn1', {
    / / declare the props
    props: ['myMessage'].// Just like data, the props data can also be used in templates,
    // It can also be used in vm instances through this.myMessage
    template: '<h1>hello {{myMessage}}</h1>',})var vm = new Vue({
    el: '#app',})</script>

// hello vue
Copy the code
// The parent component of dynamic props passes data to the child component<body>
    <div id="app">
        <! MyCpn/myCpn/myCpn/myCpn/myCpn/myCpn/myCpn/myCpn/myCpn/myCpn
      	<! Cpn-list ="list" --> cpn-bind :cpn-list="list" -->
      	<! Cpn-list is an attribute defined in the props of the child component, which is used to receive the list passed by the parent component.
        <my-cpn :cpn-list="list" :cpn-pers-info="persInfo"></my-cpn>
    </div>
    <script>
        Vue.component('myCpn', {
            // In the template of the child component, use the properties in the child component props
            template: ` < div > < h1 > I am a child component myCpn < / h1 > < h1 > receives the data: {{cpnList}} < / h1 > < h1 > receives the data: {{cpnPersInfo}} < / h1 > < / div > `.props: ['cpnList'.'cpnPersInfo']});var vm = new Vue({
            el: "#app".data() {
                return {
                    list: ['digital'.'goods'.'travel'].persInfo: {
                        name: 'Bob'.age: 20}}}});</script>
</body>
Copy the code

5.2 Child component passes to parent component

  • Child components pass data to parent components through custom events
<body>
  	<! -- Subcomponent template -->
    <template id="son">
        <div>
          	<! -- 1. The child component triggers the event function by clicking on the event -->
            <button v-for="item of categories" @click="btnClick(item)">{{item.name}}</button>
        </div>
    </template>
  
  	<! Parent component template -->
    <div id="app">
      	<! The parent component listens for the child component's custom event item-click. Note that the function for the custom event does not have an event object, but it will pass the child component's data item by default.
        <cpn-button @item-click="cpnClick"></cpn-button>
    </div>
  
    <script>
      	/ / child component
        Vue.component('cpnButton', {
            data() {
                return {
                    categories: [{id: '1'.name: 'goods' },
                        { id: '2'.name: 'technology' },
                        { id: '3'.name: 'outdoor'},]}},template: '#son'.methods: {
                btnClick(item) {
                 		// 2. The child component will emit a custom event via this.$emit(custom event name, passed to the parent component). Custom event names should be delimited with a lowercase dash
                    this.$emit('item-click', item)
                }
            }
        })

      	// Parent component instance
        new Vue({
            el: '#app'.methods: {
              	// 4. The custom event function listened by the parent component receives the item data passed by the child component
                cpnClick(item) {
                    console.log("-", item)
                }
            }
        })
    </script>
</body>
Copy the code

6. Access to parent and child components

6.1 The Parent Accesses the Child

  • Two access modesThrough:
    c h i l d r e n or Children or
    refs
1. this.$children: is an array containing all child component objects2. this.$refs: Default is` ` {}, when the ref attribute is bound to a child component,thisThe.$refs structure becomes'{bound ref property: corresponding subcomponent}'
Copy the code
<! -- this.$children example -->
<body>
  <div id="app">
      <cpn></cpn>
      <button @click="btn">button</button>
  </div>
  <template id="cpn">
      <div>
          <h1>{{message}}</h1>
      </div>
  </template>
  <script>
      var vm = new Vue({
          el: "#app".data: {
              message: "I'm the parent app.",},methods: {
              btn() {
                  console.log(this.$children[0].message)
                  this.$children[0].show(); }},components: {
              cpn: {
                  template: '#cpn'.data() {
                      return {
                          message: "I am a child component CPN",}},methods: {
                      show() {
                          console.log(this.message); }}}}});</script>
</body>
Copy the code
<! -- this.$refs Example: -->
<body>
    <div id="app">
        <cpn ref="cpnA"></cpn>
        <cpn ref="cpnB"></cpn>
        <button @click="showSon">button</button>
    </div>
    <template id="cpn">
        <div>
            <h1>{{message}}</h1>
        </div>
    </template>
    <script>
        var vm = new Vue({
            el: "#app".data() {
                return{}},methods: {
                showSon() {
                    console.log(this.$refs)
                    console.log(this.$refs.cpnA)
                    console.log(this.$refs.cpnB)
                }
            },
            components: {
                cpn: {
                    template: '#cpn'.data() {
                        return {
                            message: "I am a child component CPN",}},methods: {
                        show() {
                            console.log(this.message); }}}}});</script>
</body>
Copy the code

6.2 Child Accessing Parent

  • this.$parentThe parent component can be accessed, but this is not recommended, which will damage the reusability of the child component. For example, modify the name property of the parent component A in the child component, but other components of B reference the child component, and component B does not have the name property. There is no decoupling
  • this.$root: accesses the root instance directly

7 Dynamic Components

  • *** Dynamic component definition: by using vUE built-in<component>Element and use itisFeature dynamic binding, you can dynamically switch between multiple components at the same mount point
  • Use vUE built-in<component>Element + bind special attributeisTo complete the dynamic component
<! Basic usage -->
<! When the user clicks on the Home button, the home component will be rendered in the lower component position. Clicking on the Posts button will render the posts component below.
<body>
    <div id='app'>
        <div>
            <! CurrentTab = TAB; currentTabComponent;
            <button v-for="tab in tabs" @click="currentTab = tab">
                {{ tab }}
            </button>
            <! Component is used to render different components based on changes in the currentTabComponent. The rendered component completely replaces the built-in component.
            <component :is="currentTabComponent"></component>
        </div>
    </div>

    <script>
        Vue.component("home", {
            template: "<div>Home component</div>"
        });
        Vue.component("posts", {
            template: "<div>Posts component</div>"
        });
        new Vue({
            el: "#app".data: {
                currentTab: "Home".tabs: ["Home"."Posts"]},computed: {
                currentTabComponent: function () {
                    return this.currentTab.toLowerCase(); }}});</script>
</body>
Copy the code

When switching between these components, you sometimes want to keep the state of the previous components to avoid performance issues caused by repeated rerendering. To solve this problem, we can wrap its dynamic components with a

element.

<! Deactivated components will be cached, the next rendering will not recreate the component instance, and the previous state of the component will be cached! -->
<keep-alive>
  <component v-bind:is="currentTabComponent"></component>
</keep-alive>
Copy the code

8 Asynchronous Components

Segmentfault.com/a/119000002…