当前位置:   article > 正文

Vue(八):头条项目_@hack: true; @import /users/zhangpei/company/workf

@hack: true; @import /users/zhangpei/company/workflow-baseline/ui/src/assets

一、新建项目

与之前的不同之处在于,本次选择自动创建Router,如下:

注:发现在src目录下新增views文件夹。views文件夹和components文件夹都是存放vue页面文件的。区别在于凡是通过router/index.js路由文件引入的.vue文件放入view文件夹,其余放入components文件夹。

二、开发

2.1 安装Vant组件库

组件库地址:vant-contrib.gitee.io/vant/#/zh-CN/theme

执行npm i vant -S

2.2 组件引入

推荐采用方式一引入组件,但是方式一过于麻烦,一般采用方式三。一次性引入vant的所有组件,导致打包的体积大,后期解决该问题。

 将上述代码添加至main.js中

2.3 测试组件库

 将下面代码复制至App.vue中,页面效果实现如上,说明组件引入成功。

  1. <van-button type="primary">主要按钮</van-button>
  2. <van-button type="info">信息按钮</van-button>
  3. <van-button type="default">默认按钮</van-button>
  4. <van-button type="warning">警告按钮</van-button>
  5. <van-button type="danger">危险按钮</van-button>

 2.4 Tabbar和导航栏的创建

2.4.1创建主页Home和用户页User

分别在views文件夹下新建Home和User文件夹,并建立对应的vue文件。

 2.4.2 tabbar标签栏的创建

             

 如上,App.vue中添加占位符和Tabbar。

  1. <template>
  2. <div>
  3. <router-view></router-view>
  4. <van-tabbar route>
  5. <van-tabbar-item to="/" icon="home-o">首页</van-tabbar-item>
  6. <van-tabbar-item to="/user" icon="user-o">我的</van-tabbar-item>
  7. </van-tabbar>
  8. </div>
  9. </template>
  10. <script>
  11. export default {
  12. name: 'App'
  13. }
  14. </script>
  15. <style lang="less" scoped>
  16. </style>

并在index.js中添加路由:

  1. import Vue from 'vue'
  2. import VueRouter from 'vue-router'
  3. import Home from '@/views/Home/Home.vue'
  4. import User from '@/views/User/User.vue'
  5. Vue.use(VueRouter)
  6. const routes = [
  7. { path: '/', component: Home },
  8. { path: '/user', component: User }
  9. ]
  10. const router = new VueRouter({
  11. routes
  12. })
  13. export default router

2.4.3 导航栏的创建

主要存在问题如下:

(1)导航栏固定,这里是通过fixed参数设置

(2)底下的h1字体会被顶部的导航栏和底部的Tabbar标签栏挡住,这里需要设置padding。padding的设置为顺时针,上,右,下,左

(3)样式设置采用审查元素查看,若不生效,可加/deep/

  1. <template>
  2. <div class="home-container">
  3. <van-nav-bar title="头条" fixed/>
  4. <h1>aaa</h1>
  5. <h1>bbb</h1>
  6. </div>
  7. </template>
  8. <script>
  9. export default {
  10. name: 'Home'
  11. }
  12. </script>
  13. <style lang="less" scoped>
  14. .home-container {
  15. padding: 46px 0 50px 0;
  16. .van-nav-bar {
  17. background-color: #007bff;
  18. }
  19. /deep/ .van-nav-bar__title {
  20. color: aliceblue;
  21. }
  22. }
  23. </style>

2.5 axios请求数据

npm i axios -S安装

src目录下新建utils文件夹,并在utils文件夹下新建request.js文件,代码如下:

  1. import axios from 'axios'
  2. const request = axios.create({
  3. baseURL: 'https://www.escook.cn'
  4. })
  5. export default request

Home.vue中引入request.js文件,并定义方法发起axios请求,并在created方法中调用axios请求的方法。

  1. <template>
  2. <div class="home-container">
  3. <van-nav-bar title="头条" fixed/>
  4. </div>
  5. </template>
  6. <script>
  7. import request from '@/utils/request.js'
  8. export default {
  9. name: 'Home',
  10. data() {
  11. return {
  12. // 页码值
  13. page: 1,
  14. // 每页展示的数据条数
  15. limit: 10
  16. }
  17. },
  18. created() {
  19. this.initArticleList()
  20. },
  21. methods: {
  22. async initArticleList() {
  23. const { data: res } = await request.get('/articles', {
  24. params: {
  25. _page: this.page,
  26. _limit: this.limit
  27. }
  28. })
  29. console.log(res, res)
  30. }
  31. }
  32. }
  33. </script>
  34. <style lang="less" scoped>
  35. .home-container {
  36. padding: 46px 0 50px 0;
  37. .van-nav-bar {
  38. background-color: #007bff;
  39. }
  40. /deep/ .van-nav-bar__title {
  41. color: aliceblue;
  42. }
  43. }
  44. </style>

如上,若在我的页面也想调用axios请求'/articles'获取相关数据,则又需要在User.vue重新写一次axios.get....。为了提高可用性,创建API接口:

(1)在src下新建api文件夹,并在api文件夹下新建articleAPI.js文件。articleAPI.js代码如下:

  1. // 文章相关的接口,都封装到这个模块中
  2. import request from '@/utils/request.js'
  3. // 向外导出一个API函数
  4. export const getArticleListAPI = function(_page, _limit) {
  5. return request.get('/articles', {
  6. params: {
  7. _page,
  8. _limit
  9. }
  10. })
  11. }

(2)在Home.vue中引入articleAPI.js中的getArticleListAPI方法,并调用,代码如下:

注:方法引入时两侧需要加大括号

 2.6 文章列表

(1)在src/components文件夹下新建Article文件夹,并在其下新建ArticleInfo.vue组件。

  1. <template>
  2. <div>
  3. <van-cell>
  4. <!-- 标题区域的插槽 -->
  5. <template #title>
  6. <div class="title-box">
  7. <!-- 标题 -->
  8. <span>{{ title }}</span>
  9. <!-- 单张图片 -->
  10. <img :src="cover.images[0]" alt="" class="thumb" v-if="cover.type === 1">
  11. </div>
  12. <!-- 三张图片 -->
  13. <div class="thumb-box" v-if="cover.type === 3">
  14. <img :src="item" alt="" class="thumb" v-for="(item, index) in cover.images" :key="index">
  15. </div>
  16. </template>
  17. <!-- label区域的插槽 -->
  18. <template #label>
  19. <div class="label-box">
  20. <span>作者 {{ author }}&nbsp;&nbsp; {{ cmbCount }} 评论 &nbsp;&nbsp; 发布日期 {{ time }}</span>
  21. <!-- 关闭按钮 -->
  22. <van-icon name="cross"></van-icon>
  23. </div>
  24. </template>
  25. </van-cell>
  26. </div>
  27. </template>
  28. <script>
  29. export default {
  30. name: 'ArticleInfo',
  31. props: {
  32. // 标题
  33. title: {
  34. type: String,
  35. default: ''
  36. },
  37. // 作者
  38. author: {
  39. type: String,
  40. default: ''
  41. },
  42. // 评论数
  43. cmbCount: {
  44. // 通过数组的形式,当前属性定义为多个可能的类型
  45. type: [String, Number],
  46. default: 0
  47. },
  48. // 发布时间
  49. time: {
  50. type: String,
  51. default: ''
  52. },
  53. // 封面的信息对象
  54. cover: {
  55. type: Object,
  56. default: function() {
  57. return { type: 0 }
  58. }
  59. }
  60. }
  61. }
  62. </script>
  63. <style lang="less" scoped>
  64. .label-box {
  65. display: flex;
  66. justify-content: space-between;
  67. align-items: center;
  68. }
  69. .thumb {
  70. width: 113px;
  71. height: 70px;
  72. background-color: #f8f8f8;
  73. object-fit: cover;
  74. }
  75. .title-box {
  76. display: flex;
  77. justify-content: space-between;
  78. align-items: flex-start
  79. }
  80. .thumb-box {
  81. display: flex;
  82. justify-content: space-between;
  83. }
  84. </style>

(2)Home.vue中引入并使用ArticleInfo.vue组件

 注:主要涉及的是props值的传递。

tips:(1)props值类型可设置为数组,定义为多个可能的类型

 (2)父组件在设置属性值时,若原变量名为小驼峰式,最好修改为全部小写,中间加-。如下:

 2.7 上拉加载更多

借助vant中展示组件中的List列表实现上拉加载更多的功能

(1)使用van-list包裹<ArticleInfo>

(2)data中声明:loading(默认true)、finished(默认false)两个属性

(3)onLoad方法定义(page++、请求数据)

(4)修改initArticleList方法(数据拼接、loading属性设置、finished属性设置)

修改后的Home.vue代码如下:

  1. <template>
  2. <div class="home-container">
  3. <van-nav-bar title="头条" fixed/>
  4. <van-list
  5. v-model="loading"
  6. :finished="finished"
  7. finished-text="没有更多了"
  8. @load="onLoad"
  9. >
  10. <ArticleInfo
  11. v-for="item in articleList"
  12. :key="item.art_id" :title="item.title"
  13. :author="item.aut_name"
  14. :cmbCount="item.comm_count"
  15. :time="item.pubdate"
  16. :cover="item.cover">
  17. </ArticleInfo>
  18. </van-list>
  19. </div>
  20. </template>
  21. <script>
  22. import { getArticleListAPI } from '@/api/articleAPI.js'
  23. import ArticleInfo from '@/components/Article/ArticleInfo.vue'
  24. export default {
  25. name: 'Home',
  26. components: {
  27. ArticleInfo
  28. },
  29. data() {
  30. return {
  31. // 页码值
  32. page: 1,
  33. // 每页展示的数据条数
  34. limit: 10,
  35. // 文章列表
  36. articleList: [],
  37. // 是否正在加载下一页数据,loadding为true,则不会反复触发load事件
  38. // 当下一页数据请求回来后,要记得把loading改为false
  39. // 初始值设为true,可以防止首次进入页面时调用load事件
  40. loading: true,
  41. // 所有数据是否加载完成
  42. finished: false
  43. }
  44. },
  45. created() {
  46. this.initArticleList()
  47. },
  48. methods: {
  49. async initArticleList() {
  50. const { data: res } = await getArticleListAPI(this.page, this.limit)
  51. // this.articleList=[旧数据,新数据]
  52. this.articleList = [...this.articleList, ...res]
  53. this.loading = false
  54. if (res.length === 0) {
  55. // 无下一页数据,finished设置为true
  56. this.finished = true
  57. }
  58. },
  59. onLoad() {
  60. console.log('ok')
  61. // 页码值加1
  62. this.page++
  63. // 重新请求数据
  64. this.initArticleList()
  65. }
  66. }
  67. }
  68. </script>
  69. <style lang="less" scoped>
  70. .home-container {
  71. padding: 46px 0 50px 0;
  72. .van-nav-bar {
  73. background-color: #007bff;
  74. }
  75. /deep/ .van-nav-bar__title {
  76. color: aliceblue;
  77. }
  78. }
  79. </style>

2.8 下拉刷新

借助vant中展示组件中的List列表实现下拉刷新更多的功能.

(1)使用van-pull-refresh包裹van-list。并将其disabled属性设置为finished。也就是说当加载完成时,设置下拉刷新不可用

(2)data中定义refreshing属性,初始值设置为false

(3)定义onRefresh方法(page++、请求数据)

(4)修改initArticleList方法。(添加isRefresh入参、判断是下拉刷新还是上拉加载更多。前者是新数据在前,后者是新数据在后)

修改后的Home.vue如下:

  1. <template>
  2. <div class="home-container">
  3. <van-nav-bar title="头条" fixed/>
  4. <van-pull-refresh v-model="refreshing" :disabled="finished" @refresh="onRefresh">
  5. <van-list
  6. v-model="loading"
  7. :finished="finished"
  8. finished-text="没有更多了"
  9. @load="onLoad"
  10. >
  11. <ArticleInfo
  12. v-for="item in articleList"
  13. :key="item.art_id" :title="item.title"
  14. :author="item.aut_name"
  15. :cmbCount="item.comm_count"
  16. :time="item.pubdate"
  17. :cover="item.cover">
  18. </ArticleInfo>
  19. </van-list>
  20. </van-pull-refresh>
  21. </div>
  22. </template>
  23. <script>
  24. import { getArticleListAPI } from '@/api/articleAPI.js'
  25. import ArticleInfo from '@/components/Article/ArticleInfo.vue'
  26. export default {
  27. name: 'Home',
  28. components: {
  29. ArticleInfo
  30. },
  31. data() {
  32. return {
  33. // 页码值
  34. page: 1,
  35. // 每页展示的数据条数
  36. limit: 10,
  37. // 文章列表
  38. articleList: [],
  39. // 是否正在加载下一页数据,loading为true,则不会反复触发load事件
  40. // 当下一页数据请求回来后,要记得把loading改为false
  41. // 初始值设为true,可以防止首次进入页面时调用load事件
  42. loading: true,
  43. // 所有数据是否加载完成
  44. finished: false,
  45. // 是否正在加载下一页数据,refreshing为true,则不会反复触发onRefresh事件
  46. refreshing: false
  47. }
  48. },
  49. created() {
  50. this.initArticleList()
  51. },
  52. methods: {
  53. async initArticleList(isRefresh) {
  54. console.log('------')
  55. console.log(this.page)
  56. const { data: res } = await getArticleListAPI(this.page, this.limit)
  57. // isRefresh为true,证明是下拉刷新,新数据在前
  58. if (isRefresh) {
  59. // this.articleList=[新数据, 旧数据]
  60. this.articleList = [...res, ...this.articleList]
  61. this.loading = false
  62. } else {
  63. // this.articleList=[旧数据,新数据]
  64. this.articleList = [...this.articleList, ...res]
  65. this.loading = false
  66. }
  67. if (res.length === 0) {
  68. // 无下一页数据,finished设置为true
  69. this.finished = true
  70. }
  71. },
  72. onLoad() {
  73. // 页码值加1
  74. this.page++
  75. // 重新请求数据
  76. this.initArticleList(true)
  77. },
  78. onRefresh() {
  79. // 页码值加1
  80. this.page++
  81. // 重新请求数据
  82. this.initArticleList()
  83. }
  84. }
  85. }
  86. </script>
  87. <style lang="less" scoped>
  88. .home-container {
  89. padding: 46px 0 50px 0;
  90. .van-nav-bar {
  91. background-color: #007bff;
  92. }
  93. /deep/ .van-nav-bar__title {
  94. color: aliceblue;
  95. }
  96. }
  97. </style>

