Que signifie le développement de composants Vue ?

青灯夜游
Libérer: 2021-12-27 16:15:14
original
7593 Les gens l'ont consulté

Dans Vue, le développement de composants fait référence à la division d'une entreprise complexe en plusieurs composants, et les CSS, JS, modèles, images et autres ressources dont dépend chaque composant sont développés et maintenus ensemble. Étant donné que les composants sont indépendants des ressources, ils peuvent être réutilisés au sein du système, ce qui simplifie considérablement la quantité de code et sont plus adaptés aux modifications ultérieures des demandes et à la maintenance.

Que signifie le développement de composants Vue ?

L'environnement d'exploitation de ce tutoriel : système Windows 7, vue version 2.9.6, ordinateur DELL G3. "Développement de composants Vue" ? Ensuite, je répondrai à ces deux questions une par une. La soi-disant composantisation signifie diviser la page en plusieurs composants, et les CSS, JS, modèles, images et autres ressources dont dépend chaque composant sont développés et maintenus ensemble.

Étant donné que les composants sont indépendants des ressources, ils peuvent être réutilisés dans le système et les composants peuvent être imbriqués. Si le projet est complexe, la quantité de code peut être considérablement simplifiée et il est également plus convivial pour exiger des modifications et une maintenance ultérieures.

1. Le développement de composants fait référence à la division d'une entreprise complexe en composants les uns après les autres

2. Les composants du développement de composants doivent généralement être flexibles

3 Le développement de composants implique l'encapsulation des composants js de Vue, vous devez maîtriser les bases de Vue, Méthodes et propriétés des instances Vue, Vue.extend, plug-ins Vue, etc.

Comment réaliser le développement de composants

Premier coup d'oeil à l'image ci-dessous :

Que signifie le développement de composants Vue ?C'est vue. Une erreur dans js est due à l'utilisation d'un composant non enregistré lx-xxx. Cette erreur nous dit une vérité :

Vous devez vous inscrire avant d'utiliser un composant personnalisé

. Alors comment enregistrer un composant ? Vue.js propose deux façons d'enregistrer des composants, enregistrement global et enregistrement local

.

1. Enregistrement global

Que signifie le développement de composants Vue ?Dans vue.js, nous pouvons utiliser Vue.component(tagName, options) pour un enregistrement global, tel que

Vue.component('my-component', {
  // 选项
})
Copier après la connexion

2. >lx-xxx ,这个报错告诉我们一个道理:使用自定义组件之前必须注册
那么如何注册一个组件呢? Vue.js 提供了 2 种组件的注册方式,全局注册局部注册

1. 全局注册

在 vue.js 中我们可以使用 Vue.component(tagName, options) 进行全局注册,例如

import HelloWorld from './components/HelloWorld'

export default {
  components: {
    HelloWorld
  }
}
Copier après la connexion

2. 局部注册

Vue.js 也同样支持局部注册,我们可以在一个组件内部使用 components 选项做组件的局部注册,例如:

<lx-niu/>
<lx-niu></lx-niu/>

name: &#39;lxNiu&#39;
Copier après la connexion

区别:全局组件是挂载在 Vue.options.components 下,而局部组件是挂载在 vm.$options.componentsVue.js prend également en charge l'enregistrement local. Nous pouvons utiliser l'option composants à l'intérieur d'un composant pour effectuer l'enregistrement local du composant, par exemple :

<div>{{msg}}</div>

props: {
  msg: {
    type: String,
    default: &#39;&#39;
  }
}

show: Boolean // 默认false

msg: [String, Boolean]  // 多种类型
Copier après la connexion

Différence :

Les composants globaux sont montés dans Vue.options.components<. / code>, tandis que les composants locaux sont montés sous <code>vm.$options.components, c'est pourquoi les composants enregistrés globalement peuvent être utilisés arbitrairement.

Connaissances essentielles pour le développement de composants

