Vue.js入门 0x13 实战:知乎日报项目开发-文章详情页
加载内容
右侧的文章内容区域封装成了一个组件。在components目录下新建daily-article.vue组件,它唯一接收唯一的一个prop:id,也就是文章的id,如果id变化了,就说明切换了文章,需要请求新的文章内容。
在app.vue中导入daily-article.vue组件,并在文章列表的Item组件上绑定查看文章事件
//app.vue
<template><div class="daily"><div class="daily-menu"></div><div class="daily-list" ref="list"><template v-if="tyep==='recommend'"><div v-for="list in recommendList"><div class="daily-date">{{formatDay(list.date)}}</div><Item@click.native="handleClick(time.id)"v-for="item in list.stories":data="item":key="item.id"></Item></div></template><template v-if="type==='daily'"><Item@click.native="handleClick(time.id)"v-for="item in list":data="item":key="item.id"></Item></template></div><daily-article :id="articleId"></daily-article></div>
</template>
<script>import $ from './libs/util';import Item from './components/item.vue';import dailyArticle from './components/daily-article.vue';export default{components:{Item,dailyArticle},data(){return {themes:[],showTheme:false,type:'recommend',recommendList:[],list:[],dailyTime:$.getTodayTime(),isLoading:false,articleId:0}},methods:{handleClick(id){this.articleId = id;}}}
</script>
Item是组件,绑定原生事件时要带事件修饰符.native,否则会认为监听的是来自Item组件的定义事件click。
dailyArticle组件在监听到id改变时请求文章内容:
//components/daily-article.vue
<template><div class="daily-article"><div class="daily-article-title">{{data.title}}</div><div class="daily-article-content" v-html="data.body"></div></div>
</template>
<script>import $ from '../libs/util';export default{props:{id:{type:Number,default:0}},data(){return {data:{}}},methods:{getArticle(){$.ajax.get('new/'+this.id).then(res=>{//将文章中的图片地址替换为代理的地址res.body = res.body.replace(/src="http/g,'src="'+$.imgPath+'http');res.body = res.body.replace(/src="https/g,'src="'+$.imgPath+'https');this.data = res;//返回文章顶部window.scrollTo(0,0);})}},watch:{id(val){if(val)this.getArticle();}}};
</script>
//style.css
.daily-article{margin-left: 450px;padding: 20px;
}
.daily-article-title{font-size: 28px;font-weight: bold;color: #222;padding: 10px 0;
}
.view-more a{display: block;cursor: pointer;background: #f5f7f9;text-align: center;color: inherit;text-decoration: none;padding: 4px 0;border-radius: 3px;
}
加载评论
每条评论要显示发表时间,源数据格式为时间戳,需要前端转为相对时间。在daily目录下创建directives目录,并创建time.js文件
//directives/time.js
var Time = {//获取当前时间戳getUnix:function(){var date = new Date();return date.getTime();},//获取今天0点0分0秒的时间戳getTodayUnix:function(){var date = new Date();date.setHours(0);date.setMinutes(0);date.setSeconds(0);date.setMilliseconds(0);return date.getTime();},//获取今年1月1日0点0分0秒的时间戳getYearUnix:function(){var date = new Date();date.setMonth(0);date.setDate(1);date.setHours(0);date.setMinutes(0);date.setSeconds(0);date.setMilliseconds(0);return date.getTime();},//获取标准年月日getLastDate:function(time){var date = new Date(time);var month = date.getMonth()+1<10?'0'+(date.getMonth()+1):date.getMonth()+1;var day = date.getDate()<10?'0'+date.getDate():date.getDate();return date.getFullYear()+'-'+month+'-'+day;},//转换时间getFormatTime:function(timestamp){var now = this.getUnix();var today = this.getTodayUnix();var year = this.getYearUnix();var timer =(now-timestamp)/1000;var tip = '';if(timer<=0){tip='刚刚';}else if(Math.floor(timer/60)<=0){tip='刚刚';}else if(timer<3600){tip = Math.floor(timer/60)+'分钟前';}else if(timer>=3600&&(timestamp-today>=0)){tip = Math.floor(timer/3600)+'小时前';}else if(timer/86400<=31){tip = Math.ceil(timer/86400)+'天前';}else{tip = this.getLastDate(timestamp);}return tip;}
};
export default{bind:function(el,binding){el.innerHTML = Time.getFormatTime(binding.value*1000);el.__timeout__ = setInterval(function(){el.innerHTML = Time.getFormatTime(binding.value*1000);},60000);},unbind:function(el){clearInterval(el.__timeout__);delete el.__timeout__;}
}
//components/daily-article.vue
<template><div class="daily-article"><div class="daily-article-title">{{data.title}}</div><div class="daily-article-content" v-html="data.body"></div><div class="daily-comments" v-show="comments.length"><span>评论({{comments.length}})</span><div class="daily-comment" v-for="comment in comments"><div class="daily-comment-avatar"><img :src="comment.avator"></div><div class="daily-comment-content"><div class="daily-comment-name">{{comment.author}}</div><div class="daily-comment-time" v-time="comment.time"></div><div class="daily-comment-text">{{comment.content}}</div></div></div></div></div>
</template>
<script>import Time from '../directives/time';import $ from '../libs/util';export default{directives:{Time},props:{id:{type:Number,default:0}},data(){return {data:{},comments:[]}},methods:{getArticle(){$.ajax.get('new/'+this.id).then(res=>{//将文章中的图片地址替换为代理的地址res.body = res.body.replace(/src="http/g,'src="'+$.imgPath+'http');res.body = res.body.replace(/src="https/g,'src="'+$.imgPath+'https');this.data = res;//返回文章顶部window.scrollTo(0,0);this.getComments();})},getComments(){this.comments=[];$.ajax.get('story/'+this.id+'/short-comments').then(res=>{this.comments = res.comments.map(comment=>{//将头像的图片地址转为代理地址comment.avatar = $.imgPath+comment.avatar;return comment;});})}},watch:{id(val){if(val)this.getArticle();}}};
</script>
style.css
.daily-comments{margin:10px 0;
}
.daily-comments span{display: block;margin: 10px 0;font-size: 20px;
}
.daily-comment{overflow: hidden;margin-bottom: 20px;padding-bottom: 20px;border-bottom: 1px dashed #e3e8ee;
}
.daily-comment-avatar{width: 50px;height: 50px;float:left;
}
.daily-comment-avatar img{width: 100%;height: 100%;border-radius: 3px;
}
.daily-comment-content{margin-left: 65px;
}
.daily-comment-name{}
.daily-comment-time{color: #9ea7b4;font-size: 14px;margin-top:5px;
}
.daily-comment-text{margin-top: 10px;
}
Vue.js入门 0x13 实战:知乎日报项目开发-文章详情页相关推荐
- vue设置cookie的domain无效_【Vue.js入门到实战教程】16Tailwind 与 Bootstrap 的区别和使用入门...
来源 | https://xueyuanjun.com/post/22065我们知道,从 Laravel 8 开始,自带前端脚手架代码默认兼容 Tailwind CSS 框架,取代了之前的 Boots ...
- js模板字符串自定义类名_【Vue.js 入门到实战教程】07Vue 组件注册 | 基本使用和组件嵌套...
来源 | https://xueyuanjun.com/post/21929除了前面介绍的基本语法之外,Vue.js 还支持通过组件构建复杂的功能模块,组件可以称得上是 Vue.js 的灵魂,是 Vu ...
- vue3项目实战---知乎日报----项目搭建
目录 基础框架和响应式布局 项目介绍 接口文档 vue.config pagejson 初始化公共样式 vuex模块 路由模块 utils公共类库 axios 二次封装 响应式处理 && ...
- Vue+JS+Element UI实战(电商项目1)
目录 1.电商业务概述 2.电商后台管理系统的功能 3.项目初始化步骤 4.后台项目的环境安装配置 4.1. API V1 接口说明 4.2. 支持的请求方法 4.3. 通用返回状态说明 5.测试后 ...
- Vue.js入门教程(适合初学者)
Vue.js入门教程 Vue官网网址:Vue.js 中文网 Vue.js Vue.js是渐进式JavaScript 框架,是一套构建用户界面的渐进式框架.也可以说Vue.js 是一个用来构建网页界面的 ...
- Vue.js入门教程-组件注册
一.组件创建 1.1 创建步骤 创建Vue的组件都有三个基本步骤是 [①创建组件构造器.②注册组件和③使用组件]. 1.2 基本示例 比如,我们创建一个Button组件. // 1. 创建一个组件构造 ...
- React.js 入门与实战课程思维导图
原文发表于我的技术博客 我在慕课网的「React.js 入门与实战之开发适配PC端及移动端新闻头条平台」课程已经上线了,在这里分享了课程中的思维导图,供大家参考. 原文发表于我的技术博客 此导图为课程 ...
- React.js 入门与实战之开发适配PC端及移动端新闻头条平台课程上线了
原文发表于我的技术博客 我在慕课网的「React.js 入门与实战之开发适配PC端及移动端新闻头条平台」课程已经上线了,文章中是目前整个课程的大纲,以后此课程还会保持持续更新,此大纲文档也会保持更新, ...
- Vue.js入门指南(一)
前 言 JRedu 之前用过一段时间的AnglarJS 1.X,在低版本的AngularJS中,脏值检查在变量增多的情况下会影响程序的响应速度.后期的2.X和更高版本在脏值检查等问题上做了优化, ...
最新文章
- mysql 打开文件数_MySQL打开的文件描述符限制
- js实现数据结构及算法之二叉树(Binary Tree)
- 虚拟机下的CentOS环境中安装Node.js
- Discuz! 出现“您当前的访问请求当中含有非法字符“解决方法
- Markdown数学公式大全
- Facebook 实时聊天架构日均处理数十亿条消息!
- sql随机取一条数据
- win10键盘全变成快捷键_电脑键盘灵敏度设置方法
- 前端性能优化(三)——浏览器九大缓存方法
- 橙色——网页效果图设计之色彩索引
- win10系统截图快捷键
- c++语言程序中,main()函数必须放在程序开始的部分,C++多选题(附答案)
- 将word 转换为图片(word to pdf ->pdf to image)
- 计算机辅助教育相关论文,计算机辅助教育论文
- 动态拼图怎么做?如何将多张动图拼接在一起?
- 小觅双目摄像头标准彩色版发布 为移动机器人视觉导航避障优化设计
- 万物皆可集成系列:低代码释放用友深度价值(1)—系统对接集成
- 如何在面试中介绍自己的项目经验(面向java改进版)
- 热烈祝贺上汽通用五菱ASPICE项目通过CL 2级评估
- Linux: 宏:__stringify,字符串化传入参数