XiaoShang Replay
- 新增加的组件
- 表单元素和Vuex
- c-accordion
- 新使用的第三方组件
- portal-vue
- vue-virtual-scroller
- preload-webpack-plugin
- html-critical-webpack-plugin
- 一些坑
- 微信签名失败
- 微信分享接口调用失败的原因
- 微信浏览器中刷新页面
4.思考
- code split粒度
- 不要使用匿名函数 anonymous function(for debugging)
5.其他
- vue official style guide
1. 新增加的组件
表单元素和Vuex
通过vuex同步不同表单元素之间的值,即使表单元素在不同页面之中
// store.js
const state = {
val: 'Hello World!'
}
const mutations = {
changeMsg (state, msg) {
state.val = msg
}
}
export default new Vuex.Store({
state,
mutations
})
// 组件内通过computed属性读取/修改Vuex中的变量
export default {
name: 'Input1',
data () {
return {}
},
computed: {
message: {
get () {
return this.$store.state.val
},
set (value) {
this.$store.commit('changeMsg', value)
}
}
}
}
input1
)
Input2修改Input1的值,在不同页面的Input2的值页也被修改了
晓商中搜索的条件筛选组件使用了相同的原理
晓商-条件筛选 晓商-搜索结果页
c-accordion 手风琴菜单
晓商-我的关注为了避免浏览器的reflow/layout, 菜单的折叠/展开的过渡效果没有使用transiton: max-height(PS: height: auto & transition: height 是不会产生动画效果的),而是通过transform实现。
为什么?
what is reflowtransition: max-height 真的会导致reflow/layout 吗
.accordion-item-content {
max-height: 240px;
transition: max-height .3s;
}
每一帧都有layout过程
通过transform 实现
每一帧都没有layout过程How
- FLIP原理
-
FLIP原理 中文翻译
how to FLIP
example of FLIP
vue中transition-group的也使用了FLIP原理
accordion-menu 折叠时的动画原理2. 新使用的第三方组件
portal-vue
PortalVue is a set of two components that allow you to render a component's template (or a part of it) anywhere in the document - even outside of your the part that is controlled by your Vue App!
DEMO: http://runjs.cn/detail/gmg2uql3
why portal-vue
-
避开position:fixed引起的问题
- transform元素下的子元素元素使用position:fixed
https://stackoverflow.com/questions/15194313/transform3d-not-working-with-position-fixed-children
demo:http://runjs.cn/detail/xosvjzlb
- transform元素下的子元素元素使用position:fixed
-
modals, dialogs, notifications, snackbars等组件可以直接挂在到根元素上
-
在组件A中控制组件A结构之外其他的组件
vue-virtual-scroller
问题:随着列表的向下滚动,会加载更多的数据,同时生产更多的DOM节点。
为了防止页面中的DOM节点无限制地增长,使用了vue-virtual-scroller。该组件会随着滚动条的位置,自动删除离开视窗的DOM节点,插入新的进入视窗的DOM节点。
滚动位置变化了,DOM节点的数目几乎不变preload-webpack-plugin
问题:使用路由级别的异步加载,页面跳转时,会停顿一下,等页面顶部的下条条消失才会发生跳转。
A Webpack plugin for automatically wiring up asynchronous (and other types) of JavaScript chunks using <link rel='preload'>. This helps with lazy-loading.
what is preload good for?
what is preload good for? -- 中文翻译
Prefetch
资源加载的优先级可以通过DevTool查看<link rel=“prefetch”>但Preload与这两者不同,<link rel=“prefetch”>的作用是告诉浏览器加载下一页面可能会用到的资源,注意,是下一页面,而不是当前页面。因此该方法的加载优先级非常低(自然,相比当前页面所需的资源,未来可能会用到的资源就没那么重要了),也就是说该方式的作用是加速下一个页面的加载速度。
Preload
- 资源的提前加载
preload 一个基本的用法是提前加载资源,尽管大多数基于标记语言的资源能被浏览器的预加载器(Preloader)尽早发现,但不是所有的资源都是基于标记语言的,比如一些隐藏在 CSS 和 Javascript 中的资源。当浏览器发现自己需要这些资源时已经为时已晚,所以大多数情况,这些资源的加载都会对页面渲染造成延迟。
现在,有了 preload,你可以通过一段类似下面的代码对浏览器说,”嗨,浏览器!这个资源你后面会用到,现在就加载它吧。“
<link rel="preload" href="late_discovered_thing.js" as="script">
- 对字体的提前加载
<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>
- 动态加载,但不执行
难道我们不是已经有了<script async>? <scirpt async>虽好,但却会阻塞 window 的 onload 事件。某些情况下,你可能希望这样,但总有一些情况你不希望阻塞 window 的 onload 。- 响应式加载
通过 Preload,我们可以提前加载资源,利用 media 属性,浏览器只会加载需要的资源。
<link rel="preload" as="image" href="map.png" media="(max-width: 600px)">
<link rel="preload" as="script" href="map.js" media="(min-width: 601px)">
# 带你玩转prefetch, preload, dns-prefetch,defer和async
preload支持情况 使用preload-webpack-plugin后的效果
html-critical-webpack-plugin
解决的问题: 加快首屏渲染速度
使用了html-critical-webpack-plugin后,首屏渲染时间发生在657.04ms
没有使用html-critical-webpack-plugin,首屏渲染时间发生在1.32s
原理:利用headless browser,检测出首屏渲染的css,然后将这部分css插入到index.html文件中
缺点:critical css因为在index.html中,增大了index.html文件的体积,同时失去了被缓存的可能
扩展阅读:understanding-critical-css
一些坑
- 微信签名失败
可能是url编码(encodeURIComponent)的原因导致的 - 微信分享接口调用失败
要在每次进入页面前(如beforeEnter),都进行权限验证配置注入
export const wxConfig = () => {
if (!isWXEnv()) { return; }
Vue.http.get('/wechat/signature', {
params: {
// url: window.encodeURIComponent(window.location.href)
url: window.encodeURIComponent(window.location.href.split('#')[0])
}
}).then(response => {
const result = response.body;
// 配置信息
debugFlag && alert('wxConfig called');
window._wx.config({
debug: isDevEnv(),
appId: result.data.appId,
timestamp: result.data.timestamp,
nonceStr: result.data.nonceStr,
signature: result.data.signature,
jsApiList: [
'onMenuShareTimeline',
'onMenuShareAppMessage',
'hideMenuItems',
'showMenuItems',
'showAllNonBaseMenuItem'
]
});
}, e => { alert(`WX权限验证配置注入失败--${JSON.stringify(e)}`); });
};
- 微信浏览器中刷新要使用特殊的技巧
http://xiaoshang.brp.kingdee.com?t=5454/#/search/result
一些思考
code split的粒度
- 每个组件都异步加载?
优点: 组件可以被缓存起来,一次请求,多次复用
缺点: js代码被分割成太多的小文件,js文件请求数增加。服务器压力? - 只是基于路由的异步加载?
- 全部被多次复用的组件可以使用相同的chunkName,打成一个包
不要使用匿名函数 anonymous function(for debugging)
anonymous function(() => {
throw new Error('can we get arrow name ?');
})();
named function
const testArrowErrorTrack = () => {
throw new Error('can we get arrow name ?');
};