On dit que si vous voulez bien faire votre travail, vous devez d'abord aiguiser vos outils Avant de développer officiellement un composant, nous devons d'abord maîtriser certaines connaissances nécessaires. Je ne vais que brièvement. présentez-le ici, veuillez vous référer au site officiel pour plus de détails.

name

Le nom du composant, obligatoire

<div>{{newMsg}}</div>

computed: {
  newMsg() {
    return &#39;hello &#39; + this.msg
  }
},
Copier après la connexion
Utilisez les commandes camel case en js et utilisez la dénomination kebab-case en HTML.

props

Les propriétés des composants, utilisées pour la communication des composants parent-enfant, sont accessibles via this.msg

<lx-niu tag=&#39;button&#39;>hello world</lx-niu>

<script type="text/javascript">
  export default {
    name: &#39;lxNiu&#39;,
    props: {
      tag: {
        type: String,
        default: &#39;div&#39;
      },
    },
    // h: createElement
    render(h) {
      return h(this.tag,
        {class: &#39;demo&#39;}, 
        this.$slots.default)
    }
  }
</script>
Copier après la connexion

computed

Traitez les propriétés dans data ou props et renvoyez une nouvelle propriété

<lx-niu>
  <div slot=&#39;header&#39;>header</div>
  <div class="body" slot=&#39;body&#39;>
    <input type="text">
  </div>
  <div slot=&#39;footer&#39;>footer</div>

  <button class=&#39;btn&#39;>button</button>
</lx-niu>

<template>
  <div>
    <slot name=&#39;header&#39;></slot>
    <slot name=&#39;body&#39;></slot>
    <slot name=&#39;footer&#39;></slot>
    <slot></slot>
  </div>
</template>

<script>
  export default {
    name: &#39;lxNiu&#39;,
    mounted() {
      this.$slots.header // 包含了slot="foo"的内容
      this.$slots.default // 得到一个vnode,没有被包含在具名插槽中的节点,这里是button
    }
  }
</script>
Copier après la connexion
Remarque : étant donné que les accessoires, les données et les calculs seront fusionnés en tant qu'attributs vm pendant la phase de compilation, ils ne peuvent pas être renommés

render


Utilisez la fonction render pour décrire le modèle

// 父组件
<lx-niu round type=&#39;big&#39;/>

// 子组件
<div :class="[
  type ? &#39;lx-niu__&#39; + type : &#39;&#39;,
  {&#39;is-round&#39;: round},
]">控制</div>

//真实DOM
<div class=&#39;lx-niu__big is-round&#39;>hello</div>
Copier après la connexion

render Le h. il s'agit en fait de createElement, qui accepte trois paramètres, renvoie un vnode
h Explication du paramètre :

args1 : {string | Function Object} Utilisé pour fournir le contenu HTML du DOM

args2 : {Object} Définir les styles, les attributs et les événements de liaison du DOM , etc.

args3 : {array } Utilisé pour définir le contenu à distribuer

Remarque : ordre de compilation de vue : template–> compile render --> slot

Que signifie le développement de composants Vue ?

// 父组件
<lx-niu :bodyStyle=&#39;{color: "red"}&#39;/>


// 子组件
<template>
  <div :style=&#39;bodyStyle&#39;>hello world</div>
</template>

<script>
  export default {
    name: &#39;lxNiu&#39;,
    props: {
      bodyStyle: {},
    },
  }
</script>
Copier après la connexion
class

Définir le nom de classe du sous-composant

<input v-bind="$attrs">
Copier après la connexion
style

Pa style ss au sous-composant

<template>
  <div>
    <button @click="show = !show">button</button>
    <button @click="val = &#39;456&#39;">button</button>
    <div v-once v-if="show">
      <span>{{val}}</span>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return{
      show: false,
      val: &#39;123&#39;
    }
  },
};
</script>
Copier après la connexion
Autres attributs

$attrs

v- bind="$attrs" ajoute des attributs autres que la classe et le style au composant parent, comme la définition de l'entrée :

// mixin.js
export default {
  data() {
    return{
       msg: &#39;hello world&#39;
    }
  },
  methods: {
    clickBtn() {
      console.log(this.msg)
    }
  },
}

