《從零構建前後分離的web專案》:前端完善 – 手把手教你快速構建網站佈局

莊文達發表於2019-03-02

添磚加瓦 – 手把手教你快速構建網站佈局

專案地址

本章原始碼地址

文章地址

本文為方便講述重構去除了 Element、vux 庫,用了最近比較火的 bulma 輕量、快捷、易讀。

2018-11-22-15.58.03.gif

專案截圖

Layout and Components

design_web_layout.png

Layout

首先,似上圖,我們思考把一個小型網站拆成三部分:頁頭(Header)、內容(Content)、頁尾(Footer) 這幾乎每個網站內都必須有的,通常把萬年不變的:頁頭(Header)、頁尾(Footer) 製作成 Layout 方便通用。

Components

再把內容(Content)根據業務進行拆分成 元件(Components)

1A8A610A-E0AF-4794-96B0-D38B0C39D585.jpg

如上圖:Header 和 Content :Header其實沒有拆分的必要,沒有可以重用的元件,而 Conntent 是必須要拆分的佈局元素。因為動態網站 Conntent 隨著內容的變化而變化,內容多,可重用的東西的概率越高,需要把能重用的東西提煉出來

1、節省程式碼、提高程式碼閱讀性

2、便於修改 (比如更新廣告)

開始寫程式碼

接著我們的 第二章上傳的原始碼 開始,基於它繼續完善小網站佈局和元件化。

值得一提的是:本系列教程一章跟隨一章並且每一章可以獨立執行,章與章之間完美銜接,沒有 “突然出現” 的程式碼段。不會給新手無從下手的感覺,如果那你對程式碼陌生,那你該認真翻翻往期文章了。你可以基於上一章逐步寫程式碼,也可以下載本章簡單預覽程式碼。

  • 引入 bulma 樣式 CDN
vim new-bee/index.html
複製程式碼

 <!-- font -->
  <link href="//cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
  <!-- css -->
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.0/css/bulma.min.css">

複製程式碼
  • 新建 Layout 目錄
vim new-bee/src/renderer/components/layout
複製程式碼
  • Layout 目錄下建立 Header.vue 模板元件

這個元件專門寫頭部的內容,最好配合柵格儘可能寫出簡單的響應式元件

