Hexon 开发心得

Hexon(曾用名winwin-hexo-editor)是我开发的用于在线编辑hexo文章的编辑器。本文记录了我在开发中学到的部分知识。

OAuth token 的逻辑

分为access tokenrefresh token。仅在授权服务器和资源服务器的安全等级有较大差异的时候分为两个token才有安全作用。此外,分开token可以减轻服务器的查询负担。

没有refresh token:

  • 发送带有access token的请求
  • 服务器检索access token表,确认token是否过期或被撤回
  • 如果是,返回失败,要求用户重新登录

有refresh token

  • 发送带有access token的请求
  • 如果access token过期,使用refresh token申请新的access token
  • 服务器接受刷新申请,检索refreshtoken表,确认token是否过期或被撤回
  • 如果是,返回失败,要求用户重新登录
  • 否则返回新的access token,用户重新尝试申请

使用refresh token后的表检索次数由请求频率x用户数,降低到了请求频率/access token有效期内的请求数量x用户数。有利于代码的规模化。

Monaco Editor如何更新layout

  1. 保证container的大小正确
    • 内容可能撑起container,需要对container使用 flex: 1 0 0;使得container没有高度且撑满空间
    • 对于内容溢出需要overflow-hidden
  2. 更新editor的layout
    • 简单粗暴:在新建editor时候,启用automaticLayout=true
    • 精巧:在任何container大小改变的时候,手动调用editor.layout

IStandaloneEditorConstructionOptions | Monaco Editor API v0.22.3

如何实现vue的连续载入中界面

  1. 在app加载之前:使用原生html写加载界面
  2. 在app加载之后,用vue写加载界面,删除原生加载
  3. 在router时候,更新加载界面内容。使用vuex
  4. 在加载组件的时候,更新加载界面内容。使用vuex
  5. 组件加载完成后,关闭加载界面。还是使用vuex

需要注意

如果有异步操作,需要确保所有操作完成后再关闭加载界面。具体实现,计划使用一个map来记录不同加载开始的申请是否结束。例如,component#1 申请了加载界面,那必须在加载结束时申请关闭。

如果每个操作结束都关闭,那可能会造成界面闪烁。

Vue和Router初始化的时候都干了什么

  1. 加载应用 // 此时 vue app不可用
  2. 渲染应用 // 渲染完成后 app 可用,渲染时间可以忽略不计
  3. 如果有路由
    1. 依次运行路由钩子 // 可能涉及到钩子中的网络请求造成的延迟
    2. 加载路由对应组件 // 加载组件需要时间
    3. 渲染路由对应组件 // 渲染时间可以忽略不计

vue在路由切换后,新组建载入前,如何加入动画

()=> import('xxx.vue')只是一个普通的函数,可以对这个函数做手脚。在函数运行前后添加状态指示。

注意:由于webpack的机制,这个函数必须整体作为参数!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import { Logger } from 'src/utils/logger'
import Vue from 'vue'
const logger = new Logger({ prefix: 'async load' })
const state = {}

/**
* 懒加载模块,记录加载状态
* @param {Function} fn `()=>import('xxx)`
* @param {String} name 随便指定一个名称,需要唯一
* @param {Object} meta 附加数据,仅用于描述,不影响懒加载
* @param {Number} delay 延时
*/
function load(fn, name, meta = {}, delay = 200) {
if (!name) throw new Error('name is required')
if (Object.keys(state).includes(name)) throw new Error('duplicate async load name:', name)
logger.log('registed:', name)
Vue.set(state, name, {
loading: false,
error: false,
meta
})
return () => {
const token = window.setTimeout(() => {
state[name].loading = true
logger.log('start loading:', name)
}, delay)
const done = v => {
if (token) window.clearTimeout(token)
state[name].loading = false
logger.log('end loading:', name)
return v
}
return fn().then(done, done).catch(e => {
state[name].error = true
logger.log('fail loading:', name)
return e
})
}
}

export default {
state, load
}

什么时候判断是否要弹窗

在调用Action的时候(也就是类似在用户点击某个按钮的时候),去判定需不需要弹窗询问用户意见,然后再根据询问结果进行下一步操作。Action不进行和ui有关的操作,只更新数据。

故事点

到底什么是故事点(Story Point)?

故事点是一个度量单位,用于表示完成一个产品待办项或者其他任何某项工作所需的所有工作量的估算结果。

按照这个列表里面的情况(指TeamBition中的故事点选项),随便搞搞0.5,半天是1,一天是2,两天是3,三天是5,4天是8,5天是13
sp不一定是真实的,只是一个预估值,来表明你对这个ticket做起来,觉得复杂程度的预估

Quasar和Flex

quasar的col只会添加flex:1,如果不想内容超出边界需要自行添加flex:1 0 0

看板工作流程

  1. Backlog:所有可能作出的更改,bug,feature等
  2. Todo:下个版本需要做的更改
  3. InProgress
  4. PeerReview
  5. Done

什么时候需要路由?

用户刷新后需要回到当前页面的时候

在何处存储组件依赖的数据、

  • 组件内部:数据只在组件生命周期内使用
  • 某一个父组件内部:数据有多个子组件在使用
  • 单独存储:数据在应用打开周期内都可用
  • 持久化存储:数据一直可用

Vuex 的map怎么用

mapState,mapGetter,mapActions调用的时候第一个参数是模块名称。文档

Layout和component

Layout应该用于控制相应区域的显示范围和显示与否,具体的显示内容应该交给component处理