// index.vue
<button @click="clickBtn">button</button>

import actionMixin from "./mixin.js";
export default {
  methods: {},
  mixins: [actionMixin]
}
Copier après la connexion
Copier après la connexion

v-once

Le composant n'est rendu qu'une seule fois, et ne sera pas restitué même si les données changent ultérieurement. Par exemple, dans l'exemple, val ne deviendra pas 456

<template>
  <button>lxButton</button>
</template>

<script>
export default {
  name: &#39;lxButton&#39;
}
</script>
Copier après la connexion
Copier après la connexion

mixins🎜🎜.
// mixin.js
export default {
  data() {
    return{
       msg: &#39;hello world&#39;
    }
  },
  methods: {
    clickBtn() {
      console.log(this.msg)
    }
  },
}

// index.vue
<button @click="clickBtn">button</button>

import actionMixin from "./mixin.js";
export default {
  methods: {},
  mixins: [actionMixin]
}
Copier après la connexion
Copier après la connexion

实例演示

比如我们要注册一个 lx-button 这样一个组件,那么目录和伪代码如下:

Que signifie le développement de composants Vue ?

index.vue

<template>
  <button>lxButton</button>
</template>

<script>
export default {
  name: &#39;lxButton&#39;
}
</script>
Copier après la connexion
Copier après la connexion

index.js

import lxButton from &#39;./src/index&#39;

lxButton.install = (Vue) => {
  Vue.component(lxButton.name, lxButton)
}

export default lxButton
Copier après la connexion

其中 install 是 Vue.js 提供了一个公开方法,这个方法的第一个参数是 Vue 构造器,第二个参数是一个可选的选项对象。
MyPlugin.install = function (Vue, options){}

参考: 开发插件

https://cn.vuejs.org/v2/guide/plugins.html#%E5%BC%80%E5%8F%91%E6%8F%92%E4%BB%B6

watch-弹窗实现原理

<button @click="dialogVisible = true">显示</button>
<lx-niu :visible.sync="dialogVisible"></lx-niu>

