vue 头条 demo 写在前面
总结一下写 demo 过程中 遇到的一些问题,方便自己的学习总结!如有错误,还请指正!
一直想学习使用 vue ,并准备以后在实际项目使用,之前跟着慕课网 黄轶 老师 敲了一下 饿了么商品购买页的demo
ele效果预览
该 demo 借鉴自 hcy1996-github 这个项目,但内部内容,布局风格,完全不同,只为共同学习,共同交流
数据接口 直接打开 今日头条 网页版 ,在 network 分析了下,直接 copy 过来的
还有很多功能没有实现,后期在完善吧!
项目地址:github-项目地址
预览效果: demo预览效果
建议在 chrome 浏览器查看(不知道为什么在手机上数据请求,一个劲卡死,不知道是不是因为今日头条接口的原因)
演示头部添加 rem 布局
引入 reset.css
使用 阿里妈妈图标库,index.html 引入
使用 css 预处理器 sass安装 node-sass sass-loader npm install node-sass sass-loader --save-dev
使用
参考文章: http://www.jianshu.com/p/67f52071657d
app.vue
底部导航栏栏 ==> 刚开始时用的 vux 的 tabbar tabbar-item 组件,发现有需求实现不了,刚开始还改了源码,最后实在受不了了
就用 vue-router roter-link 自己写了
底部导航栏 四个按钮分别对应 四个组件
由于自己对 vue-router 理解还欠火候,所以遇到了一个问题
routes 数组里面的内容对应的就是 组件 ,
path 选项对应的是路由路径,初始时没有路由嵌套 即为 index
components 选项对应该路由对应的组件,由于组件已经全部通过 import 引入了,所以不需要写路径了
底部通用 tab 导航栏
本想多带带抽出一个 bottom.vue 组件呢,但在左右切换的滑动样式中,表现并不好,因为希望底部导航栏不滑动这才符合人的预期需求
所以最终还是选择不抽离这个组件,直接写在了 app.vue 里面了
通用样式库 common scss 目录 base.scss mixin.scss 通过 一个 index.scss 导入
引入 axios ,由于 axios 不支持jsonp,所以还得引入 jsonp
npm install axios jsonp --save
在 common/js/ajax.js 下使用这两个库
import axios from "axios"
import jsonp from "jsonp"
将 ajax 请求,封装在 一个通用的 js 文件里,方便统一处理 ajax
即前后端协作时 定义的一些返回值代表的意义,都可以在此方法里统一处理
遇到个问题不知道怎么解决
我想有 loading.vue 组件,就是可以在通用的 ajax.js 文件里引用,
问题是,我发现 当加载 ajax.js 文件时 ,loading.vue 组件 import 不进来的,所以无法使用
但我又想要 当用统一 ajax 处理的时候,统一执行 loading
最终我想了一个下下策,把 loading组件的内容直接写在了index.html 文件里,这样就可以加载到了,就可以在 ajax处理的时候集中使用 loading.vue 了
不仅 loading 组件,还有 通用弹框组件,(就是想在一个通用的 js 文件里,每次只要在使用的地方 import 这个 js 文件,就能使用这些 通用组件,而不必每次都要 import 这些组件)
现在的解决办法太渣,看以后能不能想到什么好的办法
如果各位大大,有什么好的方法,希望能告知 小弟 一声
index.vue 文件顶部 x-header 组件 ,感觉使用不够灵活
不知道如何 自定义左右图标
因为 vux 的 icon 是引自 icon图标css库
右侧icon 是我引用 阿里妈妈图标库里面的图标的
标签导航一栏 本来是用 vux 的scroller 组件写的,但看到官方文档上写 ,此组件已不在维护,且不建议开发者继续使用
自己按着 demo 用了一下发现不知道 如何 refresh,就放弃了
自己 用 better-scroll 处理滚动 tab 标签栏横线滚动没碰到问题
新闻内容列表滚动也是用的 better-scroll 碰到了一个问题,
下拉刷新的logo 总是无法藏在 列表后面,无论怎么设置 z-index
最后才发现问题,自己还真的是蠢,列表容器没写背景颜色,自然永远都能看到loading图标
在纠结的过程中也发现了几个问题:
移动端百分比布局时:html,body一定要设置宽高百分比,不然会遇到很多坑
better-scroll 滚动容器一定要有明确的宽高,建议最好用绝对定位,背景颜色,overflow:hidden
最大的一个坑,列表总是有一部分滚动不上来,碰到这个问题,首先想到:
列表高度是否大于容器高度
refresh 时机不对最终,发现确实时是 refresh 时机不对,
但接下来纠结的时刻到了,无论放在哪都不对,最终写了 setTimeout(fn,3000),可以正常工作,但这肯定不是解决办法
最后想到:因为列表中的图片容器高度,是靠图片撑开的,但图片加载的比较慢所以 better-scroll 计算不到准确的高度,
解决办法:图片容器高度事先写死,完美的解决了
图片懒加载 vue-lazyload 插件,超好用
懒加载引用的图片地址:loading 图片
如果 在js 引用静态图片,因为webpack 不会解析 js 文件里的图片,
所以要用 import 引用 import logo from "./assets/loading.gif"
或是把图片放在顶层的 static 目录里
微信左右滚动效果(切换底部tab时)---以下是通用思路在 全局路由 beforeEach(function(to,from,next){***}) 钩子里 要做下面的事情
假如待切换的组件为 index1,index2
在 sessionStorage 里面 创建 一个 __router__ 值
__router__的值包括:count, transitionName , to.path ,from.path
count 初识值为 0;
transitionName 初始值为 ""
to.path 初始值为 undefined
form.path 初始值为 undefined
首次进入时 to.index(index1) 为空 执行 else
count++
判断 to.path !== "/" && history[to.path] = historyCount
history["transitionName"] = "forward"; 为前进状态
此时: index1:1,count:1
二次 进入(路由已跳转过一次) 此时 to.path 依旧 为 undefined ,而 from.path 为 to.path 的值
继续走 else 里面,重复上面的步骤 此时 index2:2,count2,index1:1
在继续点第一个 tab 相当于回到第一个 tab
此时:to.path == index1, from.path == index2
假如 :!fromIndex || parseInt(toIndex) > parseInt(fromIndex
或:toIndex === "0" && fromIndex === "0"
为 forward 前进状态
否则: 为 reserve 后退状态
这样就能判断是前进状态还是后退状态,就可以用样式控制滚动方向了
Do not bb ,show me code
router.beforeEach(function (to, from, next) { let history = window.sessionStorage.__router__; if(!history){ history = {}; }else{ history = JSON.parse(history); } let historyCount = history.count * 1; //记录走过的 tab 页数量 const toIndex = history[to.path]; // 要去的索引 const fromIndex = history[from.path]; //要离开的索引 if (toIndex) { if (!fromIndex || parseInt(toIndex) > parseInt(fromIndex) || (toIndex === "0" && fromIndex === "0")) { history["transitionName"] = "forward"; } else { history["transitionName"] = "reverse"; } } else { //第一次没有记录session-storage 的情况 ++historyCount; history["count"] = historyCount; to.path !== "/" && (history[to.path] = historyCount); history["transitionName"] = "forward"; } history = JSON.stringify(history); window.sessionStorage.__router__ = history; if (//http/.test(to.path)) { let url = to.path.split("http")[1]; window.location.href = `http${url}` } else { next() } });遇到问题(2017-08-10)
当第一次进入页面时 ,如果不是处在第一个 tab 时,history 里面记录的索引就会出现错乱现象
解决办法:事先设置好 首页出现的四个 tab 的索引,设置好 初始的 count 为 4
这样就不会发生索引错乱现象
切换时的一个小问题当左右华东切换时,要注意将各个 tab 页顶层设置 ,position:absolute,这样才会排在同一排,否则会出现一上一下的现象
具体实现查看 github-项目地址 里面的 main.js app.vue通过 watch 选项监测 $route 动态的改变transitionName 的值
sessionStorage 和 localStorage 本地存储问题watch: { "$route" (to, from) { console.log(to,from); this.transitionName = JSON.parse(window.sessionStorage.__router__).transitionName; } }, 样式: //微信切换样式 ,左右滚动 //前进动画样式 .forward-enter-active,.forward-leave-active{ transition: all 0.3s; } .forward-enter{ transform: translateX(100%); } .forward-leave-to{ transform: translateX(-100%); } // 后退动画样式 .reverse-enter-active,.reverse-leave-active{ transition: all 0.3s; } .reverse-enter{ transform: translateX(-100%); } .reverse-leave-to{ transform: translateX(100%); }
sessionStorage 本地会话存储,会话结束-浏览器关闭(不包括刷新页面,恢复页面),存储结果清除
localStorage 本地存储,除非手动清除,否则永不清除
大小传说 5M
方法1:getItem(key),setItem(key,value),clear()
方法2:利用 . 或 [] 语法,访问或设置
事件:
如果你监听storage变更事件你就会发现,当数据发生变化时本页是监听不到storage事件变更消息的。而同域的其他打开的页面反而监听到了该消息。悲剧不?
解决办法百度
storage只能存储字符串 不能存储其他类型数据存储对象,读取对象:
let history = window.sessionStorage.__router__; if(!history){ history = {}; }else{ //读取 history = JSON.parse(history); } //存储 history = JSON.stringify(history); window.sessionStorage.__router__ = history;activated 钩子
在
keep-alive 组件在第二次渲染时不会触发 create mounted updated 钩子
但是会触发 activated 钩子
使用场景: 列表页==> 详情页的切换
第一次从列表页进详情页时会加载数据 触发 created,mounted,updated 钩子
第二次以上钩子就不会被触发了, 需要加上一个 activated 生命周期钩子,在里面加载请求数据
路由跳转时 需要用到 动态路由 即在 路径后面加个 id
我用query 进行传递参数,如果不主动传递参数,跳转后的子页面刷新时数据就丢失了(原计划用 vuex 做收藏功能)
index.js {path: "/newsDetails/:key", name: "newsDetails",component:newsDetails },
导航写法:
或者//路由外链
列表页 ==> 详情页
从列表页到详情页不适合用嵌套路由嵌套路由写法
因为其是两个多带带的页面,并不会同时出现在一屏上
route.js
{path: "/index", name:"index", component: index, children:[ {path: "/index/newsDetails/:id", name: "newsDetails",component:newsDetails }, ] }
index.vue
路由传参:to = ""index/newsDetails" + item.source_url"
不仅仅传递一个动态路由id还可以 通过 params 和 query进行传递,但都会显示在 url上
列表页 ==> 将该项所有参数传递到详情页,可以现将对象数据 序列化为字符串,放在 query li
在详情页时,取值时反序列化,继而可以在详情页里面使用
由于数据是存在 url 里 故可以在刷新页面仍可以拿到数据
路由小结路由中的三个基本概念: route routes router
route 一条路由(单条路由的走向) routes 一组路由(静止的一组路由的集合)
router 是一种机制相当于一个管理者(当用户点击时 去 routes 去执行相应的路由)
普通路由
动态路由
嵌套路由
编程式导航
组件内的挂载到 根实例上的两个对象 路由源信息对象: this.$route 和 路由实例对象 this.$router
父子组件通讯父组件 => 子组件
父组件传递:
简写方式(直接传值)数组形式 ==> : props:["flag"]
默认值写法: 对象形式
props:{ flag:{ type:Bollean, dafault(){ return false; } } }
子组件 ==> 父组件
v-on 绑定 子组件派发而来的事件
父组件接收:
-
methods:{ scroll_to(childmsg){ //执行 。。。 childmsg 为子组件向父组件传递的参数 } }
子组件
methods:{ xxx(){ this.$emit("scrolltoTop","aaa向父组件传递的参数") } }
注意不能直接使用 $on 监听子组件抛出的事件,而必须在模板里使用 v-on 绑定收藏页 ==> vuex
在详情页进行 收藏/取消 操作
将该操作的数据存在 vuex 里,然后存在 localStorage 里,
store.js 里建一个 newsItem字段,值为数组,然后通过 mutations 操作,
向数组里添加或删除元素
在收藏组件里进行渲染
原计划收藏页的新闻是可以 收藏/取消收藏的收藏 存进vuex,取消收藏从vuex里删除
但今日头条的数据结构感觉有点乱
想着真实开发中,后台肯定会返回一个字段告诉该条新闻本人是否已经收藏过
只做了收藏,暂无取消收藏功能,收藏之后存进 vuex ==> localstorage
bug ==> 同一条新闻可重复收藏
vuex 操作流程
store.js
import Vue from "vue" import Vuex from "vuex" import mutations from "./mutations" Vue.use(Vuex); const store = new Vuex.Store({ state:{ //数据管理中心 count:0, }, mutations, //使用处进行 commit getters:{ //外界在此处获得 vuex 数据 nowTime(state){ return new Date() - 0 + "-" + state.count; } } }); export default store;
mutations.js
//全局触发事件 export default { increment (state){ // 只有通过此处的方法才能改变vuex 内的数据 state.count++; }, decrement (state){ state.count--; }, }
使用的时候 引入 import {mapState,mapMutations,mapGetters} from "vuex"
然后通过 this.$store 对象进行操作
vuex 待续。。。 处理资源js 引用图片 必须用 import 导入 import logo.png from "相对路径"
放在 src 目录里的文件都是交由 webpack 处理的
放在 static 目录里面的文件 webpack 不会处理,而是在 build 之后,直接拷贝 相应目录里
所以在 项目里如果要引用 static 目录里的文件 必须要使用绝对路径 /static/[filename]
main.js 里 引用 图片懒加载 的加载中图片时 路径必须为 "./static/img/loading.gif"(我也不知道原因)
具体可参考此回答: vue static目录资源使用
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/87403.html
摘要:这是用高仿今日头条的移动端项目,结合了原生的部分功能以及网页版。前言本人是今日头条的重度用户,在学习过程中,在上看到了很多高仿的好项目。因为数据原因,首页请求的数据接口来自网页版今日头条,修改了一些参数收藏页面数据由本地文件获取。 vue-toutiao 这是用 vue.js 2.0 高仿 今日头条 的移动端项目,结合了原生app的部分功能以及网页版。 前言 本人是 今日头条 的重度用...
摘要:前言上次初学用写了个后台管理,这次便寻思写个移动端的项目。便有了这次的这个项目。然后通过来判断如何动画具体处理异步用来书写跟配置还有一些零零散散的知识点,就不介绍了,具体可以到上查看。个人博客在线观看地址 前言 上次初学用 react 写了个后台管理,这次便寻思写个移动端的项目。便有了这次的这个项目。 这个项目以前写了个 vue 的版本。有兴趣的可以 点击进入 模拟数据用的是 Eas...
摘要:但由于这里仅仅是实现一个,因此存储功能仅通过一个单例类来模拟实现。 本文旨在通过重写GridView,配合系统弹窗实现仿今日头条的频道编辑页面 注:由于代码稍长,本文仅列出关键部分,完整工程请参见【https://github.com/G9YH/YHChannelEdit】 在开始讲解盗版的实现方案前,让我们先来看看正版与盗版的实际使用效果对比,首先是正版 showImg(https:...
阅读 1789·2021-10-20 13:49
阅读 1339·2019-08-30 15:52
阅读 2828·2019-08-29 16:37
阅读 1011·2019-08-29 10:55
阅读 3045·2019-08-26 12:14
阅读 1603·2019-08-23 17:06
阅读 3222·2019-08-23 16:59
阅读 2526·2019-08-23 15:42