<template>

    <div id="bee-header"   element-loading-text="正在努力請求github..." element-loading-background="rgba(0, 0, 0, 0.8)">
        <!-- 遮罩 -->
        <div  :class="  loading ? `modal is-active` : `modal` " style="background-color: #ffffff36">
                < img src="https://img.actd.tw/images/2018/11/17/ezgif-4-05f4bba41fef.gif" style="width: 300px" alt="">
        </div>

        <div class="is-underline ">
    <div class="container">
      <nav class="navbar ">
        <div class="navbar-brand">
          <a class="navbar-item"   >
            < img src="https://img.actd.tw/images/2018/11/17/bee.png" alt="Bulma: a modern CSS framework based on Flexbox" width="92" height="28">
          </a >
          <div class="login-before is-hidden-mobile" style="padding-top: 5px;">
            <a class="navbar-item is-hidden-desktop" href=" " target="_blank">
              <span class="icon" style="color: #333;">
                <i class="fa fa-lg fa-github is-size-2"></i>
              </span>
            </a >
          </div>
          <div class="navbar-item is-hidden-desktop ">
             <div class="field has-addons"  ><div class="control" ><input   type="input" class="input" name="email" placeholder="搜尋一下" required="required" style="height: 36.4px;width:130px"><input   type="hidden" name="redirect" id="name" value="/fr/#thanks"></div><div class="control"  ><input  type="submit" class="button is-warning" value="GO"></div></div>
          </div>
           
          <div class="navbar-burger burger" data-target="navMenuDocumentation" >
            <span></span>
            <span></span>
            <span></span>
          </div>
        </div>

        <div id="navMenuDocumentation" class="navbar-menu">
          <div class="navbar-start">
            <div class="navbar-item has-dropdown is-hoverable">
              <a class="navbar-link  is-active">
                發現
              </a >
              <div class="navbar-dropdown ">
                <a class="navbar-item " type="收藏集">
                  收藏集
                </a >
                <a class="navbar-item" type="徽章">
                  徽章
                </a >
                <a class="navbar-item " type="排名">
                  排名
                </a >
                <a class="navbar-item "  type="職場生活">
                  職場生活
                </a >
              </div>
            </div>
            <a class="navbar-item " href="https://bulma.io/expo/">
              <!--<span class="bd-emoji">⭐️</span>-->
              專欄
            </a >
            <a class="navbar-item " href="https://bulma.io/expo/">
              <!--<span class="bd-emoji">⭐️</span>-->
              聊天
              <!-- 很多人不知道幹什麼。。。 -->
            </a >
            <a class="navbar-item " href="https://bulma.io/expo/">
              <!--<span class="bd-emoji">⭐️</span>-->
              面經
            </a >
            <router-link class="navbar-item " to="/book">
              <!--<span class="bd-emoji">❤️</span>-->
              書籍
            </router-link>
          </div>

          <div class="navbar-end">
            <div class="login-before" style="padding-top: 5px;">
              <!-- pc -->
              <a class="navbar-item is-hidden-desktop-only" href="https://github.com/pkwenda/my-bbs" target="_blank">
                <span class="icon" style="color: #333;">
                  <i class="fa fa-lg fa-github is-size-2"></i>
                </span>
              </a >
            </div>

            <div class="navbar-item is-hidden-mobile ">
               <div class="field has-addons"  ><div class="control" ><input   type="input" class="input" name="email" placeholder="搜尋一下" required="required" style="height: 36.4px;"><input   type="hidden" name="redirect" id="name" value="/fr/#thanks"></div><div class="control"  ><input  type="submit" class="button is-warning" value="GO"></div></div>
            </div>

            <div class="navbar-item is-hidden-mobile ">
              <!--<span class="icon is-medium">-->
              <i class="iconfont icon-tixing"></i>
              <!--</span>-->
            </div>

               
            <div class="navbar-item has-dropdown is-hoverable">
              <a class="is-hidden-mobile"  target="_blank">          
              < img src="https://avatars2.githubusercontent.com/u/14212375?s=400&u=dc515636befebfda36501309d1cdc087ee31d500&v=4" class=" header-avatar img-circle "
                                  style="margin-top: 10px">
              </a >
              <div class="navbar-dropdown ">
                <a class="navbar-item " type="收藏集">
                  寫文章
                </a >
                <a class="navbar-item" type="徽章">
                  設定
                </a >
                <a class="navbar-item " type="排名">
                  退出
                </a >
              </div>
            </div>   
            
 
           
            <div class="login-before">
              <div class="navbar-item">
                <div class="field is-grouped">
                 
                  <p class="control">
                    <a class="button is-warning"  v-show="!isLogin"  >
                      <strong>登入</strong>
                    </a >

                  </p >

                </div>
              </div>
            </div>
          </div>
        </div>
      </nav>
    </div>
  </div>
    </div>
</template>


<script>
export default {
  name: "BeeHeader",

  data() {
    return {
      popupShow: false,
      isLogin: false,
      user: {},
      loading: false,
      userInfo: {}
    };
  },
  created() {},
  destroyed() {},
  mounted() {},
  methods: {}
};
</script>

<style scoped>
.img-circle {
  -webkit-border-radius: 50%;
  -moz-border-radius: 50%;
  border-radius: 50%;
}
</style>

複製程式碼

什麼樣式可以寫在 .vue 檔案中

上文的比較熟悉的程式碼是讓我們的頭像變圓的程式碼段

<style scoped>
.img-circle {
  -webkit-border-radius: 50%;
  -moz-border-radius: 50%;
  border-radius: 50%;
}
複製程式碼
  • 效果
-2018-11-22-18.45.39.png

