>웹 프론트엔드 >프런트엔드 Q&A >Vue 컴포넌트 개발은 무엇을 의미하나요?

Vue 컴포넌트 개발은 무엇을 의미하나요?

青灯夜游
青灯夜游원래의
2021-12-27 16:15:147635검색

Vue에서 컴포넌트 개발이란 복잡한 비즈니스를 여러 컴포넌트로 분할하는 것을 의미하며, 각 컴포넌트가 의존하는 CSS, JS, 템플릿, 그림 및 기타 리소스를 함께 개발하고 유지 관리합니다. 구성 요소는 리소스와 독립적이기 때문에 시스템 내에서 재사용할 수 있어 코드 양이 크게 단순화되고 나중에 수요 변경 및 유지 관리에 더 친화적입니다.

Vue 컴포넌트 개발은 무엇을 의미하나요?

이 튜토리얼의 운영 환경: Windows 7 시스템, vue 버전 2.9.6, DELL G3 컴퓨터.

Vue 컴포넌트 개발

컴포넌트화란 무엇입니까

vue.js에는 두 가지 마법의 무기가 있습니다. 하나는 데이터 기반이고 다른 하나는 컴포넌트화입니다. 따라서 문제는 컴포넌트화가 무엇이며 왜 컴포넌트화하려는가입니다. ? 다음으로 이 두 가지 질문에 대해 하나씩 답변해 드리겠습니다. 소위 컴포넌트화란 페이지를 여러 개의 컴포넌트로 분할하고 각 컴포넌트가 의존하는 CSS, JS, 템플릿, 그림 및 기타 리소스를 함께 개발하고 유지하는 것을 의미합니다. 컴포넌트는 리소스와 독립적이기 때문에 시스템 내에서 재사용이 가능하고, 컴포넌트를 중첩할 수 있어 프로젝트가 복잡할 경우 코드의 양을 크게 줄일 수 있고, 추후 요구 변경 및 유지 관리에도 더 친화적입니다.

1. 컴포넌트 개발은 복잡한 비즈니스를 컴포넌트로 차례로 분할하는 것을 의미합니다.

2. 컴포넌트 개발의 컴포넌트는 일반적으로 유연해야 합니다.

3. 컴포넌트 개발에는 Vue의 js 컴포넌트 캡슐화가 필요합니다. Vue 인스턴스 메소드 및 속성, Vue.extend, Vue 플러그인 등

Vue 컴포넌트 개발은 무엇을 의미하나요?

컴포넌트 개발 수행 방법

우선 아래 그림을 보세요.

Vue 컴포넌트 개발은 무엇을 의미하나요?

이것이 vue입니다. js의 오류는 등록되지 않은 구성 요소 lx-xxx의 사용으로 인해 발생합니다. 이 오류는 다음과 같은 사실을 알려줍니다.

맞춤 구성 요소를 사용하기 전에 등록해야 합니다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
  }
}

区别:全局组件是挂载在 Vue.options.components 下,而局部组件是挂载在 vm.$options.components. 그러면 구성 요소를 등록하는 방법은 무엇입니까? Vue.js는 구성요소를 등록하는 두 가지 방법인

글로벌 등록

로컬 등록을 제공합니다.

1. 글로벌 등록

vue.js에서는

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

name: &#39;lxNiu&#39;

2과 같은 글로벌 등록에 Vue.comComponent(tagName, 옵션)를 사용할 수 있습니다. >Vue.js는 또한 로컬 등록을 지원합니다. 구성 요소 내부의 구성 요소 옵션을 사용하여 구성 요소의 로컬 등록을 수행할 수 있습니다. 예:

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

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

show: Boolean // 默认false

msg: [String, Boolean]  // 多种类型

차이점:

전역 구성 요소는 Vue.options.comComponents, 로컬 컴포넌트는 <code>vm.$options.comComponents 아래에 마운트되기 때문에 글로벌로 등록된 컴포넌트를 임의로 사용할 수 있습니다.

컴포넌트 개발을 위한 필수 지식일을 잘하려면 먼저 도구를 연마해야 한다고 합니다. 정식으로 컴포넌트를 개발하기 전에 먼저 필요한 몇 가지 지식을 간략하게 익히겠습니다. 여기에서 소개해주세요. 자세한 내용은 공식 홈페이지를 참고해주세요.

name

컴포넌트 이름 필수

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

computed: {
  newMsg() {
    return &#39;hello &#39; + this.msg
  }
},

js에서는 카멜 케이스 명령을 사용하고, HTML에서는 케밥 케이스 네이밍을 사용하세요.

props

부모-자식 구성 요소 통신에 사용되는 구성 요소 속성, 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>

computed




데이터 또는 소품의 속성을 처리하고 새 속성을 반환

<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>

: props, data 및 Computed는 컴파일 단계에서 VM의 속성으로 병합되므로 이름을 바꿀 수 없습니다

render

렌더링 기능을 사용하여 템플릿을 설명하세요

// 父组件
<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>
Vue 컴포넌트 개발은 무엇을 의미하나요?render. 세 개의 매개변수를 받아들이는 createElement는 vnode를 반환합니다.

h 매개변수 설명:

args1: {string | Object} DOM의 HTML 콘텐츠를 제공하는 데 사용됩니다. args2: {Object} DOM 스타일, 속성, 바인딩 이벤트 등을 설정합니다. args3: {array } 배포용 콘텐츠를 설정하는 데 사용됩니다.참고: vue 컴파일 순서: template–> render -->

// 父组件
<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>
class

하위 구성 요소의 클래스 이름을 정의합니다.

<input v-bind="$attrs">
style

하위 구성 요소에 스타일을 전달합니다.

<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>

기타 속성

$ attrs

v-bind="$attrs"는 입력 정의와 같이 클래스 및 스타일 이외의 속성을 상위 구성 요소에 추가합니다.

// 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]
}
🎜🎜v-once🎜🎜🎜구성 요소는 한 번만 렌더링되며 렌더링되지 않습니다. 나중에 데이터가 변경되더라도 다시 렌더링됩니다. 예를 들어 이 예에서는 val이 456🎜
<template>
  <button>lxButton</button>
</template>

<script>
export default {
  name: &#39;lxButton&#39;
}
</script>
🎜🎜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]
}

实例演示

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

Vue 컴포넌트 개발은 무엇을 의미하나요?

index.vue

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

<script>
export default {
  name: &#39;lxButton&#39;
}
</script>

index.js

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

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

export default lxButton

其中 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>

定义组件

<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>

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

注:@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);
  }
};

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>

局部组件实例

<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>

8. 分享总结

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

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

위 내용은 Vue 컴포넌트 개발은 무엇을 의미하나요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.