- javascript์ vue ์ฝ๋์ ์์ฑ์ airbnb์ vue/essential ๊ฐ์ด๋๋ฅผ ๋ฐ๋ฅธ๋ค
- style์์ญ์ scoped scss๋ฅผ ์ฌ์ฉํ๊ณ ํด๋์ค์ ๋ช ๋ช ๊ท์น์ BEM์ ์ฌ์ฉํ๋ค
-
์ปดํผ๋ํธ ๊ตฌ๋ถ
- components: ์ดํ๋ฆฌ์ผ์ด์ ์ ์ญ์์ ์ฌ์ฉ๋๋ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ์ปดํผ๋ํธ
- modules: ํน์ ํ์ด์ง๋ด์์ ์ฌ์ฉ๋๋ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ์ปดํผ๋ํธ
- pages: ๋ผ์ฐํฐ๋ฅผ ๊ฐ์ง๋ View ์ปดํผ๋ํธ
- layouts: ๋ผ์ฐํฐ์ ๋ ์ด์์์ ์ ์ํ๋ ์ปดํผ๋ํธ
-
Vue ๊ธฐ๋ฅ๊ด๋ จ
- store: vuex๋ฅผ ์ฌ์ฉํ๋ฉฐ ๊ธฐ๋ฅ๋จ์๋ก ์ํ๋ฅผ ๊ตฌ๋ถ
- router: ํ์ด์ง์ ์ง์ ๊ฒฝ๋ก๋ฅผ ๊ด๋ฆฌ
- directives: ์ปค์คํ directives
- filters: ์ปค์คํ filters
-
lib
- ์ธ๋ถ ์๋น์ค์ SDK ๋๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ค๋ฃจ๋ ์์ญ
-
assets
- ํ์ด์ง ๋ด ๋ฆฌ์์ค
-
styles
- ํ์ด์ง ์ ์ญ ์คํ์ผ
-
constants
- ํ์ด์ง์์ ์ฌ์ฉํ๋ ํจ์
- ๋ชจ๋์ Import๋ ๋์ผํ ๊ฒฝ๋ก๋ฅผ ์ ์ธํ๊ณ ์ ๋๊ฒฝ๋ก๋ฅผ ์ฌ์ฉํ๋ค.
@/components/foo
./foo
- js ํ์ผ์ด ์๋ ๊ฒฝ์ฐ ํ์ฅ์๋ฅผ ํ๊ธฐํ๊ณ ํ์ผ๋ช ์ ๋ณํํ์ง ์๋๋ค.
@/components/foo.vue; (O)
@/components/foo.vue; (X)
@import '@/scss/base/_colors.scss'; (O)
@import '@/scss/base/colors.scss'; (X)
- ํ๊ทธ์ ๋ช ๋ช ๊ณผ ํ๋กํผํฐ๋ฐ์ธ๋ฉ์ ์ค๋ค์ดํฌ์ผ์ด์ค๋ก ํ๊ธฐํ๋ค.
(O) <eight-percent/>
(X) <EightPercent/>
- Slot์์ญ์ด ํ์์๋ ๊ฒฝ์ฐ ์ถ์ํ์ผ๋ก ํ๊ธฐํ๋ค.
(O) <eight-percent/>
(X) <eight-percent></eight-percent>
- ํ๋กํผํฐ์ ์ดํธ๋ฆฌ๋ทฐํธ๋ฅผ ์ฌ๋ฌ์ค๋ก ๋ด๋ ค์ฐ๋ ๊ฒฝ์ฐ ์ค๋ฐ๊ฟ ์ดํ ์์ฑํ๋ค.
(O)
<eight-percent
v-if="loaded"
:data-index="dealIndex"
/>
(X)
<eight-percent v-if="loaded"
:data-index="dealIndex"
/>
- ๋จ ์์ํ HTMLํ๊ทธ์๋ ๋ง์ ์์๊ฐ ๋ฐ์ธ๋ฉ๋์ง ์๋๋ค๋ฉด ํ์ค์ ์ธ์ ํ์ฉํ๋ค.
(O)
<div id="foo" class="bar"></div>
(-)
<div
class="x"
></div>
- ํ๋กํผํฐ์ ์ดํธ๋ฆฌ๋ทฐํธ ๋์ด์ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ค์์ ์์๋ก ์งํํ๊ณ ์ค์๋์ ๋ฐ๋ผ ์์๋ ์กฐ์ ๋ ์ ์๋ค.
<eight-percent
// ์ ์ ํ๋กํผํฐ
class=""
// ์กฐ๊ฑด๋ถ ๋ฐ์ธ๋ฉ
v-if="loaded"
// ๋ฆฌ์คํธ๋๋๋ง
v-for="(item, index) in items"
// ์ดํธ๋ฆฌ๋ทฐํธ ๋ฐ์ธ๋ฉ
:class="{ active: isActive }"
:style="{ color: activeColor, fontSize: fontSize + 'px' }"
// ์ด๋ฒคํธ ๋ฐ์ธ๋ฉ
@click="event"
// Props ๋ฐ์ธ๋ฉ (Props๋ Array ๋๋ primary type์ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ๋ค)
:data-index="dataIndex"
/>
v-if
์v-for
๋ ๋์์ ์ฌ์ฉํ์ง ์๊ณ , ์กฐ๊ฑด๋ถ ๋ฆฌ์คํธ๋๋๋ง์ ๊ฒฝ์ฐ computed์์ฑ์์ filterํ๋ค.- style, class ๋ฐ์ธ๋ฉ์ ๋ฌธ์์ด๋ณด๋ค๋ ๊ฐ์ฒด๋ ๋ฐฐ์ด๋ก ์ ์ํ๋ค.
- ๋จ ์ด๋ฒคํธ๋ฐ์ธ๋ฉ์ ๋ฐ๋์ ์นด๋ฉ์ผ์ด์ค๋ก ์์ฑํ๋ค. (์ผ๋ฐฅ์ผ์ด์ค ์์ฑ ์ ์ค๋ฅ๊ฐ ๋ฐ์ํ ์ ์์)
- ๋ ์ด์์, ๋ฏน์ค์ธ, ๋ณ์ ๋ฑ ์ ์ญ ์คํ์ผ์ ์ ์ธํ ์์ญ์์ scoped scss๋ฅผ ์ฌ์ฉํ๋ค.
<style lang="scss" scoped>
- ํด๋์ค์ ๋ช ๋ช ์ BEM์ ๋ฐ๋ฅธ๋ค.
- ID์ ํ์๋ ๋ฐ๋์ ํ์ด์ง์์ ์ ์ผํจ์ด ๋ณด์ฅ๋์ด์ผ ํ๋ ํ ๊ทธ์๋ง ์ฌ์ฉํ๋ค.
- Module์์ฑ์ ์ฌ์ฉํ์ง ์๋๋ค. (๊ธฐ์กด์ฝ๋์ ํฌํจ๋์ด ์๊ณ ์ ์ฌํ ํํ๋ก ๊ฐ๋ฐ์ด ์งํ๋๋ ๊ฒฝ์ฐ์๋ ์ฌ์ฉ)
// module css ์์
<script>
data() {
return {
color: this.$colors.black,
redColor: this.$style.red,
};
}
</script>
<style lang="scss" module="$colors">
@import '@/scss/base/_colors.scss';
:export {
black: $color-gr-700;
}
</style>
<style module>
.red {
color: red;
}
</style>
- ์ปดํผ๋ํธ๋ ๊ธฐ๋ณธ์ ์ผ๋ก ํ์ผ๋ช ๊ณผ ์ผ์นํ๋ ๊ฒ์ ์์น์ผ๋ก ํ๊ณ ๊ตฌ๋ถ์ด ํ์ํ ๊ฒฝ์ฐ prefix๋ฅผ ๋ถ์ฌ์ค๋ค.
components: {
'el-title': Table,
},
- ์ปดํผ๋ํธ์ ๊ตฌ์ฑ์ ๋ค์์ ์์๋ฅผ ๋ฐ๋ฅด๊ณ ์ฌ์ฉ๋๋ ํญ๋ชฉ์ด ์๋๊ฒฝ์ฐ ์์ฑํ์ง ์๋๋ค
import Foo from 'path';
export default {
name: '',
mixins: [],
props: {},
component: {},
data() {
return {
}
},
computed: {},
watch: {},
methods: {},
// LifeCycle Hooks
created() {},
}
- Props๋ ๋จ์๋์ด์ด ์๋ ๊ตฌ์ฒด์ ์ผ๋ก ์ ์ํ๊ณ Optional๊ฐ์ default๊ฐ์ ๋ช ์ํ๋ค.
- validator๋ ํ์์ ๋ฐ๋ผ ์ ํ ์ ์ฉํ๋ค.
required: true
๋ ์์๋ ๋ฌธ์ ๊ฐ ๋์ผํ๋ ๊ฒฝ์ฐ์๋ง ์ฌ์ฉํ๋ค.
props: {
props1: {
type: String,
required: true,
},
props2: {
type: String,
default: '',
},
props3: {
type: Array,
default: () => [],
},
props4: {
type: Object,
default: () => ({
foo: '',
bar: 1
}),
},
props5: {
type: String,
validator: function (value) {
// The value must match one of these strings
return ['success', 'warning', 'danger'].indexOf(value) !== -1
}
},
}
- ๊ฐ๊ธ์ ๋จ๋ฐฉํฅ ๋ฐ์ดํฐ ํ๋ฆ์ ์ ์งํ๋ค.
- Store์ Vuex ๊ธฐ๋ณธ๋ฌธ๋ฒ์ ์ฌ์ฉํ๊ณ ์คํ ์ด์ ์์กด์ฑ์ด ํฐ ๊ฒฝ์ฐ Helperํจ์๋ฅผ ์ฌ์ฉํ๋ค.
// Action
this.$store.dispatch('Action Name', value)
// Mutation
this.$store.commit('Mutation Name', value);
// Getter
this.$store.state['State Name']
// helperํจ์ ์ด์ฉ
import { createNamespacedHelpers } from 'vuex';
const { mapState, mapActions } = createNamespacedHelpers('[๋ชจ๋๋ค์]');
...mapActions([
'[ActionName]',
]),
import { mapState, mapActions } from 'vuex'
...mapActions([
'[๋ชจ๋๋ค์]/[ActionName]',
]),
// ๋ชจ๋๋ณ ๊ตฌ๋ถ (ํ๋์ ์ปดํผ๋ํธ์์ ๋ค์ํ ๋ชจ๋ Store๋ฅผ ์ฐธ์กฐํ ๋)
import { mapState, mapActions } from 'vuex'
...mapActions('๋ชจ๋๋ค์', [
'ActionName1',
'ActionName2',
]),
- ์คํ ์ด๋ ๊ธฐ๋ฅ๋ณ ๋ชจ๋ํํ์ฌ ์ฌ์ฉ ํ๋ค.
- ๊ธฐ๋ณธ๊ตฌ์ฑ์ ์๋์ ๊ฐ์ผ๋ฉฐ mutation-type์ ์ ํ์ ์ฌ์ฉํ๋ค.
import request from 'superagent';
export default {
namespaced: true,
state: {
state1: '',
},
getters: {
// get + ์ํ๋ช
์ ์ฃผ๋ก ์ฌ์ฉํ๊ณ ์๋ฏธ์๋ ๋ช
์ฌ๋ ์ํ๊ฐ๊ณผ ๋์ผํ๊ฒ ์ฌ์ฉํ๊ธฐ๋ ํ๋ค.
getState1: '',
},
mutations: {
// set + ์ํ๋ช
์ผ๋ก ์ฌ์ฉํ๊ณ ์ํ๋ฅผ ๋ณ์ด์ํค๋ ์ฝ๋๊ฐ ์๋ ํฌํจํ์ง ์๋๋ค.
setState(state, value) {
state.dealNotice = value;
},
},
actions: {
// ๋น๋๊ธฐ์ฒ๋ฆฌ๋ ํ์๋ฅผ ๊ธฐ์ ํ๊ณ ๋ค์ด๋ฐ์ ์ ์ฝ์ ์๋ค.
fetchData(context, id) {
return new Promise((resolve, reject) => {})
},
},
};
- Actions
- Action์ ๋น๋๊ธฐ๊ณผ์ ์ด๋ ์ ์ ์ ํ์๋ฅผ ์ ์ํ์ฌ ์ฌ์ฉํ๋ค.
- ์ปดํผ๋ํธ์์ ์ํ๋ณํ๋ฅผ ์ผ์ผํฌ๋๋ mutation๋ช ์ผ๋ก ์๋ฏธ๊ฐ ์ ๋ฌ๋์ง ์๋๋ค๋ฉด action์ ํตํด์ ์ ๊ทผํ๋๋ก ํ๋ค.
- ๋ผ์ฐํฐ ๋์๋ '/'๋ ๋ถ์ด์ง ์๋๋ค.
- ๋ผ์ฐํฐ๋ ๊ฐ๊ธ์ ์ด๋ฆ์ ๊ฐ์ง๋๋ก ํ๊ณ name์ผ๋ก ์ฌ์ฉํ๋ค.
this.$router.push({
name: '',
params: {},
query: {},
});
- Watch๋ ๋ค์๊ณผ ๊ฐ์ด ์ ์๋์ด ์ฌ์ฉํ๋ค.
watch: {
watchDataName() {
},
},
- ๋ณต์ก๋๊ฐ ๋๊ฑฐ๋ watch option์ด ํ์ํ ๊ฒฝ์ฐ ๋ค์์ ํํ๋ก ์ฌ์ฉํ๋ค.
methods: {
todo1() { },
todo2() { },
},
watch: {
watchDataName: {
deep: true, // option: object ๋๋ array๋ฅผ ๊ฐ์ํ ๋ (default: false)
immediate: true, // option: ํ์ด์ง ๋ก๋ ์ฆ์ ์คํ (default: false)
handler: [
'todo1',
'todo2',
// oldValue๊ฐ์ ์ฐธ์กฐํ๊ฑฐ๋ ํ๋ผ๋ฏธํฐ๋ฅผ ์ ๋ฌํ๋ ๊ฒฝ์ฐ
function foo (value, oldValue) {
},
],
}
}
- computed์์ฑ์ผ๋ก ํด๊ฒฐํ ์ ์๋ค๋ฉด ๊ฐ๊ธ์ ์ฌ์ฉํ์ง ์๋๋ค.