Vue에서 컴포넌트 개발이란 복잡한 비즈니스를 여러 컴포넌트로 분할하는 것을 의미하며, 각 컴포넌트가 의존하는 CSS, JS, 템플릿, 그림 및 기타 리소스를 함께 개발하고 유지 관리합니다. 구성 요소는 리소스와 독립적이기 때문에 시스템 내에서 재사용할 수 있어 코드 양이 크게 단순화되고 나중에 수요 변경 및 유지 관리에 더 친화적입니다.
이 튜토리얼의 운영 환경: Windows 7 시스템, vue 버전 2.9.6, DELL G3 컴퓨터.
컴포넌트화란 무엇입니까
vue.js에는 두 가지 마법의 무기가 있습니다. 하나는 데이터 기반이고 다른 하나는 컴포넌트화입니다. 따라서 문제는 컴포넌트화가 무엇이며 왜 컴포넌트화하려는가입니다. ? 다음으로 이 두 가지 질문에 대해 하나씩 답변해 드리겠습니다. 소위 컴포넌트화란 페이지를 여러 개의 컴포넌트로 분할하고 각 컴포넌트가 의존하는 CSS, JS, 템플릿, 그림 및 기타 리소스를 함께 개발하고 유지하는 것을 의미합니다. 컴포넌트는 리소스와 독립적이기 때문에 시스템 내에서 재사용이 가능하고, 컴포넌트를 중첩할 수 있어 프로젝트가 복잡할 경우 코드의 양을 크게 줄일 수 있고, 추후 요구 변경 및 유지 관리에도 더 친화적입니다.
1. 컴포넌트 개발은 복잡한 비즈니스를 컴포넌트로 차례로 분할하는 것을 의미합니다. 2. 컴포넌트 개발의 컴포넌트는 일반적으로 유연해야 합니다. 3. 컴포넌트 개발에는 Vue의 js 컴포넌트 캡슐화가 필요합니다. Vue 인스턴스 메소드 및 속성, Vue.extend, Vue 플러그인 등컴포넌트 개발 수행 방법
우선 아래 그림을 보세요. 이것이 vue입니다. js의 오류는 등록되지 않은 구성 요소lx-xxx
의 사용으로 인해 발생합니다. 이 오류는 다음과 같은 사실을 알려줍니다. 맞춤 구성 요소를 사용하기 전에 등록해야 합니다lx-xxx
,这个报错告诉我们一个道理:使用自定义组件之前必须注册。
那么如何注册一个组件呢? Vue.js 提供了 2 种组件的注册方式,全局注册和局部注册。
在 vue.js 中我们可以使用 Vue.component(tagName, options) 进行全局注册,例如
Vue.component('my-component', { // 选项 })
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: 'lxNiu'
2과 같은 글로벌 등록에 Vue.comComponent(tagName, 옵션)를 사용할 수 있습니다. >Vue.js는 또한 로컬 등록을 지원합니다. 구성 요소 내부의 구성 요소 옵션을 사용하여 구성 요소의 로컬 등록을 수행할 수 있습니다. 예:
<div>{{msg}}</div> props: { msg: { type: String, default: '' } } show: Boolean // 默认false msg: [String, Boolean] // 多种类型차이점:
전역 구성 요소는 Vue.options.comComponents, 로컬 컴포넌트는 <code>vm.$options.comComponents
아래에 마운트되기 때문에 글로벌로 등록된 컴포넌트를 임의로 사용할 수 있습니다.
컴포넌트 개발을 위한 필수 지식일을 잘하려면 먼저 도구를 연마해야 한다고 합니다. 정식으로 컴포넌트를 개발하기 전에 먼저 필요한 몇 가지 지식을 간략하게 익히겠습니다. 여기에서 소개해주세요. 자세한 내용은 공식 홈페이지를 참고해주세요.
name컴포넌트 이름 필수
<div>{{newMsg}}</div> computed: { newMsg() { return 'hello ' + this.msg } },js에서는 카멜 케이스 명령을 사용하고, HTML에서는 케밥 케이스 네이밍을 사용하세요. props
부모-자식 구성 요소 통신에 사용되는 구성 요소 속성, this.msg를 통해 액세스 가능
<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>computed
데이터 또는 소품의 속성을 처리하고 새 속성을 반환
<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,没有被包含在具名插槽中的节点,这里是button } } </script>: props, data 및 Computed는 컴파일 단계에서 VM의 속성으로 병합되므로 이름을 바꿀 수 없습니다
render
렌더링 기능을 사용하여 템플릿을 설명하세요// 父组件 <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>render. 세 개의 매개변수를 받아들이는 createElement는 vnode를 반환합니다. h 매개변수 설명:
args1: {string | Object} DOM의 HTML 콘텐츠를 제공하는 데 사용됩니다. args2: {Object} DOM 스타일, 속성, 바인딩 이벤트 등을 설정합니다. args3: {array } 배포용 콘텐츠를 설정하는 데 사용됩니다.참고: vue 컴파일 순서: template–> render -->
// 父组件
<lx-niu :bodyStyle='{color: "red"}'/>
// 子组件
<template>
<div :style='bodyStyle'>hello world</div>
</template>
<script>
export default {
name: 'lxNiu',
props: {
bodyStyle: {},
},
}
</script>
class
하위 구성 요소의 클래스 이름을 정의합니다. <input v-bind="$attrs">
style
하위 구성 요소에 스타일을 전달합니다.
<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>
기타 속성
$ attrs
v-bind="$attrs"는 입력 정의와 같이 클래스 및 스타일 이외의 속성을 상위 구성 요소에 추가합니다.
// 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] }🎜🎜v-once🎜🎜🎜구성 요소는 한 번만 렌더링되며 렌더링되지 않습니다. 나중에 데이터가 변경되더라도 다시 렌더링됩니다. 예를 들어 이 예에서는 val이 456🎜
<template> <button>lxButton</button> </template> <script> export default { name: 'lxButton' } </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 这样一个组件,那么目录和伪代码如下:
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 提供了一个公开方法,这个方法的第一个参数是 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('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: 双向数据绑定,配合update:visible使用,实现子组件修改父组件中的值
官网解释: 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函数,而不是template来实现组件,原因有两个:
该组件有大量的类判断,如果采用template代码比较冗余,使用js代码更加简洁
直接render描述性能更好
官网解释: 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>
8. 分享总结
【相关推荐:《vue.js教程》】
위 내용은 Vue 컴포넌트 개발은 무엇을 의미하나요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!