2020-01-08

Bootstrap 4 Navbar Style 調整

此文記錄在 Vue 架構下調整 Bootstrap 4 Navbar style,讓它與 Bootstrap 3 Navbar 相同。調整項目如下 :

1. 點選 Dropdown Menu 時不出現藍色外框 ( 似乎是 Safari 上才會出現 )。
2. 被滑鼠指標 hover 的 Dropdown Menu 項目顯示藍底白字。
3. Active Navbar 項目顯示深底色白字。
4. Dropdown Menu 增加陰影。

下圖是 Bootstrap 4 Navbar 在 Safari 上點選 Dropdown Menu 時的擷圖 :
下圖是調整後的 Navbar 擷圖 :

1. 安裝 sass-loader 與 node-sass
npm install sass-loader
npm install node-sass
2. 在 main.js 檔案所在資料夾新增檔案 bootstrap.scss,檔案內容如下 :
@import "~bootstrap/scss/functions";
@import "~bootstrap/scss/variables";

$dropdown-link-hover-color: $light;
$dropdown-link-hover-bg:    $blue;
.dropdown-item{
  padding: .2rem 1.5rem !important;
}

.nav-link.active {
  background:$gray-900;
}

@media (min-width: 576px) {
  .navbar {
    padding-top: 0px !important;
    padding-bottom: 0px !important;
  }
}
.navbar-nav .nav-item .nav-link {
  padding-top: 1rem !important;
  padding-bottom: 1rem !important;

  padding-left: 1rem !important;
  padding-right: 1rem !important;
}

.nav-item a.active.focus,
.nav-item a.active:focus,
.nav-item a.focus,
.nav-item a:active.focus,
.nav-item a:active:focus,
.nav-item a:focus {
    outline: 0;
    outline-color: transparent;
    outline-width: 0;
    outline-style: none;
    box-shadow: 0 0 0 0 rgba(0,123,255,0);
}

@import '~bootstrap/scss/bootstrap';
3. main.js 檔案調整如下 :
import Vue from 'vue'
import App from './App.vue'

import 'bootstrap'
import 'bootstrap/dist/css/bootstrap.min.css'
import './bootstrap.scss'

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
}).$mount('#app')

Vue 2.6 + Bootstrap 4

1. 首先安裝 vue-cli ( 安裝的版本是 4.1.2 )
npm install -g @vue/cli

2. 利用 vue-cli 建立 project
vue create my-vue-project
出現 present 選項時直接選擇預設選項 default (babel, eslint),完成之後會建立一個 my-vue-project 資料夾,在資料夾內執行 npm run serve 之後用瀏覽器連線至 http://localhost:8080/,成功的話可以看到 welcome to vue 的預設畫面。

3. 安裝 bootstrap,在 my-vue-project 資料夾執行 : ( 安裝的版本是 4.4.1 )
npm install bootstrap

4. 安裝 jquery 及 popper : (jquery 版本是 3.4.1, popper.js 版本是 1.16.0
npm install jquery
npm install popper.js

5. 在 vue 上測試 bootstrap :
a. 首先在 main.js import bootstrap,main.js 檔案修改如下 :
import Vue from 'vue'
import App from './App.vue'

//新增 bootstrap import
import 'bootstrap'
import 'bootstrap/dist/css/bootstrap.min.css'

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
}).$mount('#app')
b. 在 components 資料夾內新增加一個 vue component,檔名為 BootstrapTest.vue,檔案內容如下 :
<template>
  <div class="container-fluid">
    <!-- Modal -->
    <div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
      <div class="modal-dialog" role="document">
        <div class="modal-content">
          <div class="modal-header">
            <h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
            <button type="button" class="close" data-dismiss="modal" aria-label="Close">
              <span aria-hidden="true">&times;</span>
            </button>
          </div>
          <div class="modal-body">
            ...
          </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
            <button type="button" class="btn btn-primary">Save changes</button>
          </div>
        </div>
      </div>
    </div>

    <!-- Button Test -->
    <div class="card">
      <div class="card-body">
        <ul class="list-group list-group-flush">
          <li class="list-group-item">      
            <h5 class="card-title">Button Test</h5>
            <button type="button" class="btn btn-primary">Primary</button>
            <button type="button" class="btn btn-secondary">Secondary</button>
            <button type="button" class="btn btn-success">Success</button>
            <button type="button" class="btn btn-danger">Danger</button>
            <button type="button" class="btn btn-warning">Warning</button>
            <button type="button" class="btn btn-info">Info</button>
            <button type="button" class="btn btn-light">Light</button>
            <button type="button" class="btn btn-dark">Dark</button>
            <button type="button" class="btn btn-link">Link</button>
          </li>
          <li class="list-group-item">
            <h5 class="card-title">Dropdowns / Input</h5>
            <div class="btn-group">
              
                <div class="row">
                  <div class="col-sm-6">
                    <button type="button" class="btn btn-danger dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                      Action
                    </button>
                    <div class="dropdown-menu">
                      <a class="dropdown-item" href="#">Action</a>
                      <a class="dropdown-item" href="#">Another action</a>
                      <a class="dropdown-item" href="#">Something else here</a>
                      <div class="dropdown-divider"></div>
                      <a class="dropdown-item" href="#">Separated link</a>
                    </div>

                  </div>
                  <div class="col-sm-6">
                    <div class="input-group">
                      <div class="input-group-prepend">
                        <span class="input-group-text" id="basic-addon1">@</span>
                      </div>
                      <input type="text" class="form-control" placeholder="Username" aria-label="Username" aria-describedby="basic-addon1">
                    </div>

                  </div>
                </div>
              

            </div>
          </li>
          <li class="list-group-item">
            <h5 class="card-title">Modal</h5>
            <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal">
              Launch demo modal
            </button>
          </li>
          <li class="list-group-item">
            <h5 class="card-title">Toast</h5>
            <button type="button" class="btn btn-primary" v-on:click="showToastr">
              Show Toast
            </button>
          </li>
        </ul>
      </div>
    </div>

    <!-- Toast -->
    <div id="toast" class="toast" style="position: absolute; top: 10px; right: 10px; display:none;">
      <div class="toast-header">
        <strong class="mr-auto">Bootstrap</strong>
        <small class="text-muted">11 mins ago</small>
        <button type="button" class="ml-2 mb-1 close" data-dismiss="toast" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="toast-body">
        Hello, world! This is a toast message.
      </div>
    </div>
  </div>
</template>

<script>
import $ from 'jquery'
export default {
  methods: {
    showToastr: function () {
      $('#toast').toast('show')
      $('#toast').show()
    }
  },
  mounted(){
    $('.toast').toast({
      autohide:false
    })
  }
}
</script>

c. 把預設的 HelloWorld.vue 替換成 BootstrapTest.vue,App.vue 檔案修改如下 :
<template>
  <div id="app">
    <!-- <img alt="Vue logo" src="./assets/logo.png"> -->
    <!-- <HelloWorld msg="Welcome to Your Vue.js App"/> -->
    <BootstrapTest/>
  </div>
</template>

<script>
// import HelloWorld from './components/HelloWorld.vue'
import BootstrapTest from './components/BootstrapTest.vue'

export default {
  name: 'app',
  components: {
    BootstrapTest
  }
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>
此時瀏覽器應該能自動 reload 並顯示畫面 :
此時可以測試看看各元件顯示,Modal/Toast 運作是否正常,都能運作的話那 Bootstrap 應該是成功 import 了。