這裡我偷了個懶,剛好可以說一說,對於如此通用的樣式,侷限在 .vue檔案中,並且以 scoped 標示,宣判了它無法複用的事實,任何模組想用這個樣式,都需要複製一份,顯然是不規範的,我們通常還會建立通用的 css 檔案進行管理,大型專案 css 管理規範將更加嚴格、規範的樹級結構,具體就看 CTO 的想法了。

根據喜好選擇如何佈局

按需引入

vim new-bee/src/renderer/components/HelloWorld.vue
複製程式碼
<template>
    <div>
   <Header></Header>
     <!--<div class="container"> </div>-->
    </div>
</template>

<script>
import Header from "@/components/layout/Header";
export default {
  name: "NewBeeIndex",
  components: { Header },
  data() {
    return {};
  },

  destroyed() {},
  mounted() {},
  methods: {},
  watch: {}
};
</script>
複製程式碼

缺點是要一個一個引入,但優點是程式碼可讀性高

全域性引入

  • App 主入口
vim  new-bee/src/renderer/App.vue
複製程式碼
  • 引入
<template>
  <div id="app">
     <Header></Header>
    <!-- < img src="./assets/logo.png"> -->
    <router-view/>
  </div>
</template>

<script>
import Header from "@/components/layout/Header";
export default {
  name: "App",
  components: { Header }
};
</script>

<style>
</style>


複製程式碼
  • 檢視效果
-2018-11-22-18.38.31.png

基於 webpack 爸爸的熱部署,我們無需重新整理瀏覽器,webpack 偷偷用 ws 更新了我們的內容。似乎很完美,但是也許大家發現了一個問題,我們通過瀏覽器渲染出來的 dom 就可以看到::

-2018-11-22-19.08.58.md.png

我們在主 APP 入口引入了頭部佈局, App.vue 是緊臨 元素的正文元素,而這個程式所有頁面、子路由全部都是 App.vue 入口的子集,說明全域性引入佈局會存在如下問題:

1、這個專案所有的專案都一定會帶上 Header 元件渲染的內容
2、而且會影響在下期 《效能優化》中講的 webpack 按需載入的效能。

當然可以再 Header 元件上書寫邏輯條件,過濾指定的路由,但會破壞專案的易讀性,難以維護

我個人是比較推薦第一種:按需引入的方式。

繼續佈局

  • 照貓畫虎寫好 Footer
vim new-bee/src/renderer/components/layout/Footer.vue
複製程式碼
<template>
    <footer class="footer footer-light-medium " style="padding-bottom: 20px;padding-top: 20px;">
    <div class="container">
        <div class="columns">
            <!-- Column -->
            <div class="column is-4">
                <div class="mb-20">
                    < img class="small-footer-logo" src="https://img.actd.tw/images/2018/11/17/bee.png" alt="">
                    <div class="footer-description pt-10">
                        new bee 是一個為開發者提供的專注於技術分享的開源社群,所有原始碼均可在 github 上找到,希望對廣大開發者有所幫助。
                    </div>
                </div>
                <div>
                    <span class="moto">喜歡專案可以點贊支援  <a href="https://github.com/pkwenda/new-bee" target="_blank">
                            <span class="icon"><i class="fa fa-github"></i></span>
                        </a >.</span>
                    <div class="social-links mt-20">
                         
                        
                    </div>
                </div>
            </div>
            <!-- Column -->
            <div class="column is-6 is-offset-2">
                <div class="columns">
                    <!-- Column -->
                    <div class="column">
                        <ul class="footer-column">
                            <li class="column-header">
                                Links
                            </li>
                            <li class="column-item"><a href="https://github.com/pkwenda/new-bee">Home</a ></li>
                            <li class="column-item"><a href="https://cssninja.io/themes">Blog</a ></li>
                            <li class="column-item"><a href="https://github.com/pkwenda/new-bee/wiki">Wiki</a ></li>
                        </ul>
                    </div>
                    <!-- Column -->
                    <div class="column">
                        <ul class="footer-column">
                            <li class="column-header">
                                Ressources
                            </li>
                            <li class="column-item"><a href="https://cssninja.io/help">Help center</a ></li>
                            <li class="column-item"><a href="https://cssninja.io/blog">Blog</a ></li>
                            <li class="column-item"><a href="https://cssninja.io/help/rules">Rules</a ></li>
                        </ul>
                    </div>
                    <!-- Column -->
                    <div class="column">
                        <ul class="footer-column">
                            <li class="column-header">
                                Terms
                            </li>
                            <li class="column-item"><a href="https://cssninja.io/help/terms/licenses/personal">Personal</a ></li>
                            <li class="column-item"><a href="https://cssninja.io/help/terms/licenses/developer">Developer</a ></li>
                            <li class="column-item"><a href="https://cssninja.io/help/terms/service">Terms of Service</a ></li>
                        </ul>
                    </div>
                </div>
            </div>
        </div>
    </div>