<script>
  export default {
    data() {
      return {
        dialogVisible: false
      }
    },
    watch: {
      dialogVisible(val) {
        console.log(&#39;father change&#39;, val)
      }
    }
  }
</script>
Copier après la connexion

定义组件

<template>
  <div v-show="visible">
    <button @click="hide">关闭</button>
  </div>
</template>

<script>
  export default {
    name: &#39;lxNiu&#39;,
    props: {
      visible: Boolean
    },
    watch: {
      visible(val) {
        console.log(&#39;child change:&#39;, val)
      }
    },
    methods: {
      hide() {
        this.$emit(&#39;update:visible&#39;, false);
      }
    },
  }
</script>
Copier après la connexion

点击父组件中的显示按钮,改变传入子组件中的值,点击子组件中的关闭,改变父组件中值。

注:@click=“dialogVisible = true” 点击时将dialogVisible的值改为true
注::visible.sync: 双向数据绑定,配合update:visible使用,实现子组件修改父组件中的值

官网解释: sync

col组件实例

export default {
  name: &#39;ElCol&#39;,

  props: {
    span: {
      type: Number,
      default: 24
    },
    tag: {
      type: String,
      default: &#39;div&#39;
    },
    offset: Number,
    pull: Number,
    push: Number,
    xs: [Number, Object],
    sm: [Number, Object],
    md: [Number, Object],
    lg: [Number, Object],
    xl: [Number, Object]
  },

  computed: {
    gutter() {
      let parent = this.$parent;
      while (parent && parent.$options.componentName !== &#39;ElRow&#39;) {
        parent = parent.$parent;
      }
      return parent ? parent.gutter : 0;
    }
  },
  render(h) {
    let classList = [];
    let style = {};

    if (this.gutter) {
      style.paddingLeft = this.gutter / 2 + &#39;px&#39;;
      style.paddingRight = style.paddingLeft;
    }

    [&#39;span&#39;, &#39;offset&#39;, &#39;pull&#39;, &#39;push&#39;].forEach(prop => {
      if (this[prop] || this[prop] === 0) {
        classList.push(
          prop !== &#39;span&#39;
            ? `el-col-${prop}-${this[prop]}`
            : `el-col-${this[prop]}`
        );
      }
    });

    [&#39;xs&#39;, &#39;sm&#39;, &#39;md&#39;, &#39;lg&#39;, &#39;xl&#39;].forEach(size => {
      if (typeof this[size] === &#39;number&#39;) {
        classList.push(`el-col-${size}-${this[size]}`);
      } else if (typeof this[size] === &#39;object&#39;) {
        let props = this[size];
        Object.keys(props).forEach(prop => {
          classList.push(
            prop !== &#39;span&#39;
              ? `el-col-${size}-${prop}-${props[prop]}`
              : `el-col-${size}-${props[prop]}`
          );
        });
      }
    });

    return h(this.tag, {
      class: [&#39;el-col&#39;, classList],
      style
    }, this.$slots.default);
  }
};
Copier après la connexion

col组件使用render函数,而不是template来实现组件,原因有两个:

  • 该组件有大量的类判断,如果采用template代码比较冗余,使用js代码更加简洁

  • 直接render描述性能更好

官网解释: render-function

button组件实例

<template>
  <button
    class="el-button"
    @click="handleClick"
    :disabled="buttonDisabled || loading"
    :autofocus="autofocus"
    :type="nativeType"
    :class="[
      type ? &#39;el-button--&#39; + type : &#39;&#39;,
      buttonSize ? &#39;el-button--&#39; + buttonSize : &#39;&#39;,
      {
        &#39;is-disabled&#39;: buttonDisabled,
        &#39;is-loading&#39;: loading,
        &#39;is-plain&#39;: plain,
        &#39;is-round&#39;: round,
        &#39;is-circle&#39;: circle
      }
    ]"
  >
    <i class="el-icon-loading" v-if="loading"></i>
    <i :class="icon" v-if="icon && !loading"></i>
    <span v-if="$slots.default"><slot></slot></span>
  </button>
</template>
<script>
  export default {
    name: &#39;ElButton&#39;,

    inject: {
      elForm: {
        default: &#39;&#39;
      },
      elFormItem: {
        default: &#39;&#39;
      }
    },

    props: {
      type: {
        type: String,
        default: &#39;default&#39;
      },
      size: String,
      icon: {
        type: String,
        default: &#39;&#39;
      },
      nativeType: {
        type: String,
        default: &#39;button&#39;
      },
      loading: Boolean,
      disabled: Boolean,
      plain: Boolean,
      autofocus: Boolean,
      round: Boolean,
      circle: Boolean
    },

    computed: {
      _elFormItemSize() {
        return (this.elFormItem || {}).elFormItemSize;
      },
      buttonSize() {
        return this.size || this._elFormItemSize || (this.$ELEMENT || {}).size;
      },
      buttonDisabled() {
        return this.disabled || (this.elForm || {}).disabled;
      }
    },

    methods: {
      handleClick(evt) {
        this.$emit(&#39;click&#39;, evt);
      }
    }
  };
</script>
Copier après la connexion

局部组件实例

<template>
  <div class="login">
    <login-header />
    <login-request />
    <login-footer />
  </div>
</template>

<script>
import loginHeader from &#39;./login-header&#39;;
import loginRequest from &#39;./login-request&#39;;
import loginFooter from &#39;./login-footer&#39;;

export default {
  components: {
    [loginHeader.name]: loginHeader,
    [loginRequest.name]: loginRequest,
    [loginFooter.name]: loginFooter
  }
};
</script>
Copier après la connexion

8. 分享总结

  • 首先介绍了什么是组件化开发,以及为什么要进行组件化
  • 其次介绍了组件开发的两种方式和适用场景,以及进行组件化开发的必备知识
  • 最后实例演示了全局组件和局部组件的开发

【相关推荐:《vue.js教程》】

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal