使用vue如何構(gòu)建一個(gè)自動(dòng)建站項(xiàng)目
寫在前面
之前一直用Jquery+Jquery-ui來做這個(gè)項(xiàng)目,那個(gè)時(shí)候沒有設(shè)計(jì)稿,沒有項(xiàng)目需求,就因?yàn)锽OSS一句話,要做這樣的東西,當(dāng)時(shí)就...好吧!我承認(rèn),其實(shí)已經(jīng)習(xí)慣了,無所謂了(也是無奈,哎)!!!
在之后的一段時(shí)間里,做了一個(gè)demo出來,BOSS很滿意了,所以自己接下來就慢慢做吧,差不多兩三個(gè)月吧,就悶頭做這個(gè),后來項(xiàng)目上線了,當(dāng)然因?yàn)楫a(chǎn)品的不完善,還是有點(diǎn)問題了!
不過基本能滿足公司的需求了,能編輯的都可以編輯,組件的background(包括背景圖片) color border box-shadow margin padding width height 對(duì)齊方式(字體和組件內(nèi)部元素) border-radius font(font-size/font-family)等等這些基礎(chǔ)的都可以隨心變更,當(dāng)然考慮到可能滿足不了公司的使用,就加了一個(gè)自定義樣式的功能,而這個(gè)只有懂前端的人才能使用了,沒辦法,需求永遠(yuǎn)趕不上變化,這樣保險(xiǎn)一點(diǎn)。因?yàn)榇蠹叶贾?,需求的滿足和變更永遠(yuǎn)跑在現(xiàn)成需求的前面
除了這些基礎(chǔ)的可更改,各個(gè)組件的特有可變更的功能也基本齊全的,比如輪播圖圖片變更,輪播方式,控制是否輪播等等這些功能,這里就不一一介紹了
包括后來,因?yàn)橛薪M件內(nèi)部個(gè)別元素不能修改,又增加了[綁定修改]功能,就是這個(gè)功能選中之后,在視圖界面,選中需要修改的元素,便可以進(jìn)行修改了,這個(gè)功能還是有點(diǎn)意思的
說了這么多,其實(shí)當(dāng)時(shí)因?yàn)樽龅膫}促,存儲(chǔ)的時(shí)候存的是HTML,大家不要鄙視(要臉0.0),這個(gè)也是我心里一直的梗,最近加上BOSS重新提出了一些想法,有蠻多東西要加,思前想后,決定將項(xiàng)目重構(gòu)一下
考慮到vue響應(yīng)式與基本是純數(shù)據(jù)操作,所以決定使用vue重新構(gòu)建這個(gè)項(xiàng)目。
開發(fā)準(zhǔn)備
1、使用vue-cli,下載下來配置好的東西
2、因?yàn)橹虚g牽涉了拖拽生成組件的操作,所以使用了vuedraggable和sortablejs。
安裝vuedraggable sortablejs
npm install vuedraggable npm install sortablejs
項(xiàng)目中我們只需要引入vuedraggable就可以了,牽涉了sortablejs東西的時(shí)候,vuedraggable會(huì)去自己加載調(diào)用sortablejs里面的方法的,這個(gè)就不是我們需要關(guān)注的(你如果想了解,可以自己去看看);
3、安裝vuex,因?yàn)槔锩鏍可娴搅舜罅康臄?shù)據(jù)交互,很多組件都需要一些公用的數(shù)據(jù),不使用vuex去管理,將會(huì)為開發(fā)帶來更多不必要的麻煩;
安裝vuex
npm install --save vuex
4、因?yàn)闆]有設(shè)計(jì)稿的緣故,所以大膽使用了第三方UI庫 element-ui;
安裝elememt
npm install element-ui //為什么是element-ui而不是element?因?yàn)楫?dāng)時(shí)npm上已經(jīng)有了element包了(我當(dāng)時(shí)還覺得挺有意思的,0.0 好冷?。。?!)
5、axios安裝,后面與后臺(tái)數(shù)據(jù)交互會(huì)用到
安裝axios
npm install --save axios
差不多準(zhǔn)備工作就這些了,接下來我們看項(xiàng)目實(shí)施;
項(xiàng)目開始
1、各種文件的配置
-> main.js中文件的配置
圖片中都有解釋,應(yīng)該可以看的懂的;
-> 側(cè)邊欄拖拽組件數(shù)據(jù)的配置
因?yàn)槲募L,所以刪掉了一些,這里就是一個(gè)簡單的格式,僅供參考,不作為標(biāo)準(zhǔn);
在組件當(dāng)中,存在一個(gè)布局的問題,所以要有布局組件,讓組件可以放到布局組建中,這樣才更加的靈活
-> vuexjs 狀態(tài)管理中的js配置
說明:
1、因?yàn)橛脩粼谕献е笠獙?shí)時(shí)保存到sessionStorage中, 所以再初始的時(shí)候要到sessionStroage中去取數(shù)據(jù),防止突然刷新頁面,還沒有保存到數(shù)據(jù)庫中,用戶剛剛編輯的數(shù)據(jù)全部丟失的情況;
2、這里說明一下,可能考慮到用于已經(jīng)提交了數(shù)據(jù),所以用戶關(guān)閉窗口之后,再次進(jìn)來的時(shí)候,要結(jié)合后臺(tái)給出的用戶之前的數(shù)據(jù),一起存儲(chǔ)到sessionStorage中去,相信這一點(diǎn)大家肯定想的到的,這里善意提醒一下 0.0;
3、我這這里暫時(shí)放了四個(gè)參數(shù),圖中都有說明,我主要是將基本編輯做成了一個(gè)組件,會(huì)根據(jù)用戶點(diǎn)擊時(shí)哪個(gè)組件,而重新渲染數(shù)據(jù)給到編輯組件,從而可以實(shí)時(shí)對(duì)應(yīng)到點(diǎn)擊的組件去編輯;
4、editShow的作用就是控制編輯組件顯示與否的,主要?jiǎng)h除組件的時(shí)候,讓編輯組件隱藏一下;點(diǎn)擊其他組件的顯示一下;
基本的配置就這些了,接下來就是真正的開發(fā)了;
2、項(xiàng)目開發(fā)開始
-> app.vue文件中該怎么寫?
<template> <!--用的element-ui--> <el-container> <el-aside> <Draggable class="app-aside-drag" :options="dragOption"> <div class="app-aside-list" v-for="(dragList,index) in dragData" :type="dragList.type" :key="dragList.type"> <div class="aside-item-body"> <i class="aside-item-ele"></i> <span class="aside-item-ele">{{ list.title }}</span> </div> </div> </Draggable> <el-aside> <el-main class="app-main"> <section class="app-phone"> <div class="app-phone-header"> <span class="phone-camera"></span> <span class="phone-ls"></span> </div> <!--頁面view區(qū) --> <Sort class="app-phone-body"></Sort> <div class="app-phone-footer"> <button class="app-phone-menu">RS</button> </div> </section> </el-main> <el-aside class="app-right"> <!--組件編輯區(qū)域--> <BaseEdit></BaseEdit> </el-aside> </el-container> </template> <script> import DragApi from "@/dragapi/dragapi.js"; import Draggable from "vuedraggable"; import Sort from "@/view/Sort"; import BaseEdit from "@/view/BaseEdit"; export default { name: 'app', data(){ return{ dragData: {}, dragOption: { group: { name: 'components', //這個(gè)很重要,其他的與之能產(chǎn)生關(guān)聯(lián)的拖拽框就靠這name 一定要一致 pull: 'clone', put: false }, sort: false //默然為true。這里我們只需要他拖拽,無需能拖動(dòng)排序 } } }, components: { Draggable, Sort, BaseEdit }, created(){ //側(cè)邊欄拖拽列表數(shù)據(jù) //這里我只寫了組件的數(shù)據(jù)進(jìn)來,布局的暫時(shí)沒放 this.dragData = DragApi.configList[1].content; } } </script>
-> 來看看sort view視圖區(qū)域組件
<template> <Draggable :options="sortOption" @sort="onSort" @add="onAdd" class="app-sort"> <!-- ui組件 --> <!--這里不懂的人,可以去vue官網(wǎng)看看動(dòng)態(tài)組件--> <div v-for="(appUi,index) in sortApi" //循環(huán)組件 :is="appUi.component" //根據(jù)存在的組件渲染出來 :content="appUi.content" :oStyle="appUi.style" :editPartShow="appUi.editPartShow" :aIndex="index" //組件想要點(diǎn)擊生效,只需要@click.native就行了 @click.native="getIndex(index)" //key值一定要給出來,不然相同組件的排序可能會(huì)不成功 :key="appUi.content.code"> </div> </Draggable> </template> <script> //利用vuex 輔助函數(shù)來操作vuexjs中的數(shù)據(jù) import { mapState,mapMutations } from 'vuex'; //拖拽插件引入 import Draggable from 'vuedraggable'; //各個(gè)組件引入 import Carousel from "@/components/Carousel.vue"; import Btn from "@/components/Btn.vue"; export default { name: 'Sort', components: { Draggable,Btn,Carousel }, data(){ return { sortOption: { group: { name: 'components', //前面說的name,在這里就起了作用,不一樣,是不能放入的 pull: true, put: true }, sort: true, animation: 300 //給了個(gè)動(dòng)畫,看起來舒服些 } } }, computed:{ ...mapState(['editIndex','sortApi']), }, watch:{ sortApi:{ handler(newVal,oldVal){ window.sessionStorage.setItem('localData',JSON.stringify(newVal)); }, deep: true } }, methods:{ ...mapMutations(['sortCp','addCp','setStyle','setCommon']), onSort(res){ //排序產(chǎn)生的事件 if(res.from === res.to){ this.sortCp(res); } }, onAdd(res){//組件增加產(chǎn)生的事件 this.addCp(res); }, getIndex(index){ this.setCommon({index: index,flag: true}); } } } </script>
-> 再來看看編輯組件
<template> <transition name="slide-right"> <div v-if="sortApi.length > 0 && editShow === true"> //組件特有編輯 <el-tabs v-model="activeName"> <el-tab-pane label="組件設(shè)置" name="first"> <div v-for="(appUi,index) in sortApi" :is="appUi.component+'Edit'" :content="appUi.content" :oStyle="appUi.style" :editPartShow="appUi.editPartShow" :aIndex="index" :currentIndex="editIndex" :key="appUi.content.code"> </div> </el-tab-pane> <el-tab-pane label="樣式設(shè)置" name="second"> //公共樣式編輯 <el-collapse v-model="colorPicker.name" class="base-edit" accordion> <el-collapse-item class="tititt" :title="colorPicker.type" :name="colorPicker.type"> <el-form ref="form" :model="colorPicker" size="mini"> <el-form-item class="cui-inline-reset" v-for="(item,index) in colorPicker.content" :label="item.title" :key="item.style"> <el-color-picker //在element-ui框架中,有很多@change @active-change事件,直接寫事件發(fā)現(xiàn)不能傳入?yún)?shù), //當(dāng)然,辦法總比問題多,我們換成一下這種寫法就行了,他的默然參數(shù)寫在前面 //這里顏色拾取器 返回的是實(shí)時(shí)的顏色值 //我這里主要想傳一個(gè)對(duì)應(yīng)的style @active-change=" (value) => setStyle(value,item.style)" v-model="sortApi[editIndex].style[item.style]" show-alpha> </el-color-picker> <span class="black-text-shadow" :style="{color: sortApi[editIndex].style[item.style]}"> {{ sortApi[editIndex].style[item.style] }} </span> </el-form-item> </el-form> </el-collapse-item> </el-collapse> </el-tab-pane> </el-tabs> </div> </transition> </template> <script> import { mapState,mapMutations } from 'vuex'; //這里我將組建特有的編輯欄,寫成了一個(gè)組件,為什么不寫在相應(yīng)的組件一起了? //這里必須說明一下,主要是我沒有想到方法,讓他在同一組件內(nèi)分離出來,單獨(dú)將dom結(jié)構(gòu)放在編輯欄這里,如果有大神知道 //還望不吝賜教 import BtnEdit from "@/components/BtnEdit.vue"; export default{ name: 'BaseEdit', components: { BtnEdit }, data(){ return{ colorPicker: { type: '顏色設(shè)置', name: 'Picker', content:[ { title: '背景顏色', style: 'background' }, { title: '字體顏色', style: 'color' } ] }, activeName: 'first' } }, computed:{ ...mapState(['editIndex','sortApi','editShow']) }, methods:{ setStyle(value,style){ //根據(jù)上面?zhèn)魅氲膕tyle屬性,實(shí)時(shí)改變現(xiàn)有的值 this.$set(this.sortApi[this.editIndex].style,style,value); } } } </script>
-> 選出一個(gè)組件來看看里面是怎么配置的
//按鈕組件,其實(shí)里面很簡單 //組件的對(duì)應(yīng)的編輯組件,里面內(nèi)容和這個(gè)也差不多,下面就不寫了 <template> <div class="btn-box ui-sortable" :data-code="content.code"> <el-button class="ui-btn" :style="oStyle"> {{ content.text }} </el-button> //因?yàn)槊總€(gè)組件都有刪除功能,所以寫成了一個(gè)組件 <DeleteCp :aIndex="aIndex"></DeleteCp> </div> </template> <script> import DeleteCp from "@/components/DeleteCp"; export default { name: 'Btn', props: { //父組件傳入的參數(shù) content: Object, oStyle: Object, aIndex: Number }, components: { DeleteCp }, data(){ return{ btnModel: 'btn-model' } } } </script>
->最后來看看刪除組件吧
<template> <div class="delete-compontent-box"> <div class="el-icon-delete remove-component" @click.stop="dailogStatu"></div> <el-dialog title="提示" :visible.sync="dialogVisible" :append-to-body="appendToBody" width="430px"> <div class="el-message-box__content"> <div class="el-message-box__status el-icon-warning"></div> <div class="el-message-box__message dialog-message">此操作將刪除該模塊, 是否繼續(xù)?</div> </div> <span slot="footer" class="dialog-footer"> <el-button @click="dialogVisible = false" size="small">取 消</el-button> <el-button type="primary" @click="onRemove(aIndex)" size="small">確 定</el-button> </span> </el-dialog> </div> </template> <script> import { mapMutations } from "vuex"; export default { name: 'oText', props: { aIndex: Number }, data(){ return{ //這兩個(gè)參數(shù)是彈框的參數(shù) dialogVisible: false, appendToBody: true } }, methods:{ ...mapMutations(['deleteCp','setCommon']), dailogStatu(){ //主要是控制彈窗出來,并且顯示該組件對(duì)應(yīng)的編輯欄 this.dialogVisible = true; this.setCommon({flag: true,index: this.aIndex}) }, onRemove(index){ //點(diǎn)擊確定刪除對(duì)應(yīng)的組件 let flag = false; this.deleteCp(index); this.dialogVisible = false; this.$message({ message: '該模塊已刪除 !', type: 'success' }); this.setCommon({flag: false,index: 0}) } } } </script>
-> 來看看效果圖吧
效果圖展示
結(jié)束語
好了,今天寫了很多了,最后我們來梳理一下思路:
1、首先配置左側(cè)的拖拽組件
2、配置vuex中的數(shù)據(jù)
3、app.vue中配置
4、編輯組件的配置
5、各種數(shù)據(jù)的傳遞與依賴
其實(shí)每個(gè)項(xiàng)目,都需要一個(gè)清晰的路線,這樣才能很好的開發(fā)下去,所以我的建議是,在拿到項(xiàng)目的時(shí)候,千萬不要一股腦的去寫,一定要想好怎么做,以及突發(fā)事情的發(fā)生(比如突來的需求變更),這樣既方便了我們自己,也方便了后來維護(hù)的人,也阻止了不必要的麻煩
謝謝大家的耐心的閱讀,畢竟這只是一個(gè)大概的介紹,肯定存在很多不足,如果大家有建議,歡迎留言交流,也希望大家多多支持腳本之家。
相關(guān)文章
Vue中v-on的基礎(chǔ)用法、參數(shù)傳遞和修飾符的示例詳解
使用v-on:click給button綁定監(jiān)聽事件以及回調(diào)函數(shù),@是v-on:的縮寫,也就是簡寫也可以使用@click,這篇文章主要介紹了Vue中v-on的基礎(chǔ)用法、參數(shù)傳遞和修飾符,需要的朋友可以參考下2022-08-08在Vue中實(shí)現(xiàn)地圖熱點(diǎn)展示與交互的方法詳解(如熱力圖)
隨著大數(shù)據(jù)和可視化技術(shù)的發(fā)展,地圖熱點(diǎn)展示越來越受到人們的關(guān)注,在Vue應(yīng)用中,我們通常需要實(shí)現(xiàn)地圖熱點(diǎn)的展示和交互,以便更好地呈現(xiàn)數(shù)據(jù)和分析結(jié)果,本文將介紹在Vue中如何進(jìn)行地圖熱點(diǎn)展示與交互,包括熱力圖、點(diǎn)聚合等2023-07-07uni-app 使用編輯器創(chuàng)建vue3 項(xiàng)目并且運(yùn)行的操作方法
這篇文章主要介紹了uni-app 使用編輯器創(chuàng)建vue3 項(xiàng)目并且運(yùn)行的操作方法,目前uniapp 創(chuàng)建的vue3支持 vue3.0 -- 3.2版本 也就是說setup語法糖也是支持的,需要的朋友可以參考下2023-01-01壓縮Vue.js打包后的體積方法總結(jié)(Vue.js打包后體積過大問題)
大家都知道,Vuejs的 CLI工具 是基于 webpack 來實(shí)現(xiàn)的,所以在項(xiàng)目打包后,會(huì)生成的文件會(huì)很大。 主要原因是 webpack 將我們所有文件都打包成一個(gè)js文件,即使再小的項(xiàng)目,打包之后文件都會(huì)變得很大。 下面講講最近我遇到的相同問題。2020-02-02vue使用節(jié)流函數(shù)的踩坑實(shí)例指南
防抖和節(jié)流的目的都是為了減少不必要的計(jì)算,下面這篇文章主要給大家介紹了關(guān)于vue使用節(jié)流函數(shù)踩坑的相關(guān)資料,需要的朋友可以參考下2021-05-05Vue Element前端應(yīng)用開發(fā)之Vuex中的API Store View的使用
這篇文章主要介紹了Vue Element前端應(yīng)用開發(fā)之Vuex中的API Store View的使用,對(duì)Vue感興趣的同學(xué),可以參考下2021-05-05vite+vue3中require?is?not?defined問題及解決
這篇文章主要介紹了vite+vue3中require?is?not?defined問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05