Vue ν¨μν μ»΄ν¬λνΈμ λν΄μ
π ν¨μν μ»΄ν¬λνΈλ?
ν¨μν μ»΄ν¬λνΈ
λ μνμ μΈμ€ν΄μ€κ° μ‘΄μ¬νμ§ μλ μ»΄ν¬λνΈλ₯Ό λ§ν©λλ€.
μ»΄ν¬λνΈκ° μνκ° μκ³ μΈμ€ν΄μ€ν λμ§ μκΈ° λλ¬Έμ this 컨ν
μ€νΈ
κ° μμ΅λλ€.
μνκ° μκΈ° λλ¬Έμ μ΄κΈ° λ λλ§κ³Ό μ λ°μ΄νΈ μ μ±λ₯ μ΄μ μ λ³Ό μ μλ€λ νΉμ§μ΄ μμ΅λλ€.
π ν¨μν μ»΄ν¬λνΈ μ¬μ©νκΈ°
μ΄νμ μ¬μ©λλ μμ λ Vue 2.x λ₯Ό κΈ°μ€μΌλ‘ μμ±λμμμ μ μ λ°λλλ€.
Vue 3 λΆν°λ functional: true
μμ±λμ μΌλ° ν¨μλ‘ ν¨μν μ»΄ν¬λνΈλ₯Ό ꡬνν μ μμ΅λλ€.
template μ functional μμ± μ§μ νκΈ°
SFC(single file component)
λ₯Ό μ¬μ©νλ κ²½μ° λ€μκ³Ό κ°μ΄ template
μ΅μ
μ μ¬μ©νλ©΄ λ©λλ€.
<template functional>
<div>ν¨μν μ»΄ν¬λνΈ</div>
</template>
<script lang="ts">
import { Component, Vue, } from 'vue-property-decorator'
@Component({
name: 'Functional'
})
export default class Functional extends Vue {}
</script>
@Component
λ°μ½λ μ΄ν°μ functional: true
μ΅μ
μ μ§μ ν μ μλ μ°Ύμλ΄€λλ°..
vue-class-component
λ ν¬μ ν΄λΉ μ΄μκ° λ±λ‘λμ΄μμμ΅λλ€.
How to create functional component in @Component? · Issue #120 · vuejs/vue-class-component
κ°λ°μ μ견μ λ°λ₯΄λ©΄ ν¨μν μ»΄ν¬λνΈλ κ²°κ΅ μΈμ€ν΄μ€νλμ§ μκΈ° λλ¬Έμ ν΄λμ€λ‘ ꡬνν νμκ° μκ³ ,
λλ¬Έμ @Component
λ°μ½λ μ΄ν°λ₯Ό ν΅ν΄ ν΄λμ€λ‘ μ»΄ν¬λνΈλ₯Ό λ§λλ κ²μ μ’μ λ°©λ²μ΄ μλλΌκ³ ν©λλ€.
λμ λ€μκ³Ό κ°μ΄ Vue.extend
λ₯Ό μ¬μ©νλ λ°©λ²μ κΆκ³ νκ³ μμ΅λλ€.
Vue.extend μ render ν¨μλ₯Ό μ΄μ©ν΄μ ꡬννκΈ°
render
ν¨μλ context
λΌλ μΈμλ₯Ό λ°λλ°, μ΄λ₯Ό ν΅ν΄ μ»΄ν¬λνΈμ μ¬λ¬ μμ±μ μ κ·Ό κ°λ₯ν©λλ€.
<script lang="ts">
import { Vue, } from 'vue-property-decorator'
export default Vue.extend({
functional: true,
render: function(createElement, context) {
return createElement('div', 'ν¨μν μ»΄ν¬λνΈ')
}
})
</script>
context
λ₯Ό ν΅ν΄ μ κ·Ό κ°λ₯ν μ»΄ν¬λνΈ μμ±λ€μ λ€μκ³Ό κ°μ΅λλ€.
- props: μ λ¬λ°μ props κ°μ²΄
- children: μμ VNode λ°°μ΄
- slots: μ¬λ‘― κ°μ²΄λ₯Ό λ°ννλ ν¨μ
- scopedSlots: λ²μκ° μ§μ λ μ¬λ‘―μ λ λλ§νλ ν¨μλ₯Ό κ°μ§ κ°μ²΄μ λλ€.
- data: μ»΄ν¬λνΈμ μ λ¬λ λ°μ΄ν° κ°μ²΄
- parent: λΆλͺ¨ μ»΄ν¬λνΈμ λν μ°Έμ‘°
- listeners: λΆλͺ¨μκ² λ±λ‘λ μ΄λ²€νΈ 리μ€λλ₯Ό κ°μ§ κ°μ²΄
- injections:
inject
μ΅μ μ κ°μ§ κ²½μ° μ£Όμ λ λ°μ΄ν°λ₯Ό κ°μ§κ³ μμ
ν¨μν μ»΄ν¬λνΈμ μ΄λ²€νΈ 리μ€λ ν λΉνκΈ°
// λΆλͺ¨ μ»΄ν¬λνΈ
<template>
<functional-component @click="onClick" />
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
import FunctionalComponent from '../components/Functional.vue'
@Component({
name: 'Index',
components: { FunctionalComponent }
})
export default class Index extends Vue {
public onClick() {
console.log('ν΄λ¦λ¨')
}
}
</script>
// μμ μ»΄ν¬λνΈ
<script lang="ts">
import { Vue, } from 'vue-property-decorator'
export default Vue.extend({
functional: true,
render: function(createElement, context) {
return createElement('div', {
on: {
click: context.listeners.click
}
}, 'ν¨μν μ»΄ν¬λνΈ')
}
})
</script>
π ν¨μν μ»΄ν¬λνΈλ₯Ό μ¬μ©νμ λ μ₯μ μ?
λ λλ§ μλκ° λΉ λ₯΄λ€.
ν¨μν μ»΄ν¬λνΈλ μνκ° μκΈ° λλ¬Έμ Vue μ λ°μν μμ€ν μ μν μ΄κΈ°ν μμ μ΄ νμμμ΅λλ€.
λλ¬Έμ λ λλ§ μλμμ μ°¨μ΄κ° λλλ°, μ΄λ₯Ό λ²€μΉλ§νΉν κ²°κ³Όλ ν΄μΈ ν λΈλ‘κ±°κ° μ 리ν΄λ¨μ΅λλ€.
https://codesandbox.io/s/vue-template-yterr?fontsize=14
κ²°κ³Όλ₯Ό μ΄ν΄λ³΄λ©΄ 1000κ°μ 리μ€νΈ λͺ©λ‘μ λ λλ§ ν λ, ν¨μν μ»΄ν¬λνΈλ‘ ꡬνν κ²½μ° 40ms
κ° μμλλ©°
μνκ° μ‘΄μ¬νλ μΌλ°μ μΈ μ»΄ν¬λνΈλ‘ ꡬννλ©΄ 140ms
κ° μμλλ€κ³ ν©λλ€.
λλ¬Έμ μνκ° νμνμ§ μμ presentational component
λ₯Ό λ λλ§ ν λ μ¬μ©νλ©΄ μ’μ΅λλ€.
π Vue μ ν¨μν μ»΄ν¬λνΈλ μμ νμ§ μμ΅λλ€.
μμ± λ³ν©μ΄ μ λλ‘ λμ§ μμ΅λλ€.
Vue μμλ λ€μκ³Ό κ°μ΄ μμ μ»΄ν¬λνΈμμ μμ μ»΄ν¬λνΈμκ² μμ±μ μ λ¬ν μ μμ΅λλ€.
λλΆλΆμ μμ±μ κ²½μ° μμ μ»΄ν¬λνΈμκ² μ λ¬λ μμ±κ°μΌλ‘ λ체λλλ° class
μ style
μ κ²½μ°
λ³ν©μ΄ μ΄λ£¨μ΄μ§λλ€.
λ°λΌμ λ§μ½ λ€μκ³Ό κ°μ΄ μ»΄ν¬λνΈλ₯Ό μ μνλ€λ©΄ μμ μ»΄ν¬λνΈλ fancy awesome
λͺ¨λλ₯Ό κ°μ ΈμΌ ν©λλ€.
// λΆλͺ¨ μ»΄ν¬λνΈμμ μμ μ»΄ν¬λνΈμ class μμ±μΌλ‘ fancy μ§μ
<template>
<div>
<functional-component class="fancy" @click="onClick" />
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
import FunctionalComponent from '../components/Functional.vue'
@Component({
name: 'Index',
components: { FunctionalComponent }
})
export default class Index extends Vue {
public onClick() {
console.log('ν΄λ¦λ¨')
}
}
</script>
<style lang="scss">
.fancy {
color: red;
}
</style>
// μμ μ»΄ν¬λνΈ(ν¨μν μ»΄ν¬λνΈ) μμ class μμ±μΌλ‘ awesome μ§μ
<script lang="ts">
import { Vue, } from 'vue-property-decorator'
export default Vue.extend({
functional: true,
render: function(createElement, context) {
return createElement('div', {
on: {
click: context.listeners.click
},
class: {
awesome: true,
},
}, 'ν¨μν μ»΄ν¬λνΈ')
}
})
</script>
<style lang="scss">
.awesome {
font-size: 5rem;
}
</style>
κ·Έλ°λ° μ€νν΄λ³΄λ©΄ μμ μ»΄ν¬λνΈλ awesome
νλλ§ κ°μ§κ³ μλ κ²μ νμΈν μ μλλ°,
μ΄λ λ€μκ³Ό κ°μ΄ staticClass
λ₯Ό μ§μ λ°μΈλ©μ ν΄μ€μΌλ‘μ¨ ν΄κ²° κ°λ₯ν©λλ€.
<script lang="ts">
import { Vue, } from 'vue-property-decorator'
export default Vue.extend({
functional: true,
render: function(createElement, context) {
return createElement('div', {
on: {
click: context.listeners.click
},
class: {
awesome: true,
...(context.data.staticClass && { [context.data.staticClass]: true })
},
attrs: {
...context.data.attrs
}
}, 'ν¨μν μ»΄ν¬λνΈ')
}
})
</script>
How to apply classes to Vue.js Functional Component from parent component?
ν¨μν μ»΄ν¬λνΈλ₯Ό μ€μ²©λ μ»΄ν¬λνΈλ‘ μ¬μ©μ λ¬Έμ κ° λ°μν©λλ€.
μ λ¬Έμ μ μ΄μ΄μ λ§μ½ μ μ½λμμ λΆλͺ¨ μ»΄ν¬λνΈμ μ€νμΌμ΄ scoped
λΌλ©΄ λΆλͺ¨μμ μ§μ ν
scoped css
κ° μ μ©μ΄ μλλ μ΄μκ° μμ΅λλ€.
νμ¬ μ΄ μ΄μλ ν΄κ²°μ΄ μλ κ²μΌλ‘ 보μ΄λλ°... Vue 3 μμλ ν΄κ²°μ΄ λμλμ§ νμΈμ΄ νμν΄λ³΄μ λλ€.
μ€μ ν¨μν μ»΄ν¬λνΈ μ¬μ©μ κ³ λ €ν λ μ€νμΌμ΄ νμνλ€λ©΄ ν° μ΄μλ‘ μμ©λ κ²μ΄λΌ μκ°λ©λλ€.
Nested functional components break SFC CSS scoping · Issue #1259 · vuejs/vue-loader
ν¨μν μ»΄ν¬λνΈ λ΄λΆμμ μμ μ»΄ν¬λνΈλ₯Ό λ λλ§ν λ λ¬Έμ κ° μκΉλλ€.
λ€μκ³Ό κ°μ΄ template
μμ±μ μ¬μ©ν΄μ ν¨μν μ»΄ν¬λνΈλ₯Ό ꡬμ±ν λ€
μμ μ»΄ν¬λνΈλ₯Ό import
ν΄μ λ λλ§νλ €κ³ νλ©΄ λ¬Έμ κ° μκΈ΄λ€κ³ ν©λλ€.
<template functional>
<div>
<some-children />
</div>
</template>
<script>
import SomeChildren from "./SomeChildren"
export default {
components: {
SomeChildren
}
}
</script>
μ΄λ₯Ό μ°ννλ λ°©λ²μΌλ‘ λ€μκ³Ό κ°μ΄ μ»΄ν¬λνΈλ₯Ό μ£Όμ ν΄μ£Όλ λ°©λ²μ μ¬μ©νλΌκ³ μ μνκ³ μμ΅λλ€.
<template functional>
<div>
<component :is="injections.components.SomeChildren"></component>
</div>
</template>
<script>
import SomeChildren from "./SomeChildren.vue";
export default {
inject: {
components: {
default: {
SomeChildren
}
}
}
};
</script>
κ·Έλ°λ° μ§μ ν΄λ³Έ κ²°κ³Ό, κ·Έλ₯ render
ν¨μλ₯Ό ν΅ν΄ ν¨μν μ»΄ν¬λνΈλ₯Ό ꡬννλ©΄
λ¬Έμ μμ΄ μμ μ»΄ν¬λνΈκ° λ λλ§ λλ κ²μ νμΈνμ΅λλ€.
κ·Έλ₯ λ§ νΈνκ² ν¨μν μ»΄ν¬λνΈλ μΌλ° ν¨μλ₯Ό ν΅ν΄ ꡬννλ κ²μ΄ μ μ 건κ°μ μ’μ κ² κ°μ΅λλ€. π
<script lang="ts">
import { Vue, } from 'vue-property-decorator'
import Finance from './Finance.vue'
export default Vue.extend({
functional: true,
render: function(createElement, context) {
return createElement('div', {
on: {
click: context.listeners.click
},
class: {
awesome: true,
...(context.data.staticClass && { [context.data.staticClass]: true })
},
attrs: {
...context.data.attrs
}
},
[createElement(Finance)]
)
}
})
</script>
Functional single file component with components option. · Issue #7492 · vuejs/vue
π μ°Έκ³ μλ£
ν¨μν μ»΄ν¬λνΈ(Functional Components) | Vue.js
Vue.js functional components: what, why, and when?
'π archive' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
[Vue.js] computed μμ± μ¬μ© μ μ£Όμν μ λ€ (0) | 2022.02.23 |
---|---|
[Vue.js] Error Boundary λ‘ μλ¬ νΈλ€λ§νκΈ° (0) | 2022.02.20 |
[Vue.js] v-deep μμ±μ λν΄μ (0) | 2022.02.20 |
[Vue.js] mixin μ½λ μ€νμΌ κ°μ΄λ (0) | 2022.02.20 |
[Vue.js] v-model μμ±κ³Ό @Model λ°μ½λ μ΄ν°μ κ΄ν΄μ (0) | 2022.02.20 |
π¬ λκΈ