至此,购物车项目首页开发完成。

项目完整链接Headline | 黑马头条 - 移动端

三、 定制主题(参考vue官网)

背景:一个组件在多个页面需要引入,如NavBar 导航栏默认背景颜色为白色,如果要修改颜色,则每个页面都需要重复修改。为了解决该问题,提出定制主题的思路。

步骤一 引入样式源文件

定制主题时,需要引入组件对应的 Less 样式文件,修改的是main.js文件。注释原引入index.css文件的行,修改引入文件为index.less文件。

  1. // import 'vant/lib/index.css'
  2. // 引入全部样式
  3. import 'vant/lib/index.less'

步骤二 修改样式变量

本项目为 vue-cli 搭建的项目,在 vue.config.js 中进行配置。根目录下新建 vue.config.js文件。

  1. // vue.config.js
  2. module.exports = {
  3. css: {
  4. loaderOptions: {
  5. less: {
  6. // 若 less-loader 版本小于 6.0,请移除 lessOptions 这一级,直接配置选项。
  7. lessOptions: {
  8. modifyVars: {
  9. // 直接覆盖变量
  10. 'text-color': '#111',
  11. 'border-color': '#eee',
  12. // 或者可以通过 less 文件覆盖(文件路径为绝对路径)
  13. hack: `true; @import "your-less-file-path.less";`,
  14. },
  15. },
  16. },
  17. },
  18. },
  19. };

less版本号查看:package.json搜索less-loader.查看发现小于6.0,移除lessOptions 这一级

  1. // vue.config.js
  2. module.exports = {
  3. css: {
  4. loaderOptions: {
  5. less: {
  6. modifyVars: {
  7. // 直接覆盖变量
  8. // 'text-color': '#111',
  9. // 'border-color': '#eee',
  10. // 或者可以通过 less 文件覆盖(文件路径为绝对路径)
  11. // hack: 'true; @import "your-less-file-path.less";'
  12. }
  13. }
  14. }
  15. }
  16. }

查看vue官网,发现NavBar样式变量中控制背景颜色的变量如下:

方式一:直接覆盖变量。 修改vue.config.js的样式变量:(不采用该方式)

  1. // vue.config.js
  2. module.exports = {
  3. css: {
  4. loaderOptions: {
  5. less: {
  6. modifyVars: {
  7. // 直接覆盖变量
  8. 'nav-bar-background-color': 'red'
  9. }
  10. }
  11. }
  12. }
  13. }

修改后生效,以后NavBar默认颜色为红色。该方法的缺陷在于每次修改完都需要执行npm run serve重启服务器。采用方式二避免该问题。

方式二:新建theme.less文件,并在vue.config.js 中引入。(采用)

(1)在src下新建theme.less文件,并在文件中设置背景颜色和字体颜色

  1. @blue: #007bff;
  2. @nav-bar-background-color: @blue;
  3. @nav-bar-title-text-color: #ecf0f3;

(2)vue.config.js中引入theme.less文件,如下:

  1. // vue.config.js
  2. const path = require('path')
  3. const themePath = path.join(__dirname, './src/theme.less')
  4. module.exports = {
  5. css: {
  6. loaderOptions: {
  7. less: {
  8. modifyVars: {
  9. // 或者可以通过 less 文件覆盖(文件路径为绝对路径)
  10. hack: `true; @import "${themePath}";`
  11. }
  12. }
  13. }
  14. }
  15. }

则通过修改theme.less文件保存后样式直接生效,不需再重启服务器。

四、vue.config.js 相关配置

(1)publicPath设置为'/'或者''。打包后(npm run build)的dist/index.html支持file协议打开,也就是双击本地文件打开。默认是仅支持http协议的。

浏览器输入:D:/vueworkspace/toutiao/dist/index.html可直接访问。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/82655
推荐阅读
相关标签
  

闽ICP备14008679号