简单黑马头条项目

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、搭建环境
      • (一) 准备工具
      • (二)下载工具
  • 二、使用步骤
    • (一)创建项目
    • (二)下载插件
    • (三)编写主页面
      • 步骤
      • 页面效果
    • (四)编写功能
      • 路由功能实现页面的切换
      • 调用接口,获取数据
        • 封装`request.js`
        • 封装`articleAPI.js`
        • 调用接口,获取数据
      • 将数据渲染在`home.vue`的页面上
      • 实现下拉刷新数据和上拉刷新数据的功能
      • 改变Vant的默认样式
      • github地址


前言

运用vue创建简单黑马头条的项目

一、搭建环境

(一) 准备工具

  • VsCode软件
  • Node.js
  • Vue.js
  • Vant3
  • Vue-Cil
  • axios

(二)下载工具

  • 下载VsCode
  • 下载Node.js
    也可以使用nvm-window版本管理器
  • 安装Vue.js
  • 安装Vue-Cil

二、使用步骤

(一)创建项目

  • 打开cmd窗口,使用命令进入创建项目的路径,输入如下代码
 vue create demo-toutiao 

在这里插入图片描述

  • 进入vue-cil界面,这里选择第三个自定义项
    在这里插入图片描述
  • 按下空格来选择以下三项
    简单黑马头条项目_第1张图片
  • 选择vue2版本
    简单黑马头条项目_第2张图片
  • 选择less预处理器
    在这里插入图片描述
  • 选择Eslint+Standard config的代码风格,不同的标准写出的代码不同简单黑马头条项目_第3张图片
  • 选择Lint on Save,作用是能够在ctrl+s时检查语法错误
    简单黑马头条项目_第4张图片
  • 选择In dedicate config files,作用是有各自的配置文件
    简单黑马头条项目_第5张图片

-输入n,不将刚才的配置存为预设
简单黑马头条项目_第6张图片

  • 项目创建中
    简单黑马头条项目_第7张图片
  • 项目创建成功
    简单黑马头条项目_第8张图片

(二)下载插件

  • Vetur
  • Prettier - Code formatter
 //prettier在setting.json的配置
  "prettier.configPath": "D:\\VsCode Workplace\\配置文件\\.prettierrc.js",
  "eslint.alwaysShowStatus": true,
  "prettier.trailingComma": "none",
  "prettier.semi": false, //每行文字个数超出此限制将会被迫换行
  "prettier.printWidth": 300, //使用单引号替换双引号
  "prettier.singleQuote": true,
  "prettier.arrowParens": "avoid", //甚至在.vue文件中,HTML代码的格试化插件
  "vetur.format.defaultFormatter.html": "js-beautify-html",
  "vetur.ignoreProjectWarning": true,
  "vetur.format.defaultFormatterOptions": {
    "prettier": {
      "trailingComma": "none",
      "semi": false,
      "singleQuote": true,
      "arrowParens": "avoid",
      "printWidth": 300
    },
    "js-beautify-html": {
      "wrap attributes": false
    }
  },

-ESLint

 //ESLint插件在setting.json的配置
  "editor.codeActionsOnSave": {
    "source.fixAll": true
  },

(三)编写主页面

步骤

  • 用VsCode打开demo-toutiao项目,项目结构如下
    简单黑马头条项目_第9张图片
  • 安装Vant组件库
    Vant快速上手
  • 删除项目自带的HelloWorld.vue组件,然后在src目录下创建views目录,再在views目录下创建Home和User目录,分别在Home和User下创建home.vue组件和user.vue组件,项目的结构如下:
    简单黑马头条项目_第10张图片
  1. main.js中引入Vant
import Vue from 'vue'
import App from './App.vue'
import Vant from 'vant'
import 'vant/lib/index.css' //引入全部的vant组件,一般不推荐
Vue.config.productionTip = false
Vue.use(Vant) //使用Vant
new Vue({
  render: h => h(App)
}).$mount('#app')
  1. user.vue 组件中,声明如下的模板结构:
 <template>
   <div class="user-container">
     
     <div class="user-card">
       
       <van-cell>
         
         <template #icon>
           <img src="../../assets/logo.png" alt="" class="avatar" />
         template>
         <template #title>
           <span class="username">用户名span>
         template>
         <template #label>
           <van-tag color="#fff" text-color="#007bff">申请认证van-tag>
         template>
       van-cell>
       
       <div class="user-data">
         <div class="user-data-item">
           <span>0span>
           <span>动态span>
         div>
         <div class="user-data-item">
           <span>0span>
           <span>关注span>
         div>
         <div class="user-data-item">
           <span>0span>
           <span>粉丝span>
         div>
       div>
     div>
 
     
     <van-cell-group class="action-card">
       <van-cell icon="edit" title="编辑资料" is-link />
       <van-cell icon="chat-o" title="小思同学" is-link />
       <van-cell icon="warning-o" title="退出登录" is-link />
     van-cell-group>
   div>
 template>
 
 <script>
 export default {
   name: 'User'
 }
 script>
 
 <style lang="less" scoped>
 .user-container {
   .user-card {
     background-color: #007bff;
     color: white;
     padding-top: 20px;
     .van-cell {
       background: #007bff;
       color: white;
       &::after {
         display: none;
       }
       .avatar {
         width: 60px;
         height: 60px;
         background-color: #fff;
         border-radius: 50%;
         margin-right: 10px;
       }
       .username {
         font-size: 14px;
         font-weight: bold;
       }
     }
   }
   .user-data {
     display: flex;
     justify-content: space-evenly;
     align-items: center;
     font-size: 14px;
     padding: 30px 0;
     .user-data-item {
       display: flex;
       flex-direction: column;
       justify-content: center;
       align-items: center;
       width: 33.33%;
     }
   }
 }
 style>
 
  1. home.vue 组件中,声明如下的模板结构
<template>

  <div><van-nav-bar title="黑马头条" fixed />div>
template>

<script>
export default {
  name: 'home'
}
script>

<style lang="less" scoped>

.home-container {
  padding: 46px 0 50px 0;//防止标题覆盖新闻内容
  .van-nav-bar {
    background-color: #007bff;//改变Navbar的默认样式,权重比自定义的主题大
   /deep/.van-nav-bar__title { ///deep/深度选择器,能够作用得“更深”,影响子组件
      color: #fff;
    }
  }
}
style>
  1. App.vue 组件中,声明如下的模板结构
<template>
  <div>
  
   <router-view>router-view>
   
    <van-tabbar route>
      <van-tabbar-item icon="home-o" to="/">首页van-tabbar-item>
      <van-tabbar-item icon="user-o" to="/user">我的van-tabbar-item>
    van-tabbar>
     
  div>
template>

<script>
export default {
  name: 'App'
}
script>

<style lang="less" scoped>style>
  1. .eslintrc.js配置
module.exports = {
  root: true,
  env: {
    node: true
  },
  extends: ['plugin:vue/essential', '@vue/standard'],
  parserOptions: {
    parser: '@babel/eslint-parser'
  },
  rules: {
    'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'space-before-function-paren': ['error', 'always'],
    'vue/multi-word-component-names': ['error', { ignores: ['home', 'user'] }]
  }
}

页面效果

简单黑马头条项目_第11张图片

(四)编写功能

路由功能实现页面的切换

  • 安装vue-router
    在终端输入 npm i [email protected]
  • 在src目录下建立router目录,在其目录先建立index.js
 import Vue from 'vue'
import VueRouter from 'vue-router'

// 导入需要的组件
import Home from '@/views/Home/home.vue'
import User from '@/views/User/user.vue'

// 把 VueRouter 安装为 Vue 的插件
Vue.use(VueRouter)

// 路由规则的数组
const routes = [
  // 定义首页的路由规则
  { path: '/', component: Home },
  // 定义我的路由规则
  { path: '/user', component: User }
]

// 创建路由实例对象
const router = new VueRouter({
  routes
})

export default router
  • main.js引入router
import Vue from 'vue'
import App from './App.vue'
import Vant from 'vant'
import router from './router'
import 'vant/lib/index.css' // 引入全部的vant组件,一般不推荐
Vue.config.productionTip = false
Vue.use(Vant) // 使用Vant
new Vue({
  router,
  render: h => h(App)
}).$mount('#app')
  • 页面效果
    切换home.vue组件
    简单黑马头条项目_第12张图片
    切换user.vue组件
    简单黑马头条项目_第13张图片

调用接口,获取数据

封装request.js

  • 安装axios
    在终端输入npm install axios

  • 在src文件夹下新建utils文件夹,再在其下新建request.js文件

import axios from 'axios'

// 调用 axios.create() 函数,创建一个 axios 的实例对象,用 request 来接收
const request = axios.create({
  // 指定请求的根路径
  baseURL: 'https://applet-base-api-t.itheima.net/'
})

export default request

封装articleAPI.js

  • 在src文件夹下新建api文件夹,再在其下新建articleAPI.js文件
// 文章相关的 API 接口,都封装到这个模块中
import request from '@/utils/request.js'

// 向外按需导出一个 API 函数
export const getArticleListAPI = function (_page, _limit) {
  return request.get('/articles', {
    // 请求参数
    params: {
      _page,
      _limit
    }
  })
}

调用接口,获取数据

  • home.vue
<script>
// 按需导入 API 接口
import { getArticleListAPI } from '@/api/articleAPI.js'
export default {
  name: 'home',
  data() {
    return {
      // 页码值
      page: 1,
      // 每页显示多少条数据
      limit: 10,
      // 文章的数组
      artlist: []
    }
  },
  created() {
    this.initArticleList()
  },
  methods: {
    // 封装获取文章列表数据的方法
    async initArticleList() {
      // 发起 GET 请求,获取文章的列表数据
      const { data: res } = await getArticleListAPI(this.page, this.limit)
      console.log(res)
    }
  }
}
</script>
  • 控制台输出的数据简单黑马头条项目_第14张图片

将数据渲染在home.vue的页面上

  • 在components文件夹下新建Article文件夹,再在其下新建ArticleInfo.vue文件
 <template>
  <div>
    <van-cell>
      
      <template #title>
        <div class="title-box">
          
          <span>{{ title }}span>
          
          <img :src="cover.images[0]" alt="" class="thumb" v-if="cover.type === 1" />
        div>
        
        <div class="thumb-box" v-if="cover.type === 3">
          <img :src="item" alt="" class="thumb" v-for="(item, i) in cover.images" :key="i" />
        div>
      template>
      
      <template #label>
        <div class="label-box">
          <span>作者 {{ author }}    {{ cmtCount }} 评论    发布日期 {{ time }}span>
          
          <van-icon name="cross" />
        div>
      template>
    van-cell>
  div>
template>

<script>
export default {
  name: 'ArticleInfo',
  // 自定义属性
  props: {
    // 文章的标题
    title: {
      type: String,
      default: ''
    },
    // 作者名字
    author: {
      type: String,
      default: ''
    },
    // 评论数
    cmtCount: {
      // 通过数组形式,为当前属性定义多个可能的类型
      type: [Number, String],
      default: 0
    },
    // 发布日期
    time: {
      type: String,
      default: ''
    },
    // 封面的信息对象
    cover: {
      type: Object,
      // 通过 default 函数,返回 cover 属性的默认值
      default: function() {
        // 这个 return 的对象就是 cover 属性的默认值
        return { type: 0 }
      }
    }
  }
}
script>

<style lang="less" scoped>
.label-box {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.thumb {
  // 矩形黄金比例:0.618
  width: 113px;
  height: 70px;
  background-color: #f8f8f8;
  object-fit: cover;
}

.title-box {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
}

.thumb-box {
  display: flex;
  justify-content: space-between;
}
style>

  • home.vue上使用ArticleInfo组件,并向ArticleInfo.vue传输数据
<template>
  <div class="home-container">
    <van-nav-bar title="黑马头条" fixed />
    <ArticleInfo v-for="item in artlist" :key="item.id" :title="item.title" :author="item.aut_name" :cmt-count="item.comm_count" :time="item.pubdate" :cover="item.cover">ArticleInfo>
  div>
template>

<script>
// 按需导入 API 接口
import { getArticleListAPI } from '@/api/articleAPI.js'
// 导入需要的组件
import ArticleInfo from '@/components/Article/ArticleInfo.vue'
export default {
  name: 'home',
  components: { ArticleInfo },
  data() {
    return {
      // 页码值
      page: 1,
      // 每页显示多少条数据
      limit: 10,
      // 文章的数组
      artlist: []
    }
  },
  created() {
    this.initArticleList()
  },
  methods: {
    // 封装获取文章列表数据的方法
    async initArticleList() {
      // 发起 GET 请求,获取文章的列表数据
      const { data: res } = await getArticleListAPI(this.page, this.limit)
      console.log(res)
      this.artlist = res
    }
  }
}
script>

<style lang="less" scoped>
.home-container {
  padding: 46px 0 50px 0;
  .van-nav-bar {
    background-color: #007bff;
    /deep/.van-nav-bar__title {
      color: #fff;
    }
  }
}
style>

  • 页面效果
    简单黑马头条项目_第15张图片

实现下拉刷新数据和上拉刷新数据的功能

<template>
  <div class="home-container">
    <van-nav-bar title="黑马头条" fixed />
    <van-pull-refresh v-model="isLoading" :disabled="finished" @refresh="onRefresh">
      <van-list v-model="loading" :finished="finished" finished-text="没有更多了" @load="onLoad">
        <ArticleInfo v-for="item in artlist" :key="item.id" :title="item.title" :author="item.aut_name" :cmt-count="item.comm_count" :time="item.pubdate" :cover="item.cover">ArticleInfo>
      van-list>
    van-pull-refresh>
  div>
template>

<script>
// 按需导入 API 接口
import { getArticleListAPI } from '@/api/articleAPI.js'
// 导入需要的组件
import ArticleInfo from '@/components/Article/ArticleInfo.vue'
export default {
  name: 'home',
  components: { ArticleInfo },
  data() {
    return {
      // 页码值
      page: 1,
      // 每页显示多少条数据
      limit: 10,
      // 文章的数组
      artlist: [],
      // 是否正在加载下一页数据,如果 loading 为 true,则不会反复触发 load 事件
      // 每当下一页数据请求回来之后,千万要记得,把 loading 从 true 改为 false
      loading: true,
      // 所有数据是否加载完毕了,如果没有更多数据了,一定要把 finished 改成 true
      finished: false,
      // 是否正在下拉刷新
      isLoading: false
    }
  },
  created() {
    this.initArticleList()
  },
  methods: {
    // 封装获取文章列表数据的方法
    async initArticleList(isRefresh) {
      // 发起 GET 请求,获取文章的列表数据
      const { data: res } = await getArticleListAPI(this.page, this.limit)

      if (isRefresh) {
        // 证明是下拉刷新;新数据在前,旧数据在后
        // this.artlist = [新数据在后, 旧数据在前]
        this.artlist = [...res, ...this.artlist]
        this.isLoading = false
      } else {
        // 证明是上拉加载更多;旧数据在前,新数据在后
        // this.artlist = [旧数据在前, 新数据在后]
        this.artlist = [...this.artlist, ...res]
        this.loading = false
      }

      if (res.length === 0) {
        // 证明没有下一页数据了,直接把 finished 改为 true,表示数据加载完了!
        this.finished = true
      }
    },
    // 只要 onLoad 被调用,就应该请求下一页数据
    onLoad() {
      console.log('触发了 load 事件!')
      // 1. 让页码值 +1
      this.page++
      // 2. 重新请求接口获取数据
      this.initArticleList()
    },
    // 下拉刷新的处理函数
    onRefresh() {
      console.log('触发了下拉刷新!')
      // 1. 让页码值 +1
      this.page++
      // 2. 重新请求接口获取数据
      this.initArticleList(true)
    }
  }
}
script>

<style lang="less" scoped>
.home-container {
  padding: 46px 0 50px 0;
  .van-nav-bar {
    background-color: #007bff;
    /deep/.van-nav-bar__title {
      color: #fff;
    }
  }
}
style>

改变Vant的默认样式

修改默认样式

github地址

demo-toutiao

你可能感兴趣的:(vscode,vue.js,npm)