Vuetify
|
Material Component Framework for Vue.js 2
Categories
Dark theme
- Vuetify — A Material Design Framework for Vue.js # Light and dark
- Application theming — Vuetify.js # 밝게, 어둡게 (Light and Dark)
기본 설정은 라이트 테마이며 dark
속성을 추가하여 변경할 수 있다.
// src/plugins/vuetify.js
import Vue from 'vue'
import Vuetify from 'vuetify/lib'
Vue.use(Vuetify)
export default new Vuetify({
theme: { dark: true },
})
Presets
다음 명령으로 추가할 수 있다.
- vue add vuetify-preset-basil
- vue add vuetify-preset-crane
- vue add vuetify-preset-fortnightly
- vue add vuetify-preset-owl
- vue add vuetify-preset-rally
- vue add vuetify-preset-reply
- vue add vuetify-preset-shrine
TypeScript 코딩 준비
Vue#TypeScript 코딩 준비를 우선적으로 적용.
컴포넌트 임포트 에러 해결 방법
- Stackoverflow - Typescript: TS7006: Parameter 'xxx' implicitly has an 'any' type
- How to use vuetify in vue typescript? #112
다음과 같이 임포트시
다음과 같은 에러가 출력된다면:
TS7016: Could not find a declaration file for module 'vuetify/lib/components/VForm'. '/home/your/Project/answer-plugin-vms/fe/node_modules/vuetify/lib/components/VForm/index.js' implicitly has an 'any' type. If the 'vuetify' package actually exposes this module, try adding a new declaration (.d.ts) file containing `declare module 'vuetify/lib/components/VForm';`
tsconfig.json의 컴파일러 옵션에 "noImplicitAny": false
를 추가해야 한다.
{
"compilerOptions": {
"skipLibCheck": true,
"noImplicitAny": false,
"typeRoots": [
"node_modules/@types",
"node_modules/vuetify/types"
],
"types": ["vuetify"]
}
}
Layouts
Vuetify에는 v-app 및 v-main의 두 가지 기본 레이아웃 구성 요소가 있습니다. v-app 구성 요소는 애플리케이션의 루트이며 기본 Vue 진입점인 <div id="app">
를 직접 대체합니다. v-main 구성 요소는 기본 HTML 요소와 애플리케이션 콘텐츠의 루트에 대한 의미론적 대체입니다. Vue가 DOM에 마운트되면 레이아웃의 일부인 Vuetify 구성 요소는 현재 높이 및/또는 너비를 프레임워크 코어에 등록합니다. 그런 다음 v-main 구성 요소는 이러한 값을 가져와 컨테이너 크기를 조정합니다.
<v-app>
<v-app-bar app></v-app-bar>
<v-main>
<v-container>
Hello World
</v-container>
</v-main>
</v-app>
화면의 가로/세로 중심 배치
<template>
<v-main>
<!-- The card in the center of the screen. -->
<v-container fluid class="fill-height">
<v-row align="center" justify="center">
<v-col class="max-content-width">
<!-- Main Content -->
<v-card>
<!-- ... -->
</v-card>
</v-col>
</v-row>
</v-container>
</v-main>
</template>
<style lang="scss" scoped>
.max-content-width {
max-width: 480px;
}
</style>
그리고, 메인 컨텐츠는 최대 너비 480px로 적용된다.
Customizing item-text
다음과 같이, item
의 요소로서 다음과 같이 사용할 수 있다.
매뉴얼에 따르면 다음과 같다.
따라서 다음과 같이 람다로 추가할 수도 있다.
SVG Path 직접 그리는 방법
@mdi/js 와 같은 패키지를 다운받으면 v-icon 컴포넌트를 사용해 그리는데, 직접 컴포넌트를 그린다면 다음과 같이 그리면 된다.
<template>
<svg class="grid-view--table-body-row-drag"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
role="img"
aria-hidden="true"
>
<path :d="icons.dragVertical"></path>
</svg>
</template>
<script lang="ts">
import {Vue, Component} from 'vue-property-decorator';
import {mdiDragVertical} from '@mdi/js';
@Component
export default class GridView extends Vue {
readonly icons = {
dragVertical: mdiDragVertical
};
}
</script>
<style lang="scss" scoped>
.grid-view--table-body-row-drag {
width: 10px;
height: 32px;
fill: currentColor;
}
</style>
색상의 악센트 추가하는 방법
deep-purple accent-4
와 같이 색상 이름 이후, 공백을 주고 악센트 레벨을 주면 된다:
테마에 자동으로 변경되는 커스텀 스타일 적용 방법
- Stackoverflow - Vuetify - How to set background color
- Stackoverflow - How to override vuetify styles?
스타일 적용
그냥 템플릿에 style
속성을 바인딩 하여 직접 색상을 지정할 수 있다. 가장 좋지 않은 방법이다.
<template>
<div class="fill-width" :style="contentStyle"></div>
</template>
<script lang="ts">
import {Vue, Component, Prop, Watch} from 'vue-property-decorator';
@Component
export default class ViewPort extends Vue {
get contentStyle() {
return {'background-color': '#ffffff'};
}
}
</script>
Vuetify의 colors 클래스 사용 방법
vuetify/lib/util/colors
를 import 하면 된다.
<template>
<div class="fill-width" :style="contentStyle"></div>
</template>
<script lang="ts">
import {Vue, Component, Prop, Watch} from 'vue-property-decorator';
import colors from 'vuetify/lib/util/colors'
@Component
export default class ViewPort extends Vue {
get contentStyle() {
if (this.$vuetify.theme.dark) {
return {'background-color': colors.grey.darken1};
} else {
return {'background-color': colors.grey.lighten5};
}
}
}
</script>
Vuetify의 styles.sass를 사용하는 방법
scss를 사용하여, $material-dark
와 $material-light
에 있는 text.secondary
색상을 폰트 색상으로, 테마에 따라 적용하는 컴포넌트이다:
<template>
<p class="text-subtitle-2 font-weight-bold mb-1" :class="textColorClass">
<slot></slot>
</p>
</template>
<script lang="ts">
import {Vue, Component, Prop} from 'vue-property-decorator';
@Component
export default class SubtitleBold extends Vue {
@Prop({type: String})
readonly value!: string;
get textColorClass() {
if (this.$vuetify.theme.dark) {
return 'text-color-dark';
} else {
return 'text-color-light';
}
}
}
</script>
<style lang="scss" scoped>
@import '~vuetify/src/styles/styles.sass';
.text-color-light {
color: map-get(map-get($material-light, 'text'), 'secondary');
}
.text-color-dark {
color: map-get(map-get($material-dark, 'text'), 'secondary');
}
</style>
CSS Selector 사용 방법
Vuetify의 v-app 문서를 보면 "응용 프로그램 변형 (dark/light)을 자식 구성 요소에 전파"1 한다고 나와있다. 저 v-app 은 최종 HTML은 다음과 같이 적용된다:
<div data-app="true" class="v-application v-application--is-ltr theme--dark" id="app">
<!-- ... -->
</div>
그리고 Vuetify의 많은 구성요소(컴포넌트)는 다음과 같은 CSS Selector를 통해 배경색상이 전파된다:
눈여겨 볼 점은 theme--dark
와 theme--light
클래스가, Vuetify의 다크테마(this.$vuetify.theme.dark
) 참/거짓 여부에 따라 바뀐다.
따라서 위의, 클래스 셀렉터를 사용하여 하위 컴포넌트의 CSS Selector를 지정하면 된다.
<template>
<div class="grid-view"></div>
</template>
<style lang="scss" scoped>
.grid-view {
}
.theme--light.v-application .grid-view {
background: red;
}
.theme--dark.v-application .grid-view {
background: blue;
}
</style>
이렇게 하면 javascript를 사용하지 않고 테마를 변경에 대한 특수화를 지정할 수 있다.
주의할 점은 다음과 같이 Deep Selector를 사용할 경우,
다음과 같이 컴파일된다.
이렇게 되면, 루트 엘리먼트를 찾을 수 없으므로 Deep Selector를 사용해선 안된다.
참고로 Deep Selector를 사용하지 않으면 다음과 같이 컴파일된다.
Troubleshooting
TypeScript Error: Could not find a declaration file for module 'vuetify/lib’
- typescript에서 Vuetify import 오류 해결 - Never test
- When adding typescript - Error: Could not find a declaration file for module 'vuetify/lib’
TypeScript 적용시 아래와 같은 에러가 발생될 수 있다.
ERROR in C:/workspace/inhasite/general/ctlt_apply/english_clinic/src/plugins/vuetify.ts
2:21 Could not find a declaration file for module 'vuetify/lib'. 'C:/workspace/inhasite/general/ctlt_apply/english_clinic/node_modules/vuetify/lib/index.js' implicitly has an 'any' type.
Try `npm install @types/vuetify` if it exists or add a new declaration (.d.ts) file containing `declare module 'vuetify/lib';`
1 | import Vue from 'vue';
> 2 | import Vuetify from 'vuetify/lib';
| ^
3 | import 'vuetify/src/stylus/app.styl';
4 |
5 | Vue.use(Vuetify, {
Version: typescript 3.2.2, tslint 5.11.0
tsconfig.json 파일의 compilerOptions.types
에 "vuetify"
를 추가하면 된다.
Icon 출력 오류
우선, 종속성을 추가한다.
vuetify.js 파일에 다음과 같이 수정한다.
import Vue from "vue";
import Vuetify from "vuetify/lib";
import '@mdi/font/css/materialdesignicons.css' // Ensure you are using css-loader
Vue.use(Vuetify);
export default new Vuetify({
icons: {
iconfont: 'mdi',
},
});
언어 변경시 다른 컴포넌트의 언어 변경이 적용되지 않는 현상
Vue I18n#Troubleshooting 항목 참조.
v-text-field 의 errorBuckets 이 언어 변경시 적용되지 않는 현상
v-text-field 항목 참조.
Using / for division is deprecated
- Stackoverflow - Nuxtjs vuetify throwing lots of
Using / for division is deprecated and will be removed in Dart Sass 2.0.0.
- New Sass Deprecation Recommended #13694
: Using / for division is deprecated and will be removed in Dart Sass 2.0.0.
Recommendation: math.div($grid-gutter, 3)
More info and automated migrator: https://sass-lang.com/d/slash-div
╷
63 │ 'md': $grid-gutter / 3,
│ ^^^^^^^^^^^^^^^^
╵
node_modules/vuetify/src/styles/settings/_variables.scss 63:11 @import
node_modules/vuetify/src/styles/settings/_index.sass 1:9 @import
node_modules/vuetify/src/styles/styles.sass 2:9 @import
node_modules/vuetify/src/components/VIcon/_variables.scss 1:9 @import
node_modules/vuetify/src/components/VIcon/VIcon.sass 2:9 root stylesheet
Quick fix devDependencies
in package.json:
-
"sass": "~1.32.8"
-
"sass-loader": "10"
Translation key "dataTable.ariaLabel.****" not found in fallback
VDataTable 같은 컴포넌트를 사용할 때 위와 같은 경고가 브라우저에 출력된다면 Vuetify 플러그인 생성시 다음과 같이 초기화 한다:
import Vue from 'vue';
import Vuetify from 'vuetify/lib/framework';
import en from 'vuetify/lib/locale/en';
import ko from 'vuetify/lib/locale/ko';
Vue.use(Vuetify);
export default new Vuetify({
lang: {
locales: {en, ko},
current: 'en',
},
});
언어 변경은:
vue-i18n의 언어변경과 다르므로 각각 해줘야 한다: