Material Design for Bootstrap 4 (Vue version)を導入してみる
19761 ワード
Angular5で使ってたMDBootstrapのVueバージョンがあったので入れてみた。
ナビゲーションがMDBootstrapそのままだとvue-routerのrouter-linkが使えなくて、
コンポーネントを少しローカルで変更した。
完成した画面
- vue-cliの初期画面に上にナビゲーションくっ付けた
必要なパッケージのインストール
yarn add mdbootstrap bootstrap-vue classnames
yarn add @types/classnames --dev
テンプレートのコンポーネントをgit cloneで落としてくる
- Angular、Reactはパッケージ追加でいけるけど、Vueは何故かテンプレートをgit cloneしてプロジェクト作成するか、vue-cliでテンプレートを使って新規作成する事になってて、既存プロジェクトへの導入が不便だった
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
- mixins
mkdir ~/works/todo/src/mixins
cp ~/works/mdb/src/mixins/* ~/works/todo/src/mixins
main.tsにリップル効果のCSSをimport追加
src/main.ts
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');
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で遷移させるように変更
- activeのメニューの背景色を変える部分も動かなかったので変更した。App.vue側の/のルーティングにはexact属性を付けてある。
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>
yarn add mdbootstrap bootstrap-vue classnames
yarn add @types/classnames --dev
- Angular、Reactはパッケージ追加でいけるけど、Vueは何故かテンプレートをgit cloneしてプロジェクト作成するか、vue-cliでテンプレートを使って新規作成する事になってて、既存プロジェクトへの導入が不便だった
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
- mixins
mkdir ~/works/todo/src/mixins
cp ~/works/mdb/src/mixins/* ~/works/todo/src/mixins
main.tsにリップル効果のCSSをimport追加
src/main.ts
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');
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で遷移させるように変更
- activeのメニューの背景色を変える部分も動かなかったので変更した。App.vue側の/のルーティングにはexact属性を付けてある。
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>
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
src/main.ts
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');
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で遷移させるように変更
- activeのメニューの背景色を変える部分も動かなかったので変更した。App.vue側の/のルーティングにはexact属性を付けてある。
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>
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>
- activeのメニューの背景色を変える部分も動かなかったので変更した。App.vue側の/のルーティングにはexact属性を付けてある。
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>
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>
これで完成。
感想
- Angular5でMDBootstrap使った時はパッケージ追加してソース修正でやれたけど、Vue.jsでは面倒だった。
- App.vueをTypeScriptにしたら、エラーで動かなかった。型定義は用意されてないみたいなのでJsでやるしかない。
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
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
Vue.jsのマテリアルデザインのコンポーネントフレームワークは、Vuetifyというのが有名らしい。
そちらでやる方がいいんだろうか。
Vue.js専用っぽいから廃れちゃったら嫌だなと思っちゃうけど大丈夫なんだろうか。
作ったソース
Author And Source
この問題について(Material Design for Bootstrap 4 (Vue version)を導入してみる), 我々は、より多くの情報をここで見つけました https://qiita.com/uegaki-masaaki/items/ebaefbd8d7642332aea7著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .