接前面二,下面我们实现右键菜单、http通信、路由。
本系列教程是用Vue.js + Nuxt.js + Element + Vuex + 开源js绘图库,打造一个属于自己的在线绘图软件,最终效果:http://topology.le5le.com 。如果你觉得好,欢迎给文章和开源库点赞,让我们更有动力去做好!
本系列教程源码地址:Github
目录
右键菜单
右键菜单原理很简单:自定义html的oncontextmenu事件:
屏蔽默认右键菜单事件,计算右键鼠标位置,弹出一个我们自己的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'
}
}
}
在本项目中,封装了一个右键菜单组件“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通信
这里,我们不去从零写个后端服务,直接采用topology.le5le.com线上接口服务。
代理配置
首先,我们需要给nuxt.config.js添加http代理配置,这样开发环境下的http请求,自动代理转发给topology.le5le.com,获取到真实数据。
axios: {
proxy: true
},
proxy: {
'/api/': 'http://topology.le5le.com/',
'/image/': 'http://topology.le5le.com/'
},
其中,proxy的含义是指:所有/api/、/image/开头的请求,自动转发给http://topology.le5le.com/ ,其他的不转发。
通常,我们通过前缀/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
}
}
{{user.username}}
退出
注册 / 登录
大型项目,可能需要使用vuex去保存用户数据
2. 实现登录
这里,我们直接省略登录页面,直接跳转到线上登录页面account.le5le.com,共享登录状态。
凡是le5le.com的子域名,通过共享cookie中的token来共享le5le.com的登录状态。首先,我们修改本地电脑的host文件,新增一条local.le5le.com子域名,映射到本地电脑:
127.0.0.1 local.le5le.com
如何修改host文件,请google。
然后,我们把 http://localhost:3000/ 换成 http://local.le5le.com:3000/ 去在浏览器中打开我们的开发页面,这时,我们就可以点击右上角“登录/注册”,去登录。
2.1 第一次打开网页,读取用户是否登录
在le5le.com上,是使用jwt的方式去用户认证的。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: https://axios.nuxtjs.org/usage
'@nuxtjs/axios',
'cookie-universal-nuxt'
],
然后,可以直接在我们的plugins/axios.js和(default).vue中使用了。
# 路由,添加一个首页列表页面
nuxt.js不需要去写router.js,约定pages下的vue文件就是路由。比较省事。
我们添加一个新的index.vue首页,把原index.vue改成workspace.vue。
新index.vue:
{{ item.name }}
{{ item.desc }}
{{ item.username }}
{{ item.star || 0 }}
{{ item.hot || 0 }}
index.vue 主要包含:1. getList获取首页列表数据;2. this.$router.push({ path: '/workspace', query: { id: item.id } }) 打开具体页面
路由详情:https://zh.nuxtjs.org/guide/r...
# 最后
自此,一个麻雀虽小五脏俱全的小项目就完成了,包含:框架搭建、插件、vuex、身份认证、http通信、路由等功能。
整个项目功能细节还不完善,欢迎大家提pr:
完整细节可参考:http://topology.le5le.com/ ,开发文档 。可加入贡献者名单哦!也欢迎加群交流讨论:
如何贡献
通过GitHub的pr方式:
- 阅读开发文档,了解相关属性。
- fork仓库到自己名下
- 本地修改并提交到自己的git仓库
- 在自己的fork仓库找到 “Pull request” 按钮,提交