vue-zhihudaily项目踩坑总结

学习vue框架中,一边学一边做的一个小项目,记录一下踩的一些坑,并且贴一下寻到的解决方案。

项目介绍

利用vue系列全家桶仿照知乎日报做的小项目,利用了知乎日报的API。

模块/工具 作用/功能
vue-cli 脚手架搭建项目结构
vuex 状态管理
vue-resource 请求后端数据
vue-router 路由信息管理
webpack 自动化构建
vue-devtools 调试代码 查看状态
知乎API 提供数据

API介绍

开发过程

保存了一部分json假数据用于开发过程中使用,整个项目耗时三天。因为先前做了个没有框架的知乎日报移动端版本,所以这个里面没有去过多纠结移动端适配的问题。
直接使用了bootstrap进行布局。对页面结构只做了简单的响应式处理,未做太多的移动端的优化。

因为对于vue也是个初学者,所以整个开发期间,基本闲暇时间或者遇到问题就会去查看官方的docs,然后再进行尝试,或者在segmentfault上寻求答案。

因为vue的MVVM模式是以数据为核心,而非传统的以DOM为核心的模式,所以在开发过程中的原则就是避免直接以传统模式操作DOM

然后就这样磕磕绊绊的,总算是做了点东西出来了。

开发中的坑

  1. 情景: 仍然和上个移动端版本的坑一样,页面间传值的问题。因为是做的一个新闻展示的应用,首页都是简单的新闻摘要,要通过点击摘要进入到相应的新闻详情页,这里主要是提供了一个新闻的ID。然后再进入详情页后,通过新闻详情的API请求对应的文件。不过区别的是另个版本的是页面间传值,vue的是组件间传值。

    • 原因: 因为先前做的DEMO结构都比较简单,传值是父子组件间的传值,是通过在父组件内给子组件绑定属性(v-bind),再在子组件中通过props来接收的方法来实现
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
父组件 Parent.vue

<template>
<child :id="id"></child>
</template>

<script>
export default {
name: 'Parent',
data () {
return {
id: ''
}
}
}
</script>

子组件 Child.vue

<template>
<h1>{{ id }</h1>
</template>

<script>
export default {
name: 'Child',
props: {
id: {
type: String,
required: true
}
}
}
</script>
  • 解决方案: 这个方案是直接在官方API里面看到的,那就是vue-router的动态路由匹配。通过给匹配的路由加上一个参数来匹配多个路由。
1
2
3
4
5
6
7
8
9
10
11
// 匹配/xx/aa, /xx/bb 等等
const routes = {
[
path: '/xx/:xx',
name: 'xx',
component: Xxx
]
}

// 在路由跳转的时候如此设置参数
:to="{name: 'xx', params: {xx: 'xxx'}" // 注意to前面的冒号
  • 别的解决方案: 通过路由的query参数传递 通过vuex来传递
  1. 情景: 过渡效果的实现。传统的以DOM为核心的模式,直接操作DOM来附加动画效果。那么在数据核心中如何实现呢。比如我要做的一个效果侧边栏x方向移动-100%,只有在点击后才渲染它,也就是未点击的时候,这个侧边栏本身是不存在的。还有就是点赞显示的动态效果。

    • 简单的想象中的解决方案。设置display为none,通过点击后绑定切换display属性,来让其显示。
    • 不过在学些了官方文档后,发现有针对这种问题提供的方案,transition,使用官方的过渡控制,可以方便地使用第三方的CSS或者JS动画库,而且可以与vue的生命周期函数有很好的契合。
    • 适用于
      • 条件渲染(使用 v-if)
      • 条件展示(使用 v-show)
      • 动态组件
      • 组件根节点
  2. 情景: 路由跳转问题,如何在函数内让页面渲染跳转到某个指定的路由,要做一个点击后路由回退的效果---点击分享后回退到文章详情页

    • 记得先前有看过vue-router是有这个API的,叫$route.go()或者$route.push(),然后当我尝试后,发现提示不存在这个方法。
    • 后来却segmentfault查询后才知道,是有2种路由对象的。一个是$route表示当前vue实例的路由,另一个是$router来控制全局的路由跳转。
    • 官方文档介绍
  3. 情景: 实现页面的无限加载,类似单列瀑布流的效果。

    • 因为貌似vue没有scroll事件的API。(在官方DOCS未找到,vue-router有滚动行为的API控制跳转后页面滚动)
    • 在segmentfault上有人提供了的方案是用DOM监听页面滚动事件,然后挂载到vue的生命周期钩子上。
    • 在github上发现了一个vue-scroll的插件,不过下载了后看了一下,还是封装的原生JavascriptDOM处理。
    • 所以最终的解决方案还是去用DOM监听了。
  4. 情景:使用使用的知乎API,知乎提供的新闻详情页面的内容是html格式的,但是用v-html指令渲染到页面后,设置了style标签的scoped属性后,设置的样式无法影响到动态的内容

    • 暂时的解决方案是 不加scoped属性
  5. 情景:侧边栏的内容过多,超过了100%高度,PC端会出现滚动条,特别丑。

    • 解决方案: 1.尽量不要让其超过100%高度 2. 滚动条美化(渐进增强的方案)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
::-webkit-scrollbar {  // 设置滚动条宽度
width:0;

/* or */

display:none;
}
::-webkit-scrollbar-thumb { // 设置滑块颜色
background-color: #33a877 !important;
}

::-webkit-scrollbar-button { // 滑轨两端的样式控制
background-color: #33a877;
}

开发结束后的坑

  1. 布局混乱
    • 有个页面设置了width: 100%和height: 100% 然后里面的元素是用百分比定位的,在竖屏查看时候效果很好,切换到横屏后就出现上下部分内容重合了

解决方案:去掉height: 100%属性 让其自动变化

  1. 移动端浏览器下查看因为有地址栏,在侧边栏和主页面都可以向上滑动的情况下,侧边栏先于主页面滑动到顶部会导致无限加载的功能无效,而且侧边栏全部上滑后会带动主页面上面地址栏消息,让100%高度固定定位侧边栏布局混乱,会向上移动地址栏的高度。

    • 使用一个DOM的解决方案,不过并没有很好的解决问题。
    • 可使用方案。浏览器强制全屏,隐藏掉地址栏,不过只有部分浏览器提供这样的元信息设置(meta)。
1
2
3
4
// UC浏览器
<meta name="full-screen" content="yes">
// QQ浏览器
<meta name="x5-fullscreen" content="true" />

想象中的方案:

  • 在检测到侧边栏的滑动后,同时让主页面上滑,隐藏地址栏,这样再滑动侧边栏应该就不会定位布局混乱了。
  • 在侧边栏滑动的时候,禁止主页面的滑动,让其固定。
  1. 固定定位的布局,在移动端虚拟键盘弹出后,定位元素会被顶地上移。查询得知这种问题主要出现在android平台上。

    • 解决方案 转场输入,预留出虚拟键盘的弹出空间
    • 在输入框获得焦点后虚拟键盘弹出后,不再使用定位来布局,通过js来控制元素的位置,或者重新定位布局。
  1. 无限加载效果,在移动端有时候不起作用,比如路由跳转以后,再跳转回来。即是监听路由变化,重新绑定滚动监听事件仍然无法起作用。

    • 因为对vue的事件绑定取消机制不熟悉,这个问题还有待研究
  2. 在路由跳转后,刷新页面会显示页面不存在。

    1. vuex数据消失
    • 原因:vuex数据在页面刷新后被清除了,没有数据自然也就没有页面的展现了。
    • 解决方案1,利用localstorage对数据进行缓存
    • 解决方法2, 将数据放在根组件app.vue中,子页面通过this.$root.data获取。
    1. 页面404
    • 原因:vue-router配置了mode:’history’,history模式配置需要后台配合,否则刷新后页面不存在
    • 解决办法 使用hash模式

总结

踩坑多多,学习多多,双向数据绑定真的很方便,官方DOCS必须要熟悉。
数据核心的模式感觉蛮锻炼逻辑的,组件开发很好很强大。比如样式都可以设置成范围的,那么最终其实主要就是各个组件实现的是对约定好的vuex的数据里的操作,然后在暴露给别人自己应该提高的数据。命名什么的并不存在多大的冲突问题。而且组件可复用性很好。

有钱,任性!!!