国产成人精品无码青草_亚洲国产美女精品久久久久∴_欧美人与鲁交大毛片免费_国产果冻豆传媒麻婆精东

15158846557 在線咨詢 在線咨詢
15158846557 在線咨詢
所在位置: 首頁 > 營銷資訊 > 網(wǎng)站運營 > 如何用 Vue.js 實現(xiàn)一個建站應(yīng)用

如何用 Vue.js 實現(xiàn)一個建站應(yīng)用

時間:2023-07-08 11:12:01 | 來源:網(wǎng)站運營

時間:2023-07-08 11:12:01 來源:網(wǎng)站運營

如何用 Vue.js 實現(xiàn)一個建站應(yīng)用:
隨著互聯(lián)網(wǎng)飛速發(fā)展,越來越多的傳統(tǒng)服務(wù)搬到了線上,商家急需一個官網(wǎng)介紹自己的產(chǎn)品,提高知名度。因此 “建站” 成為了一種剛需。本文就如何用 Vue.js 實現(xiàn)一個建站應(yīng)用提供了解決思路。
作為前端工程師,相信大家都寫過不少網(wǎng)站和應(yīng)用,我把網(wǎng)站簡單的分為 “表現(xiàn)型” 和 “操作型”。表現(xiàn)型可以是一個產(chǎn)品介紹網(wǎng)站,而操作型的典型代表是管理后臺。不久前有機會參與一個建站項目的設(shè)計與開發(fā),它屬于操作類型網(wǎng)站但需要更深一層的抽象,它是一個 “創(chuàng)建網(wǎng)站的網(wǎng)站”。本文嘗試基于 Vue.js 框架設(shè)計實現(xiàn)這樣一個應(yīng)用,用戶通過拖拽模塊就可以建站。希望通過本文的介紹,能夠帶給大家不一樣的視角。

需求

獲取需求是開始項目的第一步。一般來說建站工具大多提供以下功能:

需求分析

我們在開始動手之前可以先分析一下需求。

從需求中可以提取到幾個關(guān)鍵詞:“模板”、“主題色”、“模塊”、“頁面”、“分欄” 。明確這些關(guān)鍵詞的意義將有助于我們接下來的設(shè)計。

網(wǎng)站的數(shù)據(jù)表示

那么問題來了,我們應(yīng)該如何存儲我們的網(wǎng)站呢?換句話說,存在數(shù)據(jù)庫里面的是一個怎樣的數(shù)據(jù)結(jié)構(gòu)?是一個包含 HTML 的超大字符串嗎?不急,基于上面的關(guān)鍵詞定義我們可以總結(jié)一下:

  1. 一個網(wǎng)站包含幾個頁面,一個頁面包含幾個區(qū)塊,一個區(qū)塊包含幾個模塊??梢钥闯鲞@是一個樹形結(jié)構(gòu),見下圖。






用 JSON 格式可以把它表示成

{ "id": 1, "name": "xxx公司" "type": "site", "children": [{ "type": "page", "name": "首頁", "children": [{ "type": "section", "name": "公司簡介", "children": [{ "type": "paragraph" }, { "type": "carousel" }] }] }]}
  1. 那么模塊就是樹中的葉子節(jié)點,需求中要求模塊可以配置,我們可以把配置分為兩部分:包含的內(nèi)容(content)和設(shè)置(config)。舉例來說,輪播模塊中 content 存放的是幾張圖片的 URL,config 可以是輪播切換的動畫效果、是否開啟自動播放等設(shè)置。
  2. 與模塊一樣,site、page、section 都是樹中的節(jié)點,都可以根據(jù)需要在節(jié)點上增加 content 和 config。只不過對于這幾類節(jié)點來說 content 其實就是 children,只有 config 屬性。
  3. 主題色是網(wǎng)站節(jié)點的配置項,可以在site.config中增加themeColor屬性來表示。
  4. 如何支持手持設(shè)備呢?前面說到模板定義了板塊的橫向占比,所以在板塊的 config 屬性中可以配置該板塊在不同尺寸的橫向占比。若采用 Bootstrap 的 12 欄柵格系統(tǒng)的話,可以很方便的通過設(shè)置 class 來達到目的。例如某個板塊的 config 中class="col-xs-12 col-sm-6 col-md-3"表示該板塊在手機下橫向占 100%、平板占 50%、PC 占 25%。






綜上,一個網(wǎng)站可以完整的表示為一個樹形 JSON。該樹中包含了所有頁面、板塊、模塊的內(nèi)容和配置。

從數(shù)據(jù)到網(wǎng)站

我們已經(jīng)有了網(wǎng)站的數(shù)據(jù)表示,那么下一個問題是如何從數(shù)據(jù)中渲染出網(wǎng)站呈現(xiàn)給用戶呢?其實我們只要想辦法渲染這棵 JSON 樹就行了。

兩步走:

  1. 編寫每個節(jié)點的代碼,每個節(jié)點接受node屬性和themeColor
  2. 遍歷 JSON 樹,在對應(yīng)位置渲染對應(yīng)的節(jié)點(即父子節(jié)點的包含關(guān)系)
第一步是個 “體力活”,此處以單段文字模塊為例:

<!-- Paragraph.vue --><template> <div> <h1 :style="{color: themeColor}">{{node.content.title}}</h1> <small v-if="node.config.showSubTitle">{{node.content.subTitle}}</small> <p>{{node.content.detail}}</p> </div></template><script>export default { name: 'paragraph', props: ['node', 'themeColor']}</script>完成所有節(jié)點代碼編寫之后,第二步,我們需要寫一個類似于 “renderer” 的組件來遞歸的渲染 JSON 樹?;舅悸肥窃摻M件先渲染自己,然后渲染自己的后代,每個后代也重復(fù)此渲染過程,如此渲染整棵樹。

這里需要根據(jù)節(jié)點的type屬性也就是一個 String 來獲取對應(yīng)的組件定義。幸運的是 Vue.js 中已經(jīng)有這樣的動態(tài)組件Component,此組件的is屬性接受一個 String。由此我們的 render 組件可以這樣寫:

<!-- render.vue --><tempplate> <component :is="node.type" :node="node" :theme="themeColor"> <render v-for="child in node.children" :key="child.id" :node="child" :theme="themeColor" /> </component></tempplate><script>// 導(dǎo)入JSON 樹中所涉及的所有節(jié)點import Page from './Page.vue'import Section from './Section.vue'import Paragraph from './Paragraph.vue'export default { name: 'render', props: ['node', 'themeColor'], components: { Page, Section, Paragraph }}</script>注:若 Vue.js 沒有提供動態(tài) Component 組件,我們也可以利用 Vue.js 中的createElement方法自己實現(xiàn)該組件,詳見此 gist(https://gist.github.com/github-libra/7ba6eb53efd5cccdd3828030708c4297)。

至此,我們已經(jīng)設(shè)計了網(wǎng)站的數(shù)據(jù)表示,以及從數(shù)據(jù)到頁面的渲染。那么這棵 JSON 樹從何而來呢?

編輯與保存

要創(chuàng)建一個網(wǎng)站,用戶在后臺會經(jīng)歷選擇樣板站、調(diào)整色調(diào)、拖拽模塊、編輯模塊內(nèi)容和配置、保存等操作。值得注意的是,此處用戶選擇的樣板站跟文章開頭的模板定義有些差別。如果說模板是網(wǎng)站的骨架的話,那樣板站是填充了初始數(shù)據(jù)(默認色調(diào)、板塊中包含的模塊以及模塊的默認內(nèi)容)的模板。

從數(shù)據(jù)的角度來看,可以更清楚地看到這些步驟是如何逐步生成這棵樹的。

界面操作影響數(shù)據(jù)選擇模板(樣板站)該模板定義的初始樹,包含默認的色調(diào)和模塊選擇色調(diào)更新site.config.themeColor拖拽模塊到區(qū)域中在對應(yīng)的section.children的數(shù)組中 push 一個組件節(jié)點在區(qū)域中排序模塊在對應(yīng)的section.children的數(shù)組中重新設(shè)置組件節(jié)點的 index編輯模塊內(nèi)容和配置更新對應(yīng)模塊的 content 和 config 中的屬性保存網(wǎng)站把 JSON 樹存入數(shù)據(jù)庫持久化

既然選擇了 Vue.js,我們可以選擇官方推薦的 Vuex(vuex.vuejs.org/en/)來管理狀態(tài)。

首先創(chuàng)建一個 Vuex 實例,該實例包含一個 site 對象和一些對節(jié)點的操作:

// store.jsimport Vue from 'vue'import Vuex from 'vuex'Vue.use(Vuex)const store = new Vuex.Store({ state: { site: {} }, mutations: { changeThemeColor () {}, addModule () {}, sortModule () {}, removeModule () {}, updateModule () {} }, actions: { getSite () {}, saveSite () {} }})理論上有了這些方法我們已經(jīng)可以從通過程序更新這棵樹了,但作為編輯后臺,我們還要提供一些界面上的入口讓用戶來編輯這棵樹。

也就是說,我們需要在編輯后臺渲染一個可以編輯的網(wǎng)站,在網(wǎng)站上線后渲染一個只讀的網(wǎng)站,即同一個 JSON 樹需要渲染兩次。因為 renderer 是根據(jù)節(jié)點的 type 來渲染對應(yīng)的組件的,所以對于編輯后臺我們需要給每個節(jié)點取另一個 type,比如統(tǒng)一加一個前綴edit-。例如 Paragraph 這個組件的編輯組件可以編寫如下:

<!-- EditParagraph.vue --><template> <edit-wrapper> <paragraph :node="node" :themeColor="themeColor" /> </edit-wrapper></template><script>// EditWrapper提供統(tǒng)一的編輯入口,內(nèi)部仍需要渲染一次 Paragraph 便于實時預(yù)覽編輯結(jié)果import EditWrapper from './EditWrapper.vue'import Paragraph from './Paragraph.vue'import { mapMutations } from 'vuex'export default { name: 'edit-paragraph', props: ['node', 'themeColor'], methods: { ...mapMutations(['updateModule']) }}</script>用戶可以通過這個組件的界面入口編輯 Paragraph 這個模塊(此處略去edit-wrapper的實現(xiàn),事實上組件的編輯可以通過彈窗加表單實現(xiàn),也可以是更方便的 inline editing )。

如此一來,每個模塊都有一個對應(yīng)的編輯模塊,在兩次渲染的時候便存在一個轉(zhuǎn)換的過程。假設(shè)在數(shù)據(jù)庫中存的是只讀的樹,那么在編輯后臺獲取到該樹時需要轉(zhuǎn)換成可編輯樹從而渲染成帶有編輯入口的網(wǎng)站,在保存時則需要轉(zhuǎn)換成只讀樹保存。轉(zhuǎn)換的過程其實很簡單,把每個節(jié)點的 type 屬性增加或刪除前綴即可。

拖拽功能

我們選用拖拽的方式在區(qū)域中加入模塊以及排序模塊。有很多開源的庫幫我們做了拖拽的實現(xiàn),甚至有 Vue.js 的封裝。此處推薦Vue.Draggable(github.com/SortableJS/Vue.Draggable)這個庫,它是基于 Sortable.js 做的一層封裝。其典型的應(yīng)用場景如下:

<draggable v-model="myArray" :options="{group:'people'}" @start="drag=true" @end="drag=false"> <div v-for="element in myArray">{{element.name}}</div></draggable>在我們的場景中,只需在draggable組件上監(jiān)聽addsort事件調(diào)用 store 中對應(yīng)的方法即可。

如本節(jié)表格所述,拖拽只是界面上的操作方式,本質(zhì)上是對數(shù)組中元素的增加和調(diào)整 index 的操作。

變更檢測

為了及時保存用戶的編輯,我們可以在用戶修改主題色、編輯模塊、刪除模塊等操作時自動保存。本質(zhì)上是需要檢測 store 中 site 這個狀態(tài)的變更。Vuex 中的插件(plugin)可以針對改動做一些類如記錄日志和持久化的操作,我們可以寫一個 autoSave 的插件來實現(xiàn)。

// store.jsconst autoSave = (store) => { store.watch( state => state.site, (newV, oldV) => { store.dispatch('saveSite') }, { deep: true } )}const store = new Vuex.Store({ state: { site: {} }, plugins: [autoSave]})至此,我們已經(jīng)用 Vue.js 和相關(guān)技術(shù)實現(xiàn)了文章開頭列出的建站應(yīng)用的需求。

結(jié)語

本文從需求分析、方案設(shè)計、編碼實現(xiàn)分別介紹了用 Vue.js 寫一個建站應(yīng)用可能會遇到的問題以及大致的思路??梢钥闯觯恼潞艽笃荚谥v數(shù)據(jù),包括數(shù)據(jù)格式的設(shè)計、數(shù)據(jù)的操作、數(shù)據(jù)變更的檢測。這是因為 Vue.js 框架幫我們做了從數(shù)據(jù)到界面的渲染以及數(shù)據(jù)變更后界面的更新的工作,我們要做的是管理好這些數(shù)據(jù)。Vue.js 框架分擔(dān)了我們的工作,提高了開發(fā)效率,使得我們可以專注于業(yè)務(wù)邏輯設(shè)計,這也是框架價值的體現(xiàn)。




附注


作者:唐鶴俊
簡介:百姓網(wǎng)前端工程師。

本文僅為作者個人觀點,不代表百姓網(wǎng)立場。

本文在 “百姓網(wǎng)技術(shù)團隊” 微信公眾號首發(fā),點此掃碼訂閱。

關(guān)鍵詞:實現(xiàn)

74
73
25
news

版權(quán)所有? 億企邦 1997-2025 保留一切法律許可權(quán)利。

為了最佳展示效果,本站不支持IE9及以下版本的瀏覽器,建議您使用谷歌Chrome瀏覽器。 點擊下載Chrome瀏覽器
關(guān)閉