【前端vue進階實戰】:從零打造一個流程圖、拓撲圖專案【Nuxt.js
接,下面我們實現右鍵選單、http通訊、路由。
本系列教程是用Vue.js + Nuxt.js + Element + Vuex + ,打造一個屬於自己的線上繪圖軟體,最終效果: 。如果你覺得好,歡迎給文章和點贊,讓我們更有動力去做好!
本系列教程原始碼地址:
目錄
右鍵選單
右鍵選單原理很簡單:自定義html的oncontextmenu事件:
<div id="topology-canvas" class="full" @contextmenu="onContextMenu($event)"></div>
遮蔽預設右鍵選單事件,計算右鍵滑鼠位置,彈出一個我們自己的div自定義選單即可
onContextMenu(event) {
event.preventDefault()
event.stopPropagation()
if (event.clientY + 360 < document.body.clientHeight) {
this.contextmenu = {
left: event.clientX + 'px',
top: event.clientY + 'px'
}
} else {
this.contextmenu = {
left: event.clientX + 'px',
bottom: document.body.clientHeight - event.clientY + 'px'
}
}
}
<div class="context-menu" v-if="contextmenu.left" :style="this.contextmenu">
<ul>
<li>選單一</li>
<li>選單二</li>
<li>選單三</li>
</ul>
</div>
在本專案中,封裝了一個右鍵選單元件“CanvasContextMenu”,透過父元件,傳遞canvas例項和選中的屬性資料
props: {
canvas: {
type: Object,
require: true
},
props: {
type: Object,
require: true
}
}
其中,屬性props含義為:
props: {
node: null, // 選中節點
line: null, // 選中連線
nodes: null, // 選中多個節點
multi: false, // 選中多個節點/連線
locked: false // 選中物件是否被鎖定
}
然後,我們根據選單事件和屬性props來呼叫canvas的相應介面函式,參考
http通訊
這裡,我們不去從零寫個後端服務,直接採用線上介面服務。
代理配置
首先,我們需要給nuxt.config.js新增http代理配置,這樣開發環境下的http請求,自動代理轉發給,獲取到真實資料。
axios: {
proxy: true
},
proxy: {
'/api/': '',
'/image/': ''
},
其中,proxy的含義是指:所有/api/、/image/開頭的請求,自動轉發給 ,其他的不轉發。
通常,我們透過字首/api/表示這是後端介面請求,而不是靜態資源請求;/image/表示靜態資源圖片請求。
使用者登入
1. 右上角新增使用者頭像和暱稱
由於這裡,暫時沒有多頁面共享使用者資訊,因此,我們直接在layouts/default的頂部導航欄和data裡新增使用者資料
data() {
return {
about: false,
license: false,
joinin: false,
lineNames: ['curve', 'polyline', 'line'],
arrowTypes: [
'',
'triangleSolid',
'triangle',
'diamondSolid',
'diamond',
'circleSolid',
'circle',
'line',
'lineUp',
'lineDown'
],
user: null
}
}
<el-submenu index="user" v-if="user">
<template slot="title">
<el-avatar
class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"
:size="24"
></el-avatar>
{{user.username}}
</template>
<el-menu-item @click="onSignOut">退出</el-menu-item>
</el-submenu>
<el-menu-item v-if="!user">
<a @click="onLogin">註冊 / 登入</a>
</el-menu-item>
大型專案,可能需要使用vuex去儲存使用者資料
2. 實現登入
這裡,我們直接省略登入頁面,直接跳轉到線上登入頁面,共享登入狀態。
凡是le5le.com的子域名,透過共享cookie中的token來共享le5le.com的登入狀態。首先,我們修改本地電腦的host檔案,新增一條local.le5le.com子域名,對映到本地電腦:
127.0.0.1 local.le5le.com
如何修改host檔案,請google。
然後,我們把 換成 去在瀏覽器中開啟我們的開發頁面,這時,我們就可以點選右上角“登入/註冊”,去登入。
2.1 第一次開啟網頁,讀取使用者是否登入
在le5le.com上,是使用的方式去使用者認證的。jwt的token值儲存在cookie中,方便子域名共享登入。然後每個http請求headers裡面加上Authorization: token值,後端服務就可以認證使用者身份。
在第一次開啟網頁初始化時,只需在請求後端服務/api/user/profile獲取使用者即可。當介面/api/user/profile返回使用者資料,表示使用者已登入;當返回401表示未登入。這裡,我們先判斷了是否存在cookie下的token在請求使用者介面。參考default.vue:
async getUser() {
if (this.$cookies.get('token')) {
this.user = await this.$axios.$get('/api/user/profile')
}
},
async和await是成對出現的。函式名前面加async,函式里面就可以使用await表示必須等待await後面的函式執行完得到返回結果,才繼續執行後面的程式碼。通常用於等待非同步請求結果,避免回撥。即使沒有非同步也是可以的。
為了每次請求自動把cookie裡面的token新增到headers裡面,我們需要按照下面操作,寫一個http請求的攔截器。
2.2 http攔截器
http攔截器的作用時,每次請求和資料返回時,自動幫我們處理一些全域性公用操作。比如這裡的身份認證token新增。
2.2.1 新建一個plugins/axios.js外掛檔案
透過axios外掛的方式實現http攔截器。
export default function({ $axios, app, redirect }) {
// 設定token,新增Authorization到headers
$axios.setToken(app.$cookies.get('token'))
$axios.onResponse(response => {
// 統一錯誤處理。如果發現error欄位,則傳送一個notice/error錯誤訊息。在default.vue監聽並彈出右上角錯誤提示框
if (response.error) {
app.store.commit('notice/error', { text: response.error })
}
})
$axios.onError(error => {
// 透過code狀態碼判斷介面是否出錯。請自行google學習http狀態碼
const code = parseInt(error.response && error.response.status)
if (code === 401) {
// 需要登入
app.store.commit('notice/error', {
text: '請先登入!'
})
} else if (code === 403) {
// 無許可權訪問
redirect('/')
} else if (code === 500) {
app.store.commit('notice/error', {
text: error.response.error || '服務錯誤,請稍後重試!'
})
}
})
}
2.2.2 nuxt.config.js中配置載入axios外掛
plugins: ['@/plugins/element-ui', '@/plugins/axios'],
2.2.3 新增cookie外掛
因為我們需要讀取cookie,所有安裝一個cookie外掛,方便使用。
yarn add cookie-universal-nuxt --save
nuxt.config.js中
modules: [
// Doc:
'@nuxtjs/axios',
'cookie-universal-nuxt'
],
然後,可以直接在我們的plugins/axios.js和(default).vue中使用了。
路由,新增一個首頁列表頁面
nuxt.js不需要去寫router.js,約定pages下的vue檔案就是路由。比較省事。
我們新增一個新的index.vue首頁,把原index.vue改成workspace.vue。
新index.vue:
<template>
<div class="page-list">
<div>
<div class="nav">
<label>熱門圖文</label>
</div>
<div class="flex wrap">
<div
class="topo"
v-for="(item, index) of data.list"
:key="index"
:title="item.desc"
@click="onOpen(item)"
>
<div class="image">
<img :class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="item.image" />
</div>
<div class="ph15 pv10">
<div class="title line one" :title="item.name">{{ item.name }}</div>
<div class="desc line two mt5" :title="item.desc">{{ item.desc }}</div>
<div class="flex mt5">
<div class="full flex middle">
<el-avatar
class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original=""
:size="24"
></el-avatar>
<span class="ml5">{{ item.username }}</span>
</div>
<div>
<span class="hover pointer mr15" title="贊">
<i
class="iconfont"
:class="{'iconfont icon-appreciate':!item.stared, 'iconfont icon-appreciatefill':item.stared}"
></i>
<span class="ml5">{{ item.star || 0 }}</span>
</span>
<span class="hover pointer" title="收藏">
<i
class="iconfont"
:class="{'iconfont icon-like':!item.favorited, 'iconfont icon-likefill':item.favorited}"
></i>
<span class="ml5">{{ item.hot || 0 }}</span>
</span>
</div>
</div>
</div>
</div>
</div>
<div>
<el-pagination
@current-change="getList"
:current-page="search.pageIndex"
:page-size="8"
layout=" prev, pager, next, jumper, total"
:total="data.count"
></el-pagination>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
data: {
list: [],
count: 0
},
search: {
pageIndex: 1,
pageCount: 8
}
}
},
created() {
this.getList()
},
methods: {
async getList() {
this.data = await this.$axios.$get(
`/api/topologies?pageIndex=${this.search.pageIndex}&pageCount=${this.search.pageCount}`
)
},
onOpen(item) {
this.$router.push({ path: '/workspace', query: { id: item.id } })
}
}
}
</script>
index.vue 主要包含:1. getList獲取首頁列表資料;2. this.$router.push({ path: ‘/workspace’, query: { id: item.id } }) 開啟具體頁面
路由詳情:
最後
自此,一個麻雀雖小五臟俱全的小專案就完成了,包含:框架搭建、外掛、vuex、身份認證、http通訊、路由等功能。
整個專案功能細節還不完善,歡迎大家提pr:
完整細節可參考: , 。
如何貢獻
透過GitHub的pr方式:
0. 閱讀,瞭解相關屬性。
- fork倉庫到自己名下
- 本地修改並提交到自己的git倉庫
- 在自己的fork倉庫找到 “Pull request” 按鈕,提交
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/1600/viewspace-2824314/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 從零開始打造流程圖、拓撲圖專案【Nuxt.js + Element + Vuex】流程圖UXJSVue
- vue 實現動態拓撲圖Vue
- 一個很漂亮的拓撲圖程式
- 從零搭建一個vue專案Vue
- 從零打造微前端框架:實戰“汽車資訊平臺”專案前端框架
- 圖論——拓撲排序圖論排序
- 用RecyclerView打造一個輪播圖(進階版)View
- 網路拓撲圖:網路拓撲圖介紹及線上製作
- 從零開始搭建一個vue專案Vue
- 圖解拓撲排序+程式碼實現圖解排序
- Reward (圖論+拓撲排序)圖論排序
- 從零開始打造一個iOS圖片載入框架(一)iOS框架
- 圖的拓撲排序詳解與實現排序
- 從零開始打造一個iOS圖片載入框架(三)iOS框架
- 從零開始打造一個iOS圖片載入框架(二)iOS框架
- 從零開始打造一個iOS圖片載入框架(四)iOS框架
- 團隊拓撲快速參考圖
- 有向圖的拓撲排序——DFS排序
- HT For Web 拓撲圖背景設定Web
- 網站拓撲圖(來自qq)網站
- 演算法-圖論-拓撲排序演算法圖論排序
- 在 IBM Rational Software Architect 中建立一個部署拓撲圖IBM
- HTML5拓撲圖形元件設計之道(一)HTML元件
- Vue專案實戰(一)——ToDoListVue
- 【圖論】拓撲排序+優先佇列圖論排序佇列
- 從零開始構建自己的第一個vue專案Vue
- 數百個 HTML5 例子學習 HT 圖形元件 – 拓撲圖篇HTML元件
- 最新拓薪Java高階階段及ERP實戰專案(階段三)Java
- Vue專案中使用better-scroll實現一個輪播圖Vue
- 圖解Activity啟動流程,進階高階圖解
- HTML5 網路拓撲圖整合 OpenLayers 實現 GIS 地圖應用HTML地圖
- [AST實戰]從零開始寫一個wepy轉VUE的工具ASTVue
- 打造專案專屬圖示庫
- 圖(3)--拓撲排序與關鍵路徑排序
- 拓撲排序 (BFS )DAG (有向無環圖)排序
- 從零開始構建一個vue專案 --- webpack歷險記VueWeb
- Android進階 一個專案,一個ToolbarAndroid
- ECharts+百度地圖網路拓撲圖應用Echarts地圖