一、API 接口注册
1. 注册申请 聚合数据【点击进入】
进行注册、实名制认证后
搜索"新闻头条"【点击进入】
文章图片
申请后获得一个key值
文章图片
2. API 接口说明 接口地址:http://v.juhe.cn/toutiao/index
返回格式:json
请求方式:get/post
请求示例:http://v.juhe.cn/toutiao/index?type=top&key=APPKEY
接口备注:返回头条,社会,国内,娱乐,体育,军事,科技,财经,时尚等新闻信息
3. 请求参数说明
名称 | 必填 | 类型 | 说明 |
---|---|---|---|
key | 是 | string | 应用APPKEY |
type | 否 | string | 类型,shehui(社会),guonei(国内),guoji(国际),yule(娱乐),tiyu(体育)junshi(军事),keji(科技),caijing(财经),shishang(时尚) |
{
"reason": "成功的返回",
"result": {
"stat": "1",
"data": [{
"uniquekey": "6c4caa0c3ba6e05e2a272892af43c00e",
"title": "杨幂的发际线再也回不去了么?网友吐槽像半秃",
"date": "2017-01-05 11:03",
"category": "yule",
"author_name": "腾讯娱乐",
"url": "http://mini.eastday.com/mobile/170105110355287.html?qid=juheshuju",
/*新闻链接,暂支持手机端浏览器访问*/
"thumbnail_pic_s": "http://03.imgmini.eastday.com/mobile/20170105/20170105110355_
806 f4ed3fe71d04fa452783d6736a02b_1_mwpm_03200403.jpeg ",
"thumbnail_pic_s02": "http://03.imgmini.eastday.com/mobile/20170105/20170105110355_
806 f4ed3fe71d04fa452783d6736a02b_2_mwpm_03200403.jpeg ",
"thumbnail_pic_s03": "http://03.imgmini.eastday.com/mobile/20170105/20170105110355_
806 f4ed3fe71d04fa452783d6736a02b_3_mwpm_03200403.jpeg "
},
...
]
}
}
二、新建 Vue-Cli 项目 1. 搭建 Vue-Cli 脚手架 vue-cli 是一个官方发布 vue.js 项目脚手架,使用 vue-cli 可以快速创建 vue 项目
下面介绍 vue-cli 的整个搭建过程
注意:以下内容是基于Vue-cli4.0以上版本的。(1)安装 npm
NPM(node package manager)是随同node.js一起安装的包管理工具,能解决前端代码部署上的很多问题,常见的使用场景有以下几种:
- 允许用户从NPM服务器下载别人编写的第三方包到本地使用
- 允许用户从NPM服务器下载并安装别人编写的命令行程序到本地使用
- 允许用户将自己编写的包或命令行程序上传到NPM服务器供别人使用
从node官网下载并安装node,安装步骤很简单,只要一路next就可以了。 安装完成后,打开命令行工具输入命令node -v,如下图,如果出现对应版本号,就说明安装成功了
C:\Users\Administrator>node -v
v10.16.0
我们所需要的npm也已经安装好了,输入如下命令,显示出npm的版本信息
C:\Users\Administrator>npm -v
6.9.0
到这里node的环境已经安装完了,npm包管理工具也有了,但是由于npm的有些资源被墙,为了更快更稳定,所以我们需要切换到淘宝的npm镜像——cnpm
(2)安装 cnpm
点击进入淘宝的cnpm网站,里面有详细的配置方法。 或者直接在命令行输入:
npm install -g cnpm --registry=https://registry.npm.taobao.org
然后等待,安装完成。 输入cnpm -v,可以查看当前cnpm版本,这个和npm的版本还是不一样的
C:\Users\Administrator>cnpm -v
cnpm@6.1.1
使用cnpm的方法就是,需要用到npm的地方直接使用cnpm替换就可以了
(3)全局安装 vue-cli
全局安装vuecli(就相当与在本机的npm仓库中有了vuecli):
//安装最新@vue/cli版本
npm install -g @vue/cli
//安装指定的@vue/cli版本
npm install -g @vue/cli@4.1.1
安装完成后,使用 vue -V 显示版本号来测试vue是否安装成功
C:\Users\Administrator>vue -V
@vue/cli 4.1.1
2. 创建 Vue-Cli 工程 示例中文件夹在D盘根目录,项目名为
csdn_topnews
(全部小写)- 在命令行下进入到工作空间文件夹中,输入命令,(注意:工程名必须全部小写)
vue create csdn_topnews
- 选择预设模板,这里选择
Manually select features
(手动选择特征)
通过 ↑↓ 箭头选择依赖,按 “空格” 选中,按 “a” 全选,按 “i” 反选
- 选择项目功能,本次示例只选择
Babel
、Router
、Vuex
即可
- Babel:转码器,可以将ES6代码转为ES5代码,可兼容不支持ES6的浏览器
- TypeScript:是JavaScript的超集(.ts文件),包含并扩展了 JavaScript 的语法。需要被编译输出为 JavaScript在浏览器运行
- Progressive Web App (PWA) Support:渐进式Web应用程序
- Router :vue-router(vue路由)
- Vuex :vuex(vue的状态管理模式)
- CSS Pre-processors :CSS 预处理器(如:less、sass)
- Linter / Formatter:代码风格检查和格式化(如:ESlint)
- Unit Testing :单元测试(unit tests)
- E2E Testing :e2e(end to end) 测试
- 选择是否使用 history 形式的路由,也就是询问路径是否带 # 号,这里选择
n
- 询问将依赖文件放在独立文件中,还是 package.json 中,为了保持工程配置文件的整洁性,这里选择
In package.json
- 询问是否将当前选择保存以备下次使用,这里选择
n
文章图片
- 等待安装,最后出现如下图即可
文章图片
3. 安装 axios 框架 (1)axios 介绍
在实际开发中,使用一些封装好的ajax框架,这里选用axios框架
原因是:Vue官方推荐使用 axios 框架
axios框架中文官网:http://www.axios-js.com/
###(2)项目中安装 axios
- 进入项目目录
cd csdn_topnews
- 添加 axios 模块
cnpm install axios --save
文章图片
- 添加 qs 模块,用于处理 post 请求的参数解析
cnpm install qs --save
文章图片
4. 添加配置文件 由于申请的 API 不允许跨域访问,只允许代码内访问,需要加一个代理配置文件
文件名为
vue.config.js
module.exports = {
devServer: {
port: 8080,
proxy: {
'/juheNews': {
target: 'http://v.juhe.cn/', //需要跨域的url
ws: true, //代理webSocket
changeOrigin: true, //允许跨域
pathRewrite: {
'^/juheNews': '' //重写路径
}
}
}
}
}
将文件复制到项目根目录下即可
【截图1 vue.config.js】代理配置
文章图片
三、运行、导入、清空项目 1. 运行项目 在 cmd 项目目录中输入运行命令
npm run serve
等待加载,如图所示
文章图片
复制给出的地址,在浏览器中打开,这里为 http://localhost:8080/
2. 导入到 HBuilder X 中 直接拖拽文件夹或手动导入即可
文章图片
【截图2 目录】项目初始目录
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7ermo728-1615626529265)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1612856664274.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_5aW25aaI44Gu5rC05Y2w,size_12,color_FFCD42,t_100)]
3. 导入 axios、qs 模块 修改
csdn_topnews\src\main.js
文件添加语句
import axios from 'axios'
import qs from 'qs' // 只在发送post请求时用到
Vue.prototype.$axios = axios;
Vue.prototype.$qs = qs;
// 只在发送post请求时用到
【截图3 main.js】添加位置
文章图片
4. 清空模板 (1)删除模板
清空新建项目时自带的参考模板代码
删除主页面:
csdn_topnews\src\components\HelloWorld.vue
删除子组件:
csdn_topnews\src\views\About.vue
和 Home.vue
【截图4 删除模板】
文章图片
(2)修改 App.vue
修改主页面
csdn_topnews\src\App.vue
保留路由出口
,使用路由切换新闻页面删除初始模板的代码和样式
!!!删除下列代码Home |
About !!!删除下列样式
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}#nav {
padding: 30px;
}#nav a {
font-weight: bold;
color: #2c3e50;
}#nav a.router-link-exact-active {
color: #42b983;
}
【截图5 App.vue】
文章图片
(3)修改路由文件
修改路由文件
csdn_topnews\src\router\index.js
【奶妈の自学|[の项目练习]Vue-Cli、API的头条新闻项目】删除引包中的
Home.vue
!!!删除下列引入
import Home from '../views/Home.vue'
重置
routes
变量,将一组路径注释掉作为模板之后使用const routes = [
/*
{
path: '/',
name: 'Home',
component: Home
},
*/
]
【截图6 router\index.js】
文章图片
四、制作导航标签 App.vue 编写头部导航标签页面
csdn_topnews\src\App.vue
部分(1)
介绍 template 的作用是模板占位符,可以包裹元素,循环过程中,template 不会被渲染到页面上注意:
内容要求
标签中内容必须被一个大
包住,即只能有一个根的
,否则会报错具体介绍:vue 中 template 的作用及使用【点击进入】
(2)
介绍
标签定义文档或者文档的一部分区域的页眉
元素应该作为介绍内容或者导航链接栏的容器在一个文档中,可以定义多个
元素注释:
标签不能被放在
、
或者另一个
元素内部(3)
介绍
标签定义导航链接的部分并不是所有的 HTML 文档都要使用到
元素,
元素只是作为标注一个导航链接的区域在不同设备上(手机或者PC)可以制定导航链接是否显示,以适应不同屏幕的需求
(4)v-bind 样式绑定 介绍 菜鸟教程:Vue.js 样式绑定【点击进入】
class 与 style 是 HTML 元素的属性,用于设置元素的样式,可以用 v-bind 来设置样式属性
Vue.js v-bind 在处理 class 和 style 时,表达式的结果类型除了字符串之外,还可以是对象或数组
其中,
v-bind:class
可以简写为 :class
.类名 {
样式内容;
}
(5)v-on 事件处理器 介绍 菜鸟教程:Vue.js 事件处理器【点击进入】
事件监听可以使用 v-on 指令
通常需要使用一个方法来调用 JavaScript 方法,v-on 可以接收一个定义的方法来调用 ,也可以用内联 JavaScript 语句
v-on 可以接收一个定义的方法来调用
在 methods 对象中定义方法
<元素 v-on:触发方式="方法名/方法名(参数)/表达语句">元素内容元素><元素 @触发方式="方法名/方法名(参数)/表达语句">元素内容元素>
{{ 数据 }}
(6)v-on 自定义事件 介绍 菜鸟教程:Vue.js 组件(略)【点击进入】
菜鸟教程:Vue.js 组件 - 自定义事件【点击进入】
父组件是使用 props 传递数据给子组件
如果子组件要把数据传递回去,就需要使用自定义事件
可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口 (Events interface),即:
- 使用
$on(eventName)
监听事件 - 使用
$emit(eventName)
触发事件
以下实例中子组件和它外部完全解耦,实现它触发一个父组件关心的内部事件
<子组件模板名 v-on:自定义触发名="父组件方法名">子组件模板名>
{{ 父组件数据 }}
代码编写 App.vue 中的
块代码新闻头条
nav:导航栏,负责导航栏横条样式
navinit:被选中的新闻种类选项块的 class 样式,包括字体边红、下方出现红色横线
isActive:App.vue 的 data 中的字符串变量,可更改为 ‘topNews’(默认) 或 ‘typeNews’
changeNav(param):App.vue 的 methods 中的方法,param 意为 “参数”,功能有两点
- 更改 isActive 的变量值 (‘topNews’ 或 ‘typeNews’)
- 路由跳转 (this.$router.push) 至对应页面 (’/topNews’ 或 ‘/typeNews’)
部分代码编写 (1)清空默认样式
html,body,div,header,nav,h1,h2,h3,h4,h5,h6,ul,li {
margin: 0;
padding: 0;
font-family: "微软雅黑";
}
注意:padding 对
影响 将
的 padding 属性设为 0 时,
的左侧列表圆点会取消即
li {padding: 0;
}
相当于 li {list-style: none;
}
(2)设置
样式
header {
width: 100%;
height: 48px;
background-color: #E03D3E;
display: flex;
justify-content: center;
/*弹性容器内容居中*/
align-items: center;
/*弹性容器纵向对齐*/
font-size: 20px;
color: #fff;
letter-spacing: 4px;
/*设置字间距*/
}
1. display: flex 属性 介绍 菜鸟教程:CSS3 弹性盒子(Flex Box)【点击进入】
弹性盒子是 CSS3 的一种新的布局模式
是一种当页面需要适应不同的屏幕大小以及设备类型时确保元素拥有恰当的行为的布局方式
引入弹性盒布局模型的目的是提供一种更加有效的方式来对一个容器中的子元素进行排列、对齐和分配空白空间
弹性盒子由弹性容器 (Flex container) 和弹性子元素 (Flex item) 组成
弹性容器通过设置 display 属性的值为 flex 或 inline-flex 将其定义为弹性容器
弹性容器内包含了一个或多个弹性子元素
**注意:**弹性容器外及弹性子元素内是正常渲染的。弹性盒子只定义了弹性子元素如何在弹性容器内布局
弹性子元素默认在弹性盒子内一行显示,从左到右,默认情况每个容器只有一行
2. justify-content 属性 介绍 菜鸟教程:CSS3 弹性盒子(Flex Box)【点击进入】
内容对齐(justify-content)属性应用在弹性容器上,把弹性项沿着弹性容器的主轴线(main axis)对齐
justify-content: flex-start | flex-end | center | space-between | space-around
- flex-start:
弹性项目向行头紧挨着填充。这个是默认值。第一个弹性项的main-start外边距边线被放置在该行的main-start边线,而后续弹性项依次平齐摆放。
- flex-end:
弹性项目向行尾紧挨着填充。第一个弹性项的main-end外边距边线被放置在该行的main-end边线,而后续弹性项依次平齐摆放
- center:
弹性项目居中紧挨着填充。(如果剩余的自由空间是负的,则弹性项目将在两个方向上同时溢出)
- space-between:
弹性项目平均分布在该行上。如果剩余空间为负或者只有一个弹性项,则该值等同于flex-start。否则,第1个弹性项的外边距和行的main-start边线对齐,而最后1个弹性项的外边距和行的main-end边线对齐,然后剩余的弹性项分布在该行上,相邻项目的间隔相等
- space-around:
弹性项目平均分布在该行上,两边留有一半的间隔空间。如果剩余空间为负或者只有一个弹性项,则该值等同于center。否则,弹性项目沿该行分布,且彼此间隔相等(比如是20px),同时首尾两边和弹性容器之间留有一半的间隔(1/2*20px=10px)
文章图片
3. align-items 属性 介绍 菜鸟教程:CSS3 弹性盒子(Flex Box)【点击进入】
align-items
设置或检索弹性盒子元素在侧轴(纵轴)方向上的对齐方式align-items: flex-start | flex-end | center | baseline | stretch
- flex-start:
弹性盒子元素的侧轴(纵轴)起始位置的边界紧靠住该行的侧轴起始边界 - flex-end:
弹性盒子元素的侧轴(纵轴)起始位置的边界紧靠住该行的侧轴结束边界 - center:
弹性盒子元素在该行的侧轴(纵轴)上居中放置(如果该行的尺寸小于弹性盒子元素的尺寸,则会向两个方向溢出相同的长度) - baseline:
如弹性盒子元素的行内轴与侧轴为同一条,则该值与 ‘flex-start’ 等效。其它情况下,该值将参与基线对齐 - stretch:
如果指定侧轴大小的属性值为 ‘auto’,则其值会使项目的边距盒的尺寸尽可能接近所在行的尺寸,但同时会遵照 ‘min/max-width/height’ 属性的限制
文章图片
4. letter-spacing 属性 介绍 菜鸟教程:CSS letter-spacing 属性【点击进入】
letter-spacing 属性增加或减少字符间的空白(字符间距)
- normal: 默认,规定字符间没有额外的空间
- length : 定义字符间的固定空间(允许使用负值)
- inherit : 规定应该从父元素继承 letter-spacing 属性的值
文章图片
(3)设置
样式 导航栏整体样式nav {
width: 100%;
height: 56px;
display: flex;
justify-content: center;
align-items: center;
}
文章图片
注意:
的 flex 对
影响 当
为 flex,而
不是 flex 时,
的左侧圆点还是会溢出显示出来解决方法:在
继续设置子弹性盒子,或直接设置
为 list-style: none;
(4)设置 nav ul li 样式 导航栏选项文字样式
nav ul {
width: 160px;
height: 26px;
display: flex;
justify-content: space-between;
}nav ul li {
width: 70px;
height: 26px;
display: flex;
justify-content: center;
align-items: center;
}
带背景颜色区分效果
文章图片
实际效果
文章图片
(5)设置被选中标签样式 navinit
.navinit {
color: #E03D3E;
border-bottom: solid 2px #E03D3E;
}
测试效果 可将其中一个的样式绑定的判断条件设为 true,如:
头条新闻
保存后刷新即可,被选中是文字颜色变红,并且下方有红色横线
文章图片
export default { }:可从 App.vue 模块导出的 vue 数据,即 .js 文件可以导入 (import) 的数据
isActive:App.vue 的 data 中的字符串变量,可更改为 ‘topNews’(默认) 或 ‘typeNews’
created( ) { }:vue.js 的一个生命周期钩子函数
path:通过 location.href 获取存储当前文档的完整的 URL
route:获取 path 的尾部地址,即最后一个
/
后的字符串(不包括 /
)changeNav(param) { }:调用方法将 isActive 变量和路由地址根据传参 param 更改
this.$router.push( ):相当于
实现不同 vue 页面输出在
中【截图7 App.vue 完成】
文章图片
效果测试
(1)新建 TopNews.vue 在 \src\views 中新建 vue 文件,命名为 TopNews.vue
TopNews
【截图8 TopNews.vue】
文章图片
(2)新建 TypeNews.vue 在 \src\views 中新建 vue 文件,命名为 TypeNews.vue
TypeNews
【截图9 TypeNews.vue】
文章图片
(3)编写 router\index.js 编写 \src\router\index.js 文件
import Vue from 'vue'
import VueRouter from 'vue-router'import TopNews from '../views/TopNews.vue'
import TypeNews from '../views/TypeNews.vue'Vue.use(VueRouter)const routes = [{
path: '/',
name: 'Home',
component: TopNews
}, {
path: '/topNews',
name: 'TopNews',
component: TopNews
}, {
path: '/typeNews',
name: 'TypeNews',
component: TypeNews
}]const router = new VueRouter({
routes
})export default router
TopNews、TypeNews:用于引用两个 vue 文件的变量
import 命令要提升到整个模块的头部,首先执行
Vue.use(VueRouter):使用模块化机制编程,导入 Vue 和 VueRouter
routes: 一组路由,把下面的每一条路由组合起来,形成一个数组
- path:配置路径
- component:组件
{
path: "/user/:id",
name: "user",
component: user
}
命名路由的使用,在router-link 中 to 属性就可以使用对象
User123 User
【截图10 router\index.js 完成】
文章图片
(4)效果截图 项目运行方法 在项目所在根目录运行 cmd,输入 npm run serve 运行
文章图片
等待加载,运行成功后显示如下信息
文章图片
在浏览器输入提示的 Local 地址即可访问
- 默认界面效果
文章图片
- 点击”头条新闻”效果
文章图片
- 点击”分类新闻”效果
文章图片
五、制作分页页面 1. 列表组件 NewsList.vue “头条新闻”和“分类新闻“中都包含了新闻列表,应使用组件,效果如下所示
文章图片
(1)src\components 组件 介绍
菜鸟教程:Vue.js 组件【点击进入】
组件(Component)是 Vue.js 最强大的功能之一
组件可以扩展 HTML 元素,封装可重用的代码
注册一个全局组件语法格式如下:
Vue.component(tagName, options)
tagName 为组件名,options 为配置选项
注册后,可以使用以下方式来调用组件:
1. 全局组件
src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js">
>
// 注册
Vue.component('runoob', {
template: '自定义组件!'
})
// 创建根实例
new Vue({
el: '#app'
})
文章图片
2. 局部组件
src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js">
>
var Child = {
template: '局部组件!'
}
// 创建根实例
new Vue({
el: '#app',
components: {
// 将只在父模板可用
'runoob': Child
}
})
文章图片
3. prop prop 是子组件用来接受父组件传递过来的数据的一个自定义属性
父组件的数据需要通过 props 把数据传给子组件
子组件需要显式地用 props 选项声明 “prop”
src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js">
>
// 注册
Vue.component('child', {
// 声明 props
props: ['message'],
// 同样也可以在 vm 实例中像 “this.message” 这样使用
template: '{{ message }}'
})
// 创建根实例
new Vue({
el: '#app'
})
文章图片
4. 动态 prop 类似于用 v-bind 绑定 HTML 特性到一个表达式
也可以用 v-bind 动态绑定 props 的值到父组件的数据中
每当父组件的数据变化时,该变化也会传导给子组件
src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js">
>
// 注册
Vue.component('child', {
// 声明 props
props: ['message'],
// 同样也可以在 vm 实例中像 “this.message” 这样使用
template: '{{ message }}'
})
// 创建根实例
new Vue({
el: '#app',
data: {
parentMsg: '动态prop数据'
}
})
文章图片
以下实例中使用 v-bind 指令将 todo 传到每一个重复的组件中
其中 todo 为自定义变量
注意:prop 是单向绑定的 prop 是单向绑定的,当父组件的属性变化时,将传导给子组件,但是不会反过来
src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js">
>
Vue.component('todo-item', {
props: ['todo'],
template: '{{ todo.text }} '
})
new Vue({
el: '#app',
data: {
sites: [{
text: 'Runoob'
},
{
text: 'Google'
},
{
text: 'Taobao'
}
]
}
})
文章图片
5. prop 验证 组件可以为 props 指定验证要求
为了定制 prop 的验证方式,可以为 props 中的值提供一个带有验证需求的对象,而不是一个字符串数组
当 prop 验证失败的时候,(开发环境构建版本的) Vue 将会产生一个控制台的警告
Vue.component('my-component', {
props: {
// 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
propA: Number,
// 多个可能的类型
propB: [String, Number],
// 必填的字符串
propC: {
type: String,
required: true
},
// 带有默认值的数字
propD: {
type: Number,
default: 100
},
// 带有默认值的对象
propE: {
type: Object,
// 对象或数组默认值必须从一个工厂函数获取
default: function() {
return {
message: 'hello'
}
}
},
// 自定义验证函数
propF: {
validator: function(value) {
// 这个值必须匹配下列字符串中的一个
return ['success', 'warning', 'danger'].indexOf(value) !== -1
}
}
}
})
type 可以是以下原生构造器:
String
Number
Boolean
Array
Object
Date
Function
Symbol
( 表示独一无二的值,用来定义对象的唯一属性名【菜鸟教程链接】 )
6. filters 过滤器 Vue.js 允许你自定义过滤器,被用作一些常见的文本格式化
由“管道符”指示,格式如下:
{{ 原数据 | 过滤方法 }}
过滤器函数接受表达式的值作为第一个参数
过滤器可以串联:
{{ message | filterA | filterB }}
过滤器是 JavaScript 函数,因此可以接受参数:
{{ message | filterA('arg1', arg2) }}
message 是第一个参数,字符串 ‘arg1’ 将传给过滤器作为第二个参数, arg2 表达式的值将被求值然后传给过滤器作为第三个参数
例:对输入的字符串第一个字母转为大写
{{ message | capitalize }}
文章图片
(2)代码编写
编写新闻列表模板组件
csdn_topnews\src\components\NewList.vue
部分
-
文章图片
{{item.title | titleFilter}}
{{item.author_name}} {{item.date}}
data:子组件传给父组件(即 NewList.vue)的值(prop),具体的值为从 API 接口返回的 JSON 数据中的 data 键值对数组(可参考返回示例)
@click:v-on:click 的缩写
toNews(url):NewList.vue 中的方法(method),用于跳转至新闻详情页
item.url:API 接口返回的 JSON 数据中 data 内的 “'url” 项值(可参考返回示例),存放单条新闻的详情页的链接
class=“img-box”:列表行左侧的新闻图片部分
item.thumbnail_pic_s:API 接口返回的 JSON 数据中 data 内的 “'thumbnail_pic_s” 项值(可参考返回示例),存放单条新闻的标题缩略图
class=“text-box”:列表行右侧的新闻标题文本部分
item.title:API 接口返回的 JSON 数据中 data 内的 “'title” 项值(可参考返回示例),存放单条新闻的标题文本
{{item.title | titleFilter}}:相当于 titleFilter(item.title) 且返回值为过滤后的 item.title
titleFilter(value):过滤器,功能为长度大于 24 时,将后面的文本省略为 ‘…’
data:子组件传给父组件(即 NewList.vue)的值(prop),具体的值为从 API 接口返回的 JSON 数据中的 data 键值对数组(可参考返回示例)
toNews(url):NewList.vue 中的方法(method),用于跳转至新闻详情页
substr(start,length):在字符串中抽取从 start 下标开始的指定 length 个字符
部分
ul {
width: 100%;
}ul li {
box-sizing: border-box;
padding: 6px;
width: 100%;
height: 93px;
display: flex;
border-bottom: dashed 1px #AAA;
user-select: none;
cursor: pointer;
}ul li .img-box {
flex: 0 0 100px;
height: 80px;
}ul li .img-box img {
width: 100px;
height: 80px;
}ul li .text-box {
flex: 1;
box-sizing: border-box;
padding-left: 10px;
}ul li .text-box h3 {
font-size: 16px;
font-weight: 300;
}ul li .text-box p {
font-size: 14px;
text-align: right;
}
scoped:布尔属性, 使用该属性,则样式仅仅应用到 style 元素的父元素及其子元素 【菜鸟教程】
box-sizing:属性允许以某种方式定义某些元素,以适应指定区域【菜鸟教程】
- 语法:
box-sizing: content-box|border-box|inherit;
- content-box:指定元素的宽度和高度(最小/最大属性)适用于box的宽度和高度,元素的填充和边框布局和绘制指定宽度和高度除外
- border-box:指定宽度和高度(最小/最大属性)确定元素边框,即对元素指定宽度和高度包括了 padding 和 border,通过从已设定的宽度和高度分别减去边框和内边距才能得到内容的宽度和高度
- inherit:指定 box-sizing 属性的值,从父元素继承
user-select: 属性控制用户能否选中文本【html中文网】
- 语法:
user-select: none|text|all|element;
- none:文本不能被选择
- text: 可以选择文本
- all:当所有内容作为一个整体时可以被选择。如果双击或者在上下文上点击子元素,那么被选择的部分将是以该子元素向上回溯的最高祖先元素
- element:可以选择文本,但选择范围受元素边界的约束
flex:属性用于设置或检索弹性盒模型对象的子元素如何分配空间【菜鸟教程】
- flex 属性是 flex-grow、flex-shrink、flex-basis 属性的简写属性,如果元素不是弹性盒模型对象的子元素,则 flex 属性不起作用
- 语法:
flex: flex-grow flex-shrink flex-basis|auto|initial|inherit;
- flex-grow:一个数字,规定项目将相对于其他灵活的项目进行扩展的量
- flex-shrink:一个数字,规定项目将相对于其他灵活的项目进行收缩的量
- flex-basis:项目的长度,合法值:“auto”、“inherit” 或一个后跟 “%”、“px”、“em” 或任何其他长度单位的数字
- auto:与 1 1 auto 相同
- none:与 0 0 auto 相同。
- initial:设置该属性为它的默认值,即为 0 1 auto
- inherit:从父元素继承该属性
文章图片
【截图11 components\NewList.vue 完成】
文章图片
2. 完善头条新闻 TopNews.vue (1)分页头部图片素材
https://img-blog.csdnimg.cn/20210310152819703.png
文章图片
(2)Vue.js Ajax(axios) 介绍
菜鸟教程:Vue.js Ajax(axios)【点击进入】
Vue.js 2.0 版本推荐使用 axios 来完成 ajax 请求
Axios 是一个基于 Promise 的 HTTP 库,可以用在浏览器和 node.js 中
注意:跨域问题 跨域指浏览器不能执行其他网站的脚本,未配置代理情况下以下代码仅可在菜鸟教程编辑器中成功运行
1. GET 方法 简单读取 JSON 数据 案例地址为
https://www.runoob.com/try/ajax/json_demo.json
文章图片
src="http://img.readke.com/220905/140131K38-46.jpg">
src="http://img.readke.com/220905/1401311038-47.jpg">
{{ info }}
type="text/javascript">
new Vue({
el: '#app',
data() {
return {
info: null
}
},
mounted() {
axios
.get('https://www.runoob.com/try/ajax/json_demo.json')
.then(response => (this.info = response))
.catch(function(error) { // 请求失败处理
console.log(error);
});
}
})
文章图片
使用 response.data 读取 JSON 数据
src="http://img.readke.com/220905/140131K38-46.jpg">
src="http://img.readke.com/220905/1401311038-47.jpg">
{{ site.name }}
type="text/javascript">
new Vue({
el: '#app',
data() {
return {
info: null
}
},
mounted() {
axios
.get('https://www.runoob.com/try/ajax/json_demo.json')
.then(response => (this.info = response.data.sites))
.catch(function(error) { // 请求失败处理
console.log(error);
});
}
})
文章图片
传递参数说明
// 直接在 URL 上添加参数 ID=12345
axios.get('/user?ID=12345')
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
// 也可以通过 params 设置参数:
axios.get('/user', {
params: {
ID: 12345
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
2. POST 方法 简单读取 JSON 数据 案例地址为
https://www.runoob.com/try/ajax/demo_axios_post.php
文章图片
src="http://img.readke.com/220905/140131K38-46.jpg">
src="http://img.readke.com/220905/1401311038-47.jpg">
{{ info }}
type="text/javascript">
new Vue({
el: '#app',
data() {
return {
info: null
}
},
mounted() {
axios
.post('https://www.runoob.com/try/ajax/demo_axios_post.php')
.then(response => (this.info = response))
.catch(function(error) { // 请求失败处理
console.log(error);
});
}
})
文章图片
传递参数说明
axios.post('/user', {
firstName: 'Fred',// 参数 firstName
lastName: 'Flintstone'// 参数 lastName
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
3. 执行多个并发请求
function getUserAccount() {
return axios.get('/user/12345');
}
function getUserPermissions() {
return axios.get('/user/12345/permissions');
}
axios.all([getUserAccount(), getUserPermissions()])
.then(axios.spread(function (acct, perms) {
// 两个请求现在都执行完成
}));
4. axios API 可以通过向 axios 传递相关配置来创建请求
axios(config)
// 发送 POST 请求
axios({
method: 'post',
url: '/user/12345',
data: {
firstName: 'Fred',
lastName: 'Flintstone'
}
});
//GET 请求远程图片
axios({
method:'get',
url:'http://bit.ly/2mTM3nY',
responseType:'stream'
})
.then(function(response) {
response.data.pipe(fs.createWriteStream('ada_lovelace.jpg'))
});
axios(url[, config])
// 发送 GET 请求(默认的方法)
axios('/user/12345');
(3)箭头函数 介绍
菜鸟教程:JavaScript 函数定义【点击进入】
ES6 新增了箭头函数,箭头函数表达式的语法比普通函数表达式更简洁
(参数1, 参数2, …, 参数N) => { 函数声明 }(参数1, 参数2, …, 参数N) => 表达式(单一)
// 相当于:(参数1, 参数2, …, 参数N) =>{ return 表达式;
}
当只有一个参数时,圆括号是可选的
(单一参数) => {函数声明}
单一参数 => {函数声明}
没有参数的函数应该写成一对圆括号
() => {函数声明}
有的箭头函数都没有自己的 this。 不适合定义一个对象的方法
当使用箭头函数的时,箭头函数会默认绑定外层 this 的值,所以在箭头函数中 this 的值和外层的 this 是一样的
箭头函数是不能提升的,所以需要在使用之前定义
使用 const 比使用 var 更安全,因为函数表达式始终是一个常量
如果函数部分只是一个语句,则可以省略 return 关键字和大括号 {},这样做是一个比较好的习惯箭头函数表达式的语法比普通函数表达式更简洁
(4)代码编写
编写头条新闻部分
csdn_topnews\src\views\TopNews.vue
部分
文章图片
NewList:列表组件模板,需要在
import NewsList from ‘…/components/NewsList’:引入组件文件(省略
.vue
),别名为 NewListsnewsList[] = response.data.reult.data:根据 API 接口返回的数据提取 data(可参考返回示例)
文章图片
'/juheNews/toutiao/index'
:/juheNews
为重写的路径(可参考 vue.config.js),/toutiao/index
根据请求示例编写(可参考聚合数据请求示例编写)文章图片
文章图片
params:{type:'top',key:'获取的key'}
:参数在 get 请求中变为 toutiao/index?type=top&key=获取的key
response=>{this.newsList=response.data.result.data;
}
:相当于 function(response){this.newList=response.data.result.data;
}
components:{NewsList}
:声明组件,NewList 为引入模板组件后的别名
部分
img {
width: 100%;
height: 100px;
display: block;
}
由于头条新闻也仅由头部图片和新闻列表组成,新闻列表部分的 CSS 样式已在模板组件
components\NewList.vue
中完成,所以只需定义头部图片样式即可效果截图
文章图片
###【截图12 TopNews.vue 完成】
文章图片
3. 完善分类新闻 TypeNews.vue 代码编写
部分
文章图片
-
{{item.name}}
:头部图片部分,根据新闻类别改变图片和链接
和
文章图片
:图片和链接随 data 中的 news[] 内容改变而立即产生改变
:分类选择按钮部分,按钮由
组成,点击后触发头部图片、新闻列表的更改v-for="item in typeList"
:typeList 为 data 中的 (id,name) 键值对组,其中 id 作为参数传入 API 请求格式的 type,name 作为按钮的显示内容:class="{typeinit:isAlive==item.id}"
:使用 v-bind 判断该
按钮的 item.id 值是否与 data 中的 isAlive 相同,typeinit 为选中按钮的 CSS 样式,实现单独改变选中按钮的样式@click="change(item.id)"
:change(id) 方法更改 data 中的 isAlive 值,并且更换获取 API 数据时的 type 值
isAlive:用于判断分类按钮的样式,默认为
'shehui'
news:从 newList[] 中随机抽取一条存入 news,用于头部新闻图片
Math.floor():返回不大于的最大整数
Math.random(): 返回介于 0(包含)~ 1(不包含)之间的一个随机数
change(id):更改 data 中的 isAlive 值实现按钮样式变换,并且更换获取 API 数据时的 type 值实现新闻列表内容更改
部分
.news-img img {
width: 100%;
height: 200px;
display: block;
}.type-news {
width: 100%;
margin-top: 8px;
}.type-news ul {
width: 100%;
display: flex;
justify-content: center;
flex-wrap: wrap;
}.type-news ul li {
box-sizing: border-box;
width: 48px;
height: 22px;
border: solid 1px #E03D3E;
border-radius: 11px;
margin: 5px 10px;
font-size: 14px;
color: #E03D3E;
display: flex;
justify-content: center;
align-items: center;
}.typeinit {
background-color: #E03D3E;
color: #fff !important;
/*!important:将优先级提升最高*/
}
效果截图
文章图片
【截图13 TypeNews.vue 完成】
文章图片
六、整体效果 默认打开页 / "头条新闻"页 / 下滑效果
文章图片
"分类新闻"页 / 分类按钮切换 / 点击进入新闻
{id: ‘caijing’,name: ‘财经’},
{id: ‘shishang’,name: ‘时尚’}],
isAlive: ‘shehui’,
newsList: [],
news: {}
}
},
created() {
this.getNews(‘shehui’);
},
methods: {
getNews(type) {
this.$axios.get(’/juheNews/toutiao/index’, {
params: {
type: type,
key: ‘获取的key’
}
}).then(response => {
this.newsList = response.data.result.data;
this.news = this.newsList[Math.floor(Math.random() * this.newsList.length)];
})
.catch(error => {
console.log(error);
});
},
change(id) {
this.isAlive = id;
this.getNews(id);
}
},
components: {
NewsList
}
}
isAlive:用于判断分类按钮的样式,默认为 `'shehui'`news:从 newList[] 中随机抽取一条存入 news,用于头部新闻图片Math.floor():返回不大于的最大整数 Math.random(): 返回介于 0(包含)~ 1(不包含)之间的一个随机数change(id):更改 data 中的 isAlive 值实现按钮样式变换,并且更换获取 API 数据时的 type 值实现新闻列表内容更改---#### `` 部分```vue.news-img img {
width: 100%;
height: 200px;
display: block;
}.type-news {
width: 100%;
margin-top: 8px;
}.type-news ul {
width: 100%;
display: flex;
justify-content: center;
flex-wrap: wrap;
}.type-news ul li {
box-sizing: border-box;
width: 48px;
height: 22px;
border: solid 1px #E03D3E;
border-radius: 11px;
margin: 5px 10px;
font-size: 14px;
color: #E03D3E;
display: flex;
justify-content: center;
align-items: center;
}.typeinit {
background-color: #E03D3E;
color: #fff !important;
/*!important:将优先级提升最高*/
}
效果截图
文章图片
【截图13 TypeNews.vue 完成】
文章图片
六、整体效果 默认打开页 / "头条新闻"页 / 下滑效果
文章图片
"分类新闻"页 / 分类按钮切换 / 点击进入新闻
完成!
推荐阅读
- Vue|Vue语法模板(样式绑定,事件处理器,表单,自定义组件,组件通信)
- 服务器|Springboot+redis+Vue在Linux服务器下进行部署
- Vue|vue - props配置项\ mixin\插件\scoped
- vue|vue中用ref实现父子组件、孙组件、兄弟组件、非亲子孙组件互相调用的方法
- 前端|浅谈函数式编程柯里化的魔法
- vue框架|vue入门
- Vue|优秀的Vue UI组件库
- vue|最简单的分页组件-基于 elementui 的分页二次封装
- vue|Vue3按需引入ElementUI