Recursive components and dynamic components

Recursive components and dynamic components

Recursive components

Recursive component refers to the essential component to call their own in the template, open recursive component, is set in a component nameoptions. Such as the following example:

<template>
  <div>
    <my-component></my-component>
  </div>
</template>
<script>
  export default {
    name: 'my-component'
  }
</script>

Import Webpack in a Vue.js components, typically by import myComponent from 'xxx'this syntax, then the current component (page) is components: { myComponent }registered in the component. This component is not set mandatory namefields, the user name of the component are coming after import custom, but users recursive component is the component itself, it must know what this component is called, because there is no use componentsregistered, so the namefield It is a must. In addition to the components used recursively name, we in the previous section is also introduced, with some special way, to find the component instance by traversing the name option of matching components.

But then, the above example is problematic, if the direct running, throws max stack size exceededan error, because the components will be an infinite recursion, infinite loop. To solve this problem, we should give a recursive component constraints, the general assembly will be used in the recursive v-ifsetting somewhere falseto end. For example, we add to the above example attribute count, when more than 5 is no longer recursion:

<template>
  <div>
    <my-component :count="count + 1" v-if="count <= 5"></my-component>
  </div>
</template>
<script>
  export default {
    name: 'my-component',
    props: {
      count: {
        type: Number,
        default: 1
      }
    }
  }
</script>

Therefore, conclude the necessary conditions to implement a recursive components are:

  • Give the assembly is provided name ;
  • Have a clear end condition

Recursive components used to develop stand-alone component with an unknown level of relationship is rarely used in business development. Such as common cascade selector and tree controls:

Usually such components are data-driven, there is a parent Children field, then recursively. The next section of combat, will develop a tree control Tree.

Dynamic Components

Sometimes, we hope, according to some conditions, dynamically switch a component, or a component dynamically select the rendering. When subsections describe the functional components Functional Render previously been mentioned, it is a function of context, commonly used in the procedure of selecting a plurality of components. Functional Render Render or use can address the needs of dynamic switching assembly, but it is based on a JS objects (Render function), and provides another Vue.js built-in components <component>and isproperties can be better dynamic component.

A first look <component>and isbasic example, first define three general components:

<!-- a.vue -->
<template>
  <div>
    组件 A
  </div>
</template>
<script>
  export default {

  }
</script>
<!-- b.vue -->
<template>
  <div>
    组件 B
  </div>
</template>
<script>
  export default {

  }
</script>
<!-- c.vue -->
<template>
  <div>
    组件 C
  </div>
</template>
<script>
  export default {

  }
</script>

Then introducing the three components in the parent component, and dynamically switching:

<template>
  <div>
    <button @click="handleChange('A')">显示 A 组件</button>
    <button @click="handleChange('B')">显示 B 组件</button>
    <button @click="handleChange('C')">显示 C 组件</button>

    <component :is="component"></component>
  </div>
</template>
<script>
  import componentA from '../components/a.vue';
  import componentB from '../components/b.vue';
  import componentC from '../components/c.vue';

  export default {
    data () {
      return {
        component: componentA
      }
    },
    methods: {
      handleChange (component) {
        if (component === 'A') {
          this.component = componentA;
        } else if (component === 'B') {
          this.component = componentB;
        } else if (component === 'C') {
          this.component = componentC;
        }
      }
    }
  }
</script>

Here the isdynamic binding is a component object (Object), which points directly to a a / b / c of the three components. In addition to a direct binding Object, also can be a String, such as tag name, component name. Following this component, the original raw button button the package, if passed in prop: to, then it will be rendered as a <a>tag, to open the link address, if not pass to, use it as a normal button. Consider the following example:

<!-- button.vue -->
<template>
  <component :is="tagName" v-bind="tagProps">
    <slot></slot>
  </component>
</template>
<script>
  export default {
    props: {
      // 链接地址
      to: {
        type: String,
        default: ''
      },
      // 链接打开方式,如 _blank
      target: {
        type: String,
        default: '_self'
      }
    },
    computed: {
      // 动态渲染不同的标签
      tagName () {
        return this.to === '' ? 'button' : 'a';
      },
      // 如果是链接,把这些属性都绑定在 component 上
      tagProps () {
        let props = {};

        if (this.to) {
          props = {
            target: this.target,
            href: this.to
          }
        }

        return props;
      }
    }
  }
</script>

Use components:

<template>
  <div>
    <i-button>普通按钮</i-button>
    <br>
    <i-button to="https://juejin.im">链接按钮</i-button>
    <br>
    <i-button to="https://juejin.im" target="_blank">新窗口打开链接按钮</i-button>
  </div>
</template>
<script>
  import iButton from '../components/a.vue';

  export default {
    components: { iButton }
  }
</script>

Eventually render a native <button>link button and two native <a>, and a second click on the link will open in a new window, as shown:

i-button assembly <component> isbinding is a label name button / a, and by v-bindthe additional properties all bound to <component>the.

Go back to the first example of a / b / c switch components, if such components, the frequent switching, will in fact be re-render the component, such as our Riga two components A life cycle:

<!-- a.vue -->
<template>
  <div>
    组件 A
  </div>
</template>
<script>
  export default {
    mounted () {
      console.log('组件创建了');
    },
    beforeDestroy () {
      console.log('组件销毁了');
    }
  }
</script>

As long as the switch to the A component, mountedit will trigger a switch to other components, beforeDestroyit will trigger once, and then re-render the assembly instructions, which may lead to performance problems. To avoid repetition render component can be in <component>the outer sleeve Vue.js a built-in <keep-alive>assembly, so that the assembly will be cached:

<keep-alive>
  <component :is="component"></component>
</keep-alive>

At this point, only mountedtriggered if you do not leave the current page, switch to other components, beforeDestroywill not be triggered, indicating that components have been cached.

keep-alive some extra props can be configured:

  • include: String or a regular expression. Only the component name matches will be cached.
  • exclude: String or a regular expression. Any component matching names will not be cached.
  • max:digital. The maximum number of component instances can be cached.

Epilogue

Another type is the asynchronous component, Vue.js document has been presented very clearly, it can be extended at the end of reading the text reading 1. Many, such as router configuration list of the components we use in fact asynchronous, asynchronous components are generally used in the form of:

{
  path: '/form',
  component: () => import('./views/form.vue')
}

So that each page will load corresponding to when the JS file routing, otherwise entry file will be very large.

Recursive component, dynamic components and asynchronous components are relatively popular Vue.js three kinds of component patterns, but when the individual components of a complex package, the former two will often use.

Further reading

Published 112 original articles · won praise 43 · views 50000 +

Guess you like

Origin blog.csdn.net/itwangyang520/article/details/105021492