</footer>
</template>


<script>
export default {
  name: "Footer",
  data() {
    return {};
  },
  created() {},
  destroyed() {},
  mounted() {

  },
  methods: {}
};
</script>

複製程式碼

別忘了在 HelloWorld 引入一下

  • 看看效果
-2018-11-22-19.46.28.png
  • 看起來效果還不錯,接下來是 Content(正文)部分
vim new-bee/src/renderer/components/layout/Content.vue
複製程式碼
<template>

      <div class="container" style="height:700px">
        <h1  >部落格列表</h1>
          <article class="column is-3"   v-for="blog in blogs" v-bind:key="blog"> 
            <a   class="bd-article-image is-bootstrap" >
            <span class="bd-article-overlay"></span>
            <span class="bd-article-icon">
                <i class="fa fa-tag"></i>
            </span>
            <strong class="bd-star-icon" ><i class="fa fa-star"></i> <span style="font-size: 1rem">&nbsp;{{blog.commendCount}}</span></strong>
            <strong class="bd-article-info">
                <span>
                <time class="bd-article-date" datetime="2017-10-09T00:00:00+00:00">
                    {{blog.tag}}
                </time>
                <strong class="bd-article-title">
                    {{blog.title}}
                </strong>
                </span>
            </strong>
            </a>
        </article>
      </div>
</template>


<script>
let article = { tag: "java", title: "java", commendCount: 0 };
export default {
  name: "Footer",
  data() {
    return {
      blogs: [
        article,
        article,
        article,
        article,
        article,
        article,
        article,
        article
      ]
    };
  },
  created() {},
  destroyed() {},
  mounted() {},
  methods: {}
};
</script>

<style scoped>
.bd-article-image.is-bootstrap {
  background-color: #6f5499;
}
.bd-article-image {
  background-color: #00d1b2;
  display: block;
  height: 240px;
  margin-left: auto;
  margin-right: auto;
  position: relative;
  text-align: center;
}

.bd-star-icon {
  font-size: 19.2px;
  font-size: 1.2rem;
  color: #0a0a0a;
  opacity: 0.25;
  bottom: 10px;
  left: 30px;
  position: absolute;
  -webkit-box-align: center;
  -ms-flex-align: center;
  -webkit-align-items: center;
  align-items: center;
  display: -webkit-box;
  display: -ms-flexbox;
  display: -webkit-flex;
  display: flex;
  -webkit-box-pack: center;
  -ms-flex-pack: center;
  -webkit-justify-content: center;
  justify-content: center;
}
.bd-article-icon,
.bd-article-info {
  bottom: 0;
  left: 0;
  position: absolute;
  right: 0;
  top: 0;
  -webkit-box-align: center;
  -ms-flex-align: center;
  align-items: center;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-pack: center;
  -ms-flex-pack: center;
  justify-content: center;
}
.bd-article-info {
  padding: 20px;
}
a strong {
  color: currentColor;
}
.bd-article-date {
  color: rgba(0, 0, 0, 0.5);
  display: block;
}
.bd-article-title {
  color: white;
  display: block;
  font-size: 1.8rem;
  font-weight: 700;
  line-height: 1.25;
  padding: 0 20px;
}
.bd-article-icon {
  color: #0a0a0a;
  opacity: 0.25;
}
h1 {
  text-align: center;
  font-size: 30px;
}

.column.is-3,
.column.is-3-tablet {
  -webkit-box-flex: 0;
  -ms-flex: none;
  flex: none;
  width: 25%;
  float: left;
}
</style>


複製程式碼
  • 看看效果

    -2018-11-22-22.31.22.md.png
  • HelloWorld.vue 程式碼看起來是這樣的

-2018-11-22-19.52.42.png

還算看得過去,我們繼續參照圖二

design_web_layout.png

為 Content 制定 AD(廣告) 元件。

vim new-bee/src/renderer/components/common/AD.vue
複製程式碼

<template>
     
             <div class="ad"><h1>澳門皇家賭場上線啦</h1></div>
    
</template>

<script>
export default {
  name: "AD",

  data() {
    return {};
  },
  destroyed() {},
  mounted() {},
  methods: {},
  watch: {}
};
</script>
 <style   scoped>
.ad {
  width: 150px;
  height: 180px;
  background-color: #ececec;
  position: fixed;
  right: 30px;
  top: 80px;
}
</style>
 
複製程式碼
  • 別忘了在 Content.vue 引入一下
...
<AD></AD>
...
import AD from "@/components/common/AD";
export default {
  name: "Content",
  components: { AD },
  ...
  }
複製程式碼
  • 看下效果
2018-11-22-22.45.30.gif
  • 對比一下我們之前 sketch 畫的草圖
design_web_layout.png

差不多完成了我們初步的構思

總結

至此頁面佈局和元件的引用大概講述完了,相信大家可以舉一反三,寫好自己的小網站,其中更復雜的巢狀方式不再講了,大家直接去看專案吧。

作者的話

其實這個專案老早就是今天這個樣子了,只是一直在下班後寫教程,耽誤了進度,寫教程也不是複製貼上,首先要保障準確性,而不是刪刪改改草草了事,想寫出好的教程只能換位思考,以小白的身份,從 CLI 、頭到尾一行程式碼一行程式碼堆上去。相信寫到現在一部分人對前端也有了一些新的認識,前端已經不是引入一個 JQuery.js、Vue.js 去寫指令碼的時代了 (Angular 已經有 IOC 了),作為一個後端,前端初步就帶大家玩到這裡了,Electron 以後大家直接去看專案吧,沒什麼好講的,下一章會單獨講解一章終章《前端效能優化》大概涉及: webpack按需載入 、gZip、CDN、沒錢買伺服器如何除錯小程式等 Tips ,本教程全棧方向的,下一步還有後端微服務、訊息佇列、docker、docker-compose/rancher 模擬叢集、運維 等幾個點,以後會加快進度的,儘量新年之前寫完全部內容。

關於回覆

新發布的文章前兩天其實我都會去掘金大家的評論我都會看,但是你能想象得到嗎,掘金訊息提醒沒有分類 :點贊 | 回覆 |

-2018-11-22-23.10.17.png
-2018-11-22-23.12.50.png

大家的訊息就是在無盡的滾動條中石沉大海了,之後也就懶得看了,評論找不到我可以去 github的issues 各個文章下面留言提問,或者勘誤,為後人鋪路,新文章也會先發到這裡一天請大家勘誤,star 不 star 無所謂了,謝謝大家。

專案地址

本章原始碼地址

文章地址

往期文章

序 – 開源的意義

開篇 – 縱觀WEB歷史演變

探究 – 深入聊聊前後分離架構

準備 – 前端了解過關了嗎?前端基礎架構和技術介紹

實戰 – 5分鐘快速構建規範的前端專案骨架

實戰 – 欲善其事先利其器 繼續打磨前端架構

完善 – 手把手教你快速構建網站佈局

下一章《前端終章-前端效能優化與上線》

相關文章