Vue 스타일 가이드 3

Vue 스타일 가이드 3편입니다.

2편 : http://gameb.co.kr/vue-스타일-가이드-2/

: 필수
: 매우 추천
: 추천
X : 주의 요함

21.속성 값에 따옴표 ☆

속성 값은 항상 따옴표를 사용합니다.

나쁨
<input type=text>

<AppSidebar :style={width:sidebarWidth+'px'}>
좋음
<input type="text">

<AppSidebar :style="{ width: sidebarWIdth + 'px' }">

22.축약형 지시어 ☆

v-bind, @, # 와 같은 축약형 지시어는 항상 사용하거나 사용하지 않는게 좋습니다.

나쁨
<input
    v-bind:value="newTodoNext"
    :placeholder="newTodoInstructions"
>

<input
    v-on:input="onInput"
    @focus="onFocus"
>

<template v-slot:header>
    <h1>Here might be a page title</h1>
</template>

<template #footer>
    <p>Here's some contact info</p>
</template>
좋음
<input
    :value="newTodoText"
    :placeholder="newTodoInstructions"
>

<input
    v-bind:value="newTodoText"
    v-bind:placeholder="newTodoInstructions"
>

<input
    @input="onInput"
    @focus="onFocus"
>

<input
    v-on:input="onInput"
    v-on:focus="onFocus"
>

<template v-slot:header>
    <h1>Here might be a page title</h1>
</template>

<template v-slot:footer>
    <p>Here's some contact info</p>
</template>

23.컴포넌트/인스턴스의 옵션 순서 ○

컴포넌트/인스턴스 옵션의 순서는 언제나 일정한 순서로 정렬 되어야 합니다.

1.사이드이펙트 – 컴포넌트 외부에 효과가 미치는 옵션
  • el
2.전역 인지 – 컴포넌트 외부에 필요한 옵션
  • name
  • parent
3.컴포넌트 유형 – 컴포넌트의 유형을 바꾸는 옵션
  • functional
4.템플릿 변경자 – 템플릿 컴파일 변경 옵션
  • delimiters
  • comments
5.템플릿 의존성 – 템플릿에 이용되는 요소들을 지정하는 옵션
  • components
  • directives
  • filters
6.컴포지션 – 다른 컴포넌트의 속성을 가져와 합치는 옵션
  • extends
  • mixins
7.인터페이스 – 컴포넌트의 인터페이스를 지정하는 옵션
  • inheritAttrs
  • model
  • props / propsData
8.지역 상태 – 반응적인 지역 속성들을 설정하는 옵션
  • data
  • computed
9.이벤트 – 반응적인 이벤트 옵션
  • watch
  • beforeCreate
  • created
  • beforeMount
  • mounted
  • beforeUpdate
  • updated
  • activated
  • deactived
  • beforeDestory
  • destroyed
10.비반응적 속성 – 반응과 상관업는 옵션
  • methods
11.렌더링 – 컴포넌트의 출력 옵션
  • template / render
  • renderError

24.엘리먼트 속성 순서

1.정의 – 컴포넌트 옵션을 제공하는 속성
  • is
2.리스트 렌더링 – 같은 엘리먼트를 여러 개 생성하는 속성
  • v-for
3.조건부 렌더링 – 렌더링 여부를 결정하는 속서
  • v-if
  • v-else-if
  • v-else
  • v-show
  • v-cloak
4.렌더 변경자 – 렌더링 방식을 변경하는 속성
  • v-pre
  • v-once
5.전역 인지 – 컴포넌트의 외부 속성
  • id
6.유일한 속성 – 유일한 값을 가진 속성
  • ref
  • key
  • slot
7.양방향 바인딩 – 바인딩과 이벤트를 결합
  • v-model
8.이벤트 – 이벤트 리스너 속성
  • v-on
9.내용 – 엘리먼트의 내용 변경 속성
  • html
  • text

25.컴포넌트/인스턴스 옵션간 빈 줄 ○

가독성을 위해 속성 사이에 빈 줄을 추가할 수 있습니다.

좋음
props : {
    value : {
        type : String,
        required : true
    },

    focused : {
        type : Boolean,
        default : false
    },

    label : String,
    icon : String
},

computed : {
    formattedValue : function () {
        //...
    },

    inputClassed : function ) {
        //...
    }
}
props : {
    value : {
        type : String,
        required : true
    },  
    focused : {
        type : Boolean,
        default : false
    },  
    label : String,
    icon : String
},
computed : {
    formattedValue : function () {
        //...
    },  
    inputClassed : function ) {
        //...
    }
}

