Material Design for Bootstrap 4 (Vue version) 소개
내비게이션이 MDBootstrap 그대로라면 vue-router의 router-link를 사용할 수 없어,
구성 요소를 약간 로컬로 변경했습니다.
완성된 화면
필요한 패키지 설치
yarn add mdbootstrap bootstrap-vue classnames
yarn add @types/classnames --dev
템플릿의 구성 요소를 git clone으로 떨어뜨립니다.
yarn add mdbootstrap bootstrap-vue classnames
yarn add @types/classnames --dev
git clone https://github.com/mdbootstrap/Vue-Bootstrap-with-Material-Design.git mdb
템플릿에서 vue-cli로 만든 기존 프로젝트로 소스 복사
mkdir ~/works/todo/src/conponents/mdbootstrap
cp ~/works/mdb/src/components/* ~/works/todo/src/mdbootstrap
mkdir ~/works/todo/src/mixins
cp ~/works/mdb/src/mixins/* ~/works/todo/src/mixins
main.ts에 리플 효과의 CSS를 import 추가
src/main.tsimport Vue from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';
import './registerServiceWorker';
import 'bootstrap/dist/css/bootstrap.css';
import 'mdbootstrap/css/mdb.css';
+ import './components/mdbootstrap/Waves.css';
Vue.config.productionTip = false;
new Vue({
router,
store,
render: (h) => h(App),
}).$mount('#app');
App.vue 네비게이션을 MDBootstrap 네비게이션으로 변경
src/App.vue<template>
<div id="app">
<!--Navbar-->
<navbar position="top" class="indigo navbar-dark" name="ToDo" to="/" scrolling>
<navbar-collapse>
<navbar-nav>
<navbar-item to="/" active exact waves-fixed>Home</navbar-item>
<navbar-item to="/about" waves-fixed>About</navbar-item>
<navbar-item to="/tasks" waves-fixed>Tasks</navbar-item>
<!-- Dropdown -->
<dropdown tag="li" class="nav-item">
<dropdown-toggle tag="a" navLink color="indigo" waves-fixed>Dropdown</dropdown-toggle>
<dropdown-menu>
<dropdown-item>Action</dropdown-item>
<dropdown-item>Another action</dropdown-item>
<dropdown-item>Something else here</dropdown-item>
</dropdown-menu>
</dropdown>
</navbar-nav>
<!-- Search form -->
<form class="form-inline">
<mdinput type="text" placeholder="Search" aria-label="Search" label navInput waves waves-fixed/>
</form>
</navbar-collapse>
</navbar>
<div class="container">
<router-view/>
</div>
</div>
</template>
<script>
import Navbar from "@/components/mdbootstrap/Navbar.vue";
import NavbarItem from "@/components/mdbootstrap/NavbarItem.vue";
import NavbarNav from "@/components/mdbootstrap/NavbarNav.vue";
import NavbarCollapse from "@/components/mdbootstrap/NavbarCollapse.vue";
import Container from "@/components/mdbootstrap/Container.vue";
import Dropdown from "@/components/mdbootstrap/Dropdown.vue";
import DropdownItem from "@/components/mdbootstrap/DropdownItem.vue";
import DropdownMenu from "@/components/mdbootstrap/DropdownMenu.vue";
import DropdownToggle from "@/components/mdbootstrap/DropdownToggle.vue";
import drop from "@/mixins/drop";
import Mdinput from "@/components/mdbootstrap/MdInput.vue";
export default {
components: {
Navbar,
NavbarItem,
NavbarNav,
NavbarCollapse,
Container,
Dropdown,
DropdownItem,
DropdownMenu,
DropdownToggle,
Mdinput
},
mixins: [drop]
};
</script>
<style lang="scss">
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
.navbar .dropdown-menu a:hover {
color: inherit !important;
}
.fixed-top {
position: sticky;
}
</style>
Navbar의 구성 요소를 router-link로 전환하도록 변경
import Vue from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';
import './registerServiceWorker';
import 'bootstrap/dist/css/bootstrap.css';
import 'mdbootstrap/css/mdb.css';
+ import './components/mdbootstrap/Waves.css';
Vue.config.productionTip = false;
new Vue({
router,
store,
render: (h) => h(App),
}).$mount('#app');
src/App.vue
<template>
<div id="app">
<!--Navbar-->
<navbar position="top" class="indigo navbar-dark" name="ToDo" to="/" scrolling>
<navbar-collapse>
<navbar-nav>
<navbar-item to="/" active exact waves-fixed>Home</navbar-item>
<navbar-item to="/about" waves-fixed>About</navbar-item>
<navbar-item to="/tasks" waves-fixed>Tasks</navbar-item>
<!-- Dropdown -->
<dropdown tag="li" class="nav-item">
<dropdown-toggle tag="a" navLink color="indigo" waves-fixed>Dropdown</dropdown-toggle>
<dropdown-menu>
<dropdown-item>Action</dropdown-item>
<dropdown-item>Another action</dropdown-item>
<dropdown-item>Something else here</dropdown-item>
</dropdown-menu>
</dropdown>
</navbar-nav>
<!-- Search form -->
<form class="form-inline">
<mdinput type="text" placeholder="Search" aria-label="Search" label navInput waves waves-fixed/>
</form>
</navbar-collapse>
</navbar>
<div class="container">
<router-view/>
</div>
</div>
</template>
<script>
import Navbar from "@/components/mdbootstrap/Navbar.vue";
import NavbarItem from "@/components/mdbootstrap/NavbarItem.vue";
import NavbarNav from "@/components/mdbootstrap/NavbarNav.vue";
import NavbarCollapse from "@/components/mdbootstrap/NavbarCollapse.vue";
import Container from "@/components/mdbootstrap/Container.vue";
import Dropdown from "@/components/mdbootstrap/Dropdown.vue";
import DropdownItem from "@/components/mdbootstrap/DropdownItem.vue";
import DropdownMenu from "@/components/mdbootstrap/DropdownMenu.vue";
import DropdownToggle from "@/components/mdbootstrap/DropdownToggle.vue";
import drop from "@/mixins/drop";
import Mdinput from "@/components/mdbootstrap/MdInput.vue";
export default {
components: {
Navbar,
NavbarItem,
NavbarNav,
NavbarCollapse,
Container,
Dropdown,
DropdownItem,
DropdownMenu,
DropdownToggle,
Mdinput
},
mixins: [drop]
};
</script>
<style lang="scss">
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
.navbar .dropdown-menu a:hover {
color: inherit !important;
}
.fixed-top {
position: sticky;
}
</style>
Navbar의 구성 요소를 router-link로 전환하도록 변경
src/components/mdbootstrap/Navbar.vue
<template>
<nav :class="className" :is="tag">
- <a :href="href" class="navbar-brand">{{name}}
+ <router-link :to="to" class="navbar-brand">{{name}}
<img v-if="src" :src="src" :alt="alt"/>
- </a>
+ </router-link>
<button class="navbar-toggler" type="button" data-toggle="collapse" :data-target="target" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation" v-on:click="toggle">
<span class="navbar-toggler-icon"></span>
</button>
<slot></slot>
</nav>
</template>
<script>
//
//
//
//
//
//
//
//
//
//
//
//
//
//
import classNames from "classnames";
export default {
props: {
tag: {
type: String,
default: "nav"
},
expand: {
type: String,
default: "large"
},
position: {
type: String
},
- href: {
+ to: {
type: String
},
src: {
type: String
},
alt: {
type: String
},
name: {
type: String
},
target: {
type: String,
default: "#navbarSupportedContent"
},
scrolling: {
type: Boolean,
default: false
}
},
data() {
return {
className: classNames(
"navbar",
"navbar-dark",
this.expand === "small"
? "navbar-expand-sm"
: this.expand === "medium"
? "navbar-expand-md"
: this.expand === "large" ? "navbar-expand-lg" : "navbar-expand-lx",
this.position === "top"
? "fixed-top"
: this.position === "bottom" ? "fixed-bottom" : "",
this.scrolling ? "scrolling-navbar" : ""
),
scrolled: false,
toggleClicked: true
};
},
methods: {
toggle(e) {
if (this.toggleClicked) {
this.collapse.classList.toggle("show-navbar");
this.collapse.classList.remove("hide-navbar");
this.collapse.classList.toggle("collapse");
this.collapse.style.overflow = "hidden";
this.collapseOverflow = setTimeout(() => {
this.collapse.style.overflow = "initial";
}, 300);
this.toggleClicked = false;
} else {
this.collapse.classList.add("hide-navbar");
this.collapse.classList.toggle("show-navbar");
this.collapse.style.overflow = "hidden";
this.collapseOverflow = setTimeout(() => {
this.collapse.classList.toggle("collapse");
this.collapse.style.overflow = "initial";
}, 300);
this.toggleClicked = true;
}
},
handleScroll() {
if (window.scrollY > 100 && this.scrolled === false) {
this.$el.style.paddingTop = 5 + "px";
this.$el.style.paddingBottom = 5 + "px";
this.scrolled = true;
} else if (window.scrollY < 100 && this.scrolled === true) {
this.$el.style.paddingTop = 12 + "px";
this.$el.style.paddingBottom = 12 + "px";
this.scrolled = false;
}
}
},
mounted() {
this.collapse = this.$el.children.navbarSupportedContent;
this.collapse.classList.add("collapse");
},
created() {
window.addEventListener("scroll", this.handleScroll);
},
destroyed() {
window.removeEventListener("scroll", this.handleScroll);
}
};
</script>
<style scoped>
.scrolling-navbar {
transition: padding 0.5s;
}
.nav-item {
position: relative;
}
</style>
NavbarItem의 구성 요소를 router-link에서 전환하도록 변경
src/components/mdbootstrap/NavbarItem.vue<template>
<li :is="tag" :class="[className, {'ripple-parent': waves}]" @click="wave">
- <a :href="href" class="nav-link"><slot></slot></a>
+ <router-link :to="to" class="nav-link" :exact="exact"><slot></slot></router-link>
</li>
</template>
<script>
//
//
//
//
//
//
import classNames from "classnames";
import waves from "../../mixins/waves";
export default {
props: {
tag: {
type: String,
default: "li"
},
active: {
type: Boolean,
default: false
},
- href: {
+ to: {
type: String,
default: "#"
},
waves: {
type: Boolean,
default: true
},
wavesFixed: {
type: Boolean,
default: false
},
+ exact: {
+ type: Boolean,
+ default: false
+ }
},
data() {
return {
className: classNames("nav-item", this.active ? "active" : "")
};
},
mixins: [waves]
};
</script>
<style scoped>
+ .navbar.navbar-dark .breadcrumb .nav-item > .nav-link.router-link-active,
+ .navbar.navbar-dark .navbar-nav .nav-item > .nav-link.router-link-active {
+ background-color: rgba(255, 255, 255, 0.1);
}
</style>
이것으로 완성.
감상
<template>
<li :is="tag" :class="[className, {'ripple-parent': waves}]" @click="wave">
- <a :href="href" class="nav-link"><slot></slot></a>
+ <router-link :to="to" class="nav-link" :exact="exact"><slot></slot></router-link>
</li>
</template>
<script>
//
//
//
//
//
//
import classNames from "classnames";
import waves from "../../mixins/waves";
export default {
props: {
tag: {
type: String,
default: "li"
},
active: {
type: Boolean,
default: false
},
- href: {
+ to: {
type: String,
default: "#"
},
waves: {
type: Boolean,
default: true
},
wavesFixed: {
type: Boolean,
default: false
},
+ exact: {
+ type: Boolean,
+ default: false
+ }
},
data() {
return {
className: classNames("nav-item", this.active ? "active" : "")
};
},
mixins: [waves]
};
</script>
<style scoped>
+ .navbar.navbar-dark .breadcrumb .nav-item > .nav-link.router-link-active,
+ .navbar.navbar-dark .navbar-nav .nav-item > .nav-link.router-link-active {
+ background-color: rgba(255, 255, 255, 0.1);
}
</style>
ERROR in /Users/uwettie/works/todo-client/src/App.vue
43:18 Could not find a declaration file for module '@/mixins/drop'. '/Users/uwettie/works/todo-client/src/mixins/drop.js' implicitly has an 'any' type.
41 | import DropdownMenu from "@/components/mdbootstrap/DropdownMenu.vue";
42 | import DropdownToggle from "@/components/mdbootstrap/DropdownToggle.vue";
> 43 | import drop from "@/mixins/drop";
| ^
44 | import Mdinput from "@/components/mdbootstrap/MdInput.vue";
45 |
46 | export default {
Version: typescript 2.8.3, tslint 5.9.1
Vuetify
Vue.js의 머티리얼 디자인의 컴포넌트 프레임워크는 Vuetify라는 것이 유명하다.
그곳에서 하는 것이 좋을까.
Vue.js 전용이기 때문에 버려지면 싫다고 생각해 버리지만 괜찮을까.
만든 소스
Reference
이 문제에 관하여(Material Design for Bootstrap 4 (Vue version) 소개), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/uegaki-masaaki/items/ebaefbd8d7642332aea7
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
Reference
이 문제에 관하여(Material Design for Bootstrap 4 (Vue version) 소개), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/uegaki-masaaki/items/ebaefbd8d7642332aea7텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)