Detailed explanation and in-depth application of vue component development - Part 1 (recommended intensive reading)

    The Vue 2.0 series is based on component development. This part is divided into two parts. The first part is mainly about concepts, global components and local components, the application of components in modularization, and parent-child component communication. The next part is non-parent-child component communication, the use of component slots, dynamic components and handling of component boundary conditions. Please read patiently, I believe it will give you a deeper understanding and better application of component-based development.

    Detailed explanation and in-depth application of vue component development - Part 2: Part 2 address

    All codes in this article have been uploaded to GitHub: A-sketch123 -VueComponent-eng

    1. Concept

    Component development is to split the page into reusable components as much as possible, so that our code is more convenient to organize and manage during class, and the scalability is also stronger.

    We can use this component as a custom element in a Vue root instance created by new Vue. If the component is not mounted under the instance of new Vue, it will not be rendered


    2. Global components and local components

    Global components:
    Components created with Vue.component(component name, {method}) are globally registered, which means they can be used in any newly created Vue root instance (new Vue) template after registration
    The globally registered behavior must happen before the root Vue instance (via new Vue ) is created

    Partial components:
    Use the components attribute under new Vue, which can only be used under the mounted new Vue instance

      <body>
        <div id="app">
          <global-cpn></global-cpn>
          <local-cpn></local-cpn>
        </div>
    
        <h2>I split two Vue instances</h2>
    
        <div id="app2">
          <global-cpn></global-cpn>
          <local-cpn></local-cpn>
        </div>
    
    <!-- Define the template for the global component -->
        <template id="globalCpn">
          <div>
            <p>I am a global component, which can be used under multiple Vue instances</p>
          </div>
        </template>
        <script>
          // 1. Register a global component, note that the global component must be defined before the vue instance is created, otherwise it cannot be displayed and an error will be reported
          Vue. component('global-cpn', {
            template: '#globalCpn',
          });
          //Define the template of the local component in the variable to make the code more tidy and standardized
      var localCpn = {
            template:`
       <div>
            <p>I am a local component, which can only be used under the mounted new Vue instance</p>
        </div>
      ` };
    
          const app = new Vue({
            el: '#app',
            //Register local components under app
            components: {
              'local-cpn': localCpn,
            },
          });
          const app2 = new Vue({
            el: '#app2',
          });
        </script>
      </body>
    

    The effect is as follows: local components cannot be rendered under the app2 instance

    The reason why the data of the component must be a function

    A component's data option must be a function, so each instance can maintain an independent copy of the returned object

    The data attribute must be a function, and this function returns an object, which holds the data inside. In this way, each component instance has its own scope, and different components can be independent of each other and will not affect each other
    If the data of the component is an object, when multiple components share a data source, all component data will change accordingly when one data changes, so the function return should be used to return a copy of the object, so that each instance has its own role area.

    data(){
        return{
            count:0
        }
    },
    

    template template error problem

    In the template template, all html needs to be wrapped into an element (div), otherwise the following error may be reported

    <template id="cpn">
       <div>I am a child component</div>
       <input type="text">
    </template>
    

    Correct should be:

    <template id="cpn">
       <div>
       I am child component
       <input type="text">
       </div>
    </template>
    


    3. Using components in the module system

    In the vue-cli project, a components file is usually built to store components

    <script>
    //Import the file where the component is located
    import Footer from "./components/Footer.vue";
    
    export default {
       components: {
         Footer,
       },
    };
    </script>
    


    4. Parent-child components

    Component communication - father to son

    Props are used to pass from parent to child, and child components use props attribute to receive data from parent components, and parent components use v-bind (:) to dynamically pass data to child components
    The value of props has two ways:
    Method 1: string array, the string in the array is the name when passing
    Method 2: object, the value of props can be set in the form of an object, such as default value, type and other attributes

    The case of props:
    Attribute names in HTML are case-insensitive, which means that when you use templates in DOM, camelCase (camel case) prop names need to use their equivalent kebab-case (dash-separated names) Naming: (this rule also applies to component naming, components named in camel case must also be connected with dashes when used in HTML)

    Use an array of strings:

        <div id="demo">
           <son-cpn :father-title="title"></son-cpn>
        </div>
    
        <script>
           var sonCpn = {
             template: ` <h4>{{fatherTitle}}</h4> `,
             //props uses an array of strings
             props: ['fatherTitle'],
           };
           const demo = new Vue({
             el: '#demo',
             data: {
               title: 'I am the value passed from the parent component to the child component',
             },
             components: {
               'son-cpn': sonCpn,
             },
           });
        </script>
    

    use object form:

    <div id="demo">
       <son-cpn :names="name"></son-cpn>
    </div>
    
    <template id="cpn">
       <div>
         <h4>{{mes}}</h4>
         <ul>
           <li v-for="item in names">{{item}}</li>
         </ul>
       </div>
    </template>
    <script>
       // props use object mode
       var sonCpn = {
         template: '#cpn',
         props: {
           mes: {
             type: String,
             default: 'No value is passed to me, I am the default value',
           },
           names: {
             type: Array,
             //// When the type is an object or an array, the default value must be a function
             default() {
               return ['Zhang San', 'Li Si', 'F'];
             },
             //Required value
             required: true,
           },
         },
       };
       const demo = new Vue({
         el: '#demo',
         data: {
           name: ['A', 'B', 'C'],
         },
         components: {
           'son-cpn': sonCpn,
         },
       });
    </script>
    

    The running result mes is the default value, and names is the value passed from the parent component

    Component communication - child to father

    Child components pass values to parent components using custom events:
    In the child component, the event is triggered by $emit()
    In the parent component, listen to the child component event through v-on

    this.$emit('event name') cannot use camel case (with case), because the v-on event listener will be automatically converted to all lowercase in the DOM template (because HTML is case Insensitive), such as v-on:myEvent will become v-on:myevent - making myEvent impossible to be monitored, because the name of the event that is triggered needs to exactly match the name used to listen to this event Therefore, we recommend that you always use kebab-case event names

    <div id="demo">
         <!-- Parent component listens to custom events -->
         <son-cpn @btn-click = 'sonclick'></son-cpn>
         <h4>Clicks: {{total}}</h4>
    </div>
    <script src="../js/vue.js"></script>
    <script>
         var cpn = {
             template:` <button @click="btnClick()">+</button> `,
             data(){
                 return {
                     count :0
                 }
             },
             methods: {
                 btnClick(){
                     this.count++
                     //Subcomponents send custom events
                     this. $emit('btn-click', this. count )
                 }
             }
    
         }
         const demo = new Vue({
             el:'#demo',
             data:{
                 total: 0
             },
             components: {
                 'son-cpn': cpn
             },
             methods: {
                 sonclick(count){
                     this.total = count
                 }
             },
         })
    </script>
    


    Access method of parent-child components: $refs

    If you want to directly access a specific component, you can use $refs
    Use of $refs: $refs and ref directives are usually used together

    First, bind a specific ID number to a subcomponent through ref
    Second, through this.$refs.ID, you can access the bound specific component

    <div id="app">
           <cpn ref="child1"></cpn>
           <cpn ref="child2"></cpn>
           <button @click="btnClick">Access subcomponents through res</button>
         </div>
         <script src="../js/vue.js"></script>
         <script>
           const app = new Vue({
             el: '#app',
             methods: {
               btnClick() {
                 //Access the data of the child component through ref
                 console.log(this.$refs.child1.name);
                 //The parent component implements by calling the method of the child component so that the parent component can focus on the input box in the child component
                 this.$refs.child2.sonfocus();
               },
             },
             components: {
               cpn: {
                 template:`
             <div>I am a child component
             <input ref="ipt">
             </div>`,
                 data() {
                   return {
                     name: 'I am the name of subcomponent child1',
                   };
                 },
                 methods: {
                   sonfocus() {
                     // Subcomponents can also use ref to access specified elements inside themselves
                     this.$refs.ipt.focus();
                   },
                 },
               },
             },
           });
         </script>
    

    Before clicking:

    After clicking:

    $refs will only take effect after the component renders, and they are not reactive. This is only intended as an "escape hatch" for directly manipulating child components ——you should avoid accessing $refs in templates or computed properties

    In addition, the parent component can also use $children to access the child component, which returns an array type that contains all child component objects. Note that $children does not guarantee order, nor is it reactive.
    Direct access to parent components in subcomponents can be done through $parent (official documents strongly recommend this method) These two methods are rarely used, and will not be applied here


    References

    Component Basics - Vue.js

    Deep Dive into Components - Vue.js

    Popular posts from this blog

    大学资料分享——广工计院各个科目实验报告、课设及期末复习资料!!

    Win10 远程计算机或设备将不接受连接

    JAVA Traffic Signal Light Course Design (Source Code + Report + Video Demonstration)