26.싱글 파일 컴포넌트 최상위 엘리먼트 순서

style 엘리먼트는 마지막에 배치하는게 좋습니다.

나쁨
<style> /*...*/ </style>
<script> /*...*/ </script>
<template> /*...*/ </template>

<!-- ComponentA.vue -->
<script> /*...*/ </script>
<template> /*...*/ </template>
<style> /*...*/ </style>

<!-- ComponentB.vue -->
<template> /*...*/ </template>
<script> /*...*/ </script>
<style> /*...*/ </style>
좋음
<!-- ComponentA.vue -->
<script> /*...*/ </script>
<template> /*...*/ </template>
<style> /*...*/ </style>

<!-- ComponentB.vue -->
<script> /*...*/ </script>
<template> /*...*/ </template>
<style> /*...*/ </style>
<!-- ComponentA.vue -->
<template> /*...*/ </template>
<script> /*...*/ </script>
<style> /*...*/ </style>

<!-- ComponentB.vue -->
<template> /*...*/ </template>
<script> /*...*/ </script>
<style> /*...*/ </style>

26.key 가 없는 v-if / v-if-else / v-else X

요소 유형이 동일한 경우 key와 함께 사용하는 것이 좋습니다. (v-if, v-else)

나쁨
<div v-if="error">
    Error : {{ error }}
</div>
<div v-else>
    {{ results }}
</div>
좋음
<div 
    v-if="error"
    key="search-status"
>
    Error : {{ Error }}
</div>
<div
    v-else
    key="search-results"
>
    {{ results }}
</div>

27.scoped에서 엘리먼트 선택자 사용 X

태그 선택자보다 클래스 선택자를 사용합니다.

나쁨
<template>
    <button>X</button>
</template>

<style scoped>
button {
    background-color:red;
}
</style>
좋음
<template>
    <button class="btn btn-close">X</button>    
</template>

<style scoped>
.btn-close {
    background-color:red;
}
</style>

28.부모 자식간 의사소통 X

this.$parent 보다는 emit을 사용하는게 좋습니다.

나쁨
Vue.component('TodoItem', {
    props : {
        todo : {
            type : Object,
            required : true
        }
    },
    template : '<input v-model="todo.text">'
})
Vue.component('TodoItem', {
    props : {
        todo : {
            type : Object,
            required : true
        }
    },
    methods : {
        removeTodo () {
            var vm = this
            vm.$parent.todos = vm.$parent.todos.filter(function (todo) {
                return todo.id !== vm.todo.id
            })
        }
    },
    templte : `
        <span>
            {{ todo.text }}
            <button @click="removeTodo">
                X
            </button>
        </span>
    `   
})
좋음
Vue.component('TodoItem', {
    props: {
        todo: {
            type: Object,
            required: true
        }
    },
    template: `
        <input
            :value="todo.text"
            @input="$emit('input', $event.target.value)"
        >
    `
})
Vue.component('TodoItem', {
    props: {
        todo: {
            type: Object,
            required: true
        }
    },
    template: `
        <span>
            {{ todo.text }}
            <button @click="$emit('delete')">
                X
            </button>
        </span>
    `
})

29.전역 상태 관리

전역 상태는 this.$root, global event bus 보다는 Vuex를이용하는 것이 좋습니다.

나쁨
new Vue({
    data : {
        todos : []
    },
    created : function() {
        this.$on('remove-todo',this.removeTodo)
    },
    methods : {
        removeTodo : function (todo) {
            var todoIdToRemove = todo.id
            this.todos = this.todos.filter(function (todo) {
                return todo.id !== todoIdToRemove
            })
        }
    }
})
좋음
// store/modules/todos.js
export default {
    state : {
        list : []
    },
    mutations : {
        REMOVE_TODO (state,todoId) {
            state.list = state.list.filter(todo => todo.id ! == todoId)
        }
    },
    actions : {
        removeTodo ({ commit, state }, todo) {
            commit('REMOVE_TODO', todo_id)
        }
    }
}
<!-- TodoItem.vue -->
<template >
    <span>
        {{ todo.text }}
        <button @click="removeTodo(todo)">
            X
        </button>
    </span>
</template>

<script>
import { mapActions } from 'vuex'

export default {
    props : {
        todo : {
            type : Object,
            required : true
        }
    },
    methods : mapActions(['removeTodo'])
}
</script>