溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

vue組件化開發(fā)指的是什么意思

發(fā)布時間:2021-12-27 16:33:52 來源:億速云 閱讀:421 作者:小新 欄目:web開發(fā)

小編給大家分享一下vue組件化開發(fā)指的是什么意思,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!

在vue中,組件化開發(fā)指的是將復雜的業(yè)務拆分為多個組件,每個組件依賴的CSS、JS、模板、圖片等資源放在一起開發(fā)和維護。因為組件是資源獨立的,所以組件在系統(tǒng)內部可復用,且可以極大簡化代碼量,對后期的需求變更和維護也更加友好。

vue組件化開發(fā)指的是什么意思

本教程操作環(huán)境:windows7系統(tǒng)、vue2.9.6版,DELL G3電腦。

Vue 組件化開發(fā)

什么叫做組件化

vue.js 有兩大法寶,一個是數(shù)據(jù)驅動,另一個就是組件化,那么問題來了,什么叫做組件化,為什么要組件化?接下來我就針對這兩個問題一一解答,所謂組件化,就是把頁面拆分成多個組件,每個組件依賴的 CSS、JS、模板、圖片等資源放在一起開發(fā)和維護。 因為組件是資源獨立的,所以組件在系統(tǒng)內部可復用,組件和組件之間可以嵌套,如果項目比較復雜,可以極大簡化代碼量,并且對后期的需求變更和維護也更加友好。

1、組件化開發(fā)指的是將復雜的業(yè)務拆分為一個又一個的組件

2、組件化開發(fā)的組件一般來說要靈活

3、組件化開發(fā)涉及到了Vue的js組件封裝,需要掌握Vue基礎、Vue實例方法與屬性、Vue.extend、Vue插件等知識

vue組件化開發(fā)指的是什么意思

如何進行組件化開發(fā)

先看下圖:

vue組件化開發(fā)指的是什么意思

這是 vue.js 中的一個報錯,原因是使用了一個未經(jīng)注冊的組件 lx-xxx ,這個報錯告訴我們一個道理:使用自定義組件之前必須注冊。  
那么如何注冊一個組件呢? Vue.js 提供了 2 種組件的注冊方式,全局注冊局部注冊。

1. 全局注冊

在 vue.js 中我們可以使用 Vue.component(tagName, options) 進行全局注冊,例如

Vue.component('my-component', {
  // 選項
})

2. 局部注冊

Vue.js 也同樣支持局部注冊,我們可以在一個組件內部使用 components 選項做組件的局部注冊,例如:

import HelloWorld from './components/HelloWorld'

export default {
  components: {
    HelloWorld
  }
}

區(qū)別:全局組件是掛載在 Vue.options.components 下,而局部組件是掛載在 vm.$options.components 下,這也是全局注冊的組件能被任意使用的原因。

組件化開發(fā)必備知識

所謂工欲善其事,必先利其器,在正式開發(fā)一個組件之前,我們先要掌握一些必備的知識,這里我只會簡單介紹一下,詳情參考官網(wǎng)。

name

組件的名稱,必填

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

name: 'lxNiu'

js 中使用駝峰式命令,HTML 使用kebab-case命名。

props

組件屬性,用于父子組件通信,可通過this.msg訪問

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

props: {
  msg: {
    type: String,
    default: ''
  }
}

show: Boolean // 默認false

msg: [String, Boolean]  // 多種類型

computed

處理data或者props中的屬性,并返回一個新屬性

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

computed: {
  newMsg() {
    return 'hello ' + this.msg
  }
},

注:因為props,data和computed在編譯階段都會作為vm的屬性合并,所以不可重名

render

用render函數(shù)描述template

<lx-niu tag='button'>hello world</lx-niu>

<script type="text/javascript">
  export default {
    name: 'lxNiu',
    props: {
      tag: {
        type: String,
        default: 'div'
      },
    },
    // h: createElement
    render(h) {
      return h(this.tag,
        {class: 'demo'}, 
        this.$slots.default)
    }
  }
</script>

render 中的 h 其實就是 createElement,它接受三個參數(shù),返回一個 vnode  
h 參數(shù)解釋:  
args1: {string | Function | Object} 用于提供DOM的html內容  
args2: {Object} 設置DOM樣式、屬性、綁定事件之類  
args3: {array} 用于設置分發(fā)的內容

注:vue編譯順序: template–> compile --> render --> vnode --> patch --> DOM

slot

vue組件化開發(fā)指的是什么意思

<lx-niu>
  <div slot='header'>header</div>
  <div class="body" slot='body'>
    <input type="text">
  </div>
  <div slot='footer'>footer</div>

  <button class='btn'>button</button>
</lx-niu>

<template>
  <div>
    <slot name='header'></slot>
    <slot name='body'></slot>
    <slot name='footer'></slot>
    <slot></slot>
  </div>
</template>

<script>
  export default {
    name: 'lxNiu',
    mounted() {
      this.$slots.header // 包含了slot="foo"的內容
      this.$slots.default // 得到一個vnode,沒有被包含在具名插槽中的節(jié)點,這里是button
    }
  }
</script>

class

定義子組件的類名

// 父組件
<lx-niu round type='big'/>

// 子組件
<div :class="[
  type ? 'lx-niu__' + type : '',
  {'is-round': round},
]">控制</div>

//真實DOM
<div class='lx-niu__big is-round'>hello</div>

style

向子組件傳遞樣式

// 父組件
<lx-niu :bodyStyle='{color: "red"}'/>


// 子組件
<template>
  <div :style='bodyStyle'>hello world</div>
</template>

<script>
  export default {
    name: 'lxNiu',
    props: {
      bodyStyle: {},
    },
  }
</script>

其他屬性

$attrs

v-bind="$attrs" 將除class和style外的屬性添加到父組件上,如定義input:

<input v-bind="$attrs">

v-once

組件只渲染一次,后面即使數(shù)據(jù)發(fā)生變化也不會重新渲染,比如例子中val不會變成456

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

<script>
export default {
  data() {
    return{
      show: false,
      val: '123'
    }
  },
};
</script>

mixins

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

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

import actionMixin from "./mixin.js";
export default {
  methods: {},
  mixins: [actionMixin]
}

實例演示

比如我們要注冊一個 lx-button 這樣一個組件,那么目錄和偽代碼如下:

vue組件化開發(fā)指的是什么意思

index.vue

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

<script>
export default {
  name: 'lxButton'
}
</script>

index.js

import lxButton from './src/index'

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

export default lxButton

其中 install 是 Vue.js 提供了一個公開方法,這個方法的第一個參數(shù)是 Vue 構造器,第二個參數(shù)是一個可選的選項對象。
MyPlugin.install = function (Vue, options){}

參考: 開發(fā)插件

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

watch-彈窗實現(xiàn)原理

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

<script>
  export default {
    data() {
      return {
        dialogVisible: false
      }
    },
    watch: {
      dialogVisible(val) {
        console.log('father change', val)
      }
    }
  }
</script>

定義組件

<template>
  <div v-show="visible">
    <button @click="hide">關閉</button>
  </div>
</template>

<script>
  export default {
    name: 'lxNiu',
    props: {
      visible: Boolean
    },
    watch: {
      visible(val) {
        console.log('child change:', val)
      }
    },
    methods: {
      hide() {
        this.$emit('update:visible', false);
      }
    },
  }
</script>

點擊父組件中的顯示按鈕,改變傳入子組件中的值,點擊子組件中的關閉,改變父組件中值。

注:@click=“dialogVisible = true” 點擊時將dialogVisible的值改為true  
注::visible.sync: 雙向數(shù)據(jù)綁定,配合update:visible使用,實現(xiàn)子組件修改父組件中的值

官網(wǎng)解釋: sync

col組件實例

export default {
  name: 'ElCol',

  props: {
    span: {
      type: Number,
      default: 24
    },
    tag: {
      type: String,
      default: 'div'
    },
    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 !== 'ElRow') {
        parent = parent.$parent;
      }
      return parent ? parent.gutter : 0;
    }
  },
  render(h) {
    let classList = [];
    let style = {};

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

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

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

    return h(this.tag, {
      class: ['el-col', classList],
      style
    }, this.$slots.default);
  }
};

col組件使用render函數(shù),而不是template來實現(xiàn)組件,原因有兩個:

  • 該組件有大量的類判斷,如果采用template代碼比較冗余,使用js代碼更加簡潔

  • 直接render描述性能更好

官網(wǎng)解釋: render-function

button組件實例

<template>
  <button
    class="el-button"
    @click="handleClick"
    :disabled="buttonDisabled || loading"
    :autofocus="autofocus"
    :type="nativeType"
    :class="[
      type ? 'el-button--' + type : '',
      buttonSize ? 'el-button--' + buttonSize : '',
      {
        'is-disabled': buttonDisabled,
        'is-loading': loading,
        'is-plain': plain,
        'is-round': round,
        'is-circle': 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: 'ElButton',

    inject: {
      elForm: {
        default: ''
      },
      elFormItem: {
        default: ''
      }
    },

    props: {
      type: {
        type: String,
        default: 'default'
      },
      size: String,
      icon: {
        type: String,
        default: ''
      },
      nativeType: {
        type: String,
        default: 'button'
      },
      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('click', evt);
      }
    }
  };
</script>

局部組件實例

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

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

export default {
  components: {
    [loginHeader.name]: loginHeader,
    [loginRequest.name]: loginRequest,
    [loginFooter.name]: loginFooter
  }
};
</script>

看完了這篇文章,相信你對“vue組件化開發(fā)指的是什么意思”有了一定的了解,如果想了解更多相關知識,歡迎關注億速云行業(yè)資訊頻道,感謝各位的閱讀!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內容。

vue
AI