Vue2 实战 — 仿卖座电影 APP

发布于 2021-08-09  120 次阅读


1.初始化项目工程

1.1 开发环境

  • 开发环境:Window 10
  • 开发工具:VScode 1.59.0
  • 项目运行环境:node 16.6.2
  • 项目包管理工具:npm 7.20.3
  • Vue 脚手架: vue-cli 4.5.13
  • 代码版本管理工具:git 2.32.0

1.2 开发技术栈

  • vue 全家桶(vuejs/vue-router/vuex)
  • webpack 增量配置 proxy
  • ui 组件库 vant
  • axios
  • nodejs 模拟数据

1.3 创建项目

vue create m.maizuo.huxinfeng.com
# OR
vue ui

# 1.选择
# ? Please pick a preset:
#   Default ([Vue 2] babel, eslint)
#   Default (Vue 3) ([Vue 3] babel, eslint)
# > Manually select features

# 2.勾选
# ? Check the features needed for your project:
#  (*) Choose Vue version
#  (*) Babel
#  ( ) TypeScript
#  ( ) Progressive Web App (PWA) Support
#  (*) Router
#  (*) Vuex
#  (*) CSS Pre-processors
# >( ) Linter / Formatter
#  ( ) Unit Testing
#  ( ) E2E Testing

# 3.选择
# ? Choose a version of Vue.js that you want to start the project with (Use arrow keys)
# > 2.x
#   3.x

# 4.选择
# ? Use history mode for router? (Requires proper server setup for index fallback in production) (Y/n) Y

# 5.选择
# ? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): (Use arrow keys)
# > Sass/SCSS (with dart-sass)
#   Sass/SCSS (with node-sass)
#   Less
#   Stylus

# 6.选择
# ? Where do you prefer placing config for Babel, ESLint, etc.? (Use arrow keys)
# > In dedicated config files
#   In package.json

# 7.不保存配置
# ? Save this as a preset for future projects? (y/N) N

1.4 git 版本配置、提交

# Git 全局设置:
git config --global user.name "星宿君"
git config --global user.email "bytedance.hu@qq.com"

# 创建 git 仓库:
cd m.maizuo.huxinfeng.com
git init
git add .
git commit -m "create m.maizuo.huxinfeng.com project in vue"
git remote add origin https://gitee.com/huxinfeng/m.maizuo.huxinfeng.com.git
git push -u origin master

# 创建 git 分支 hxf
git checkout -b hxf

1.5 初始化项目

在 ./ 目录下新建 jsconfig.json

// 配置绝地路径
{
    "compilerOptions": {
        "baseUrl": ".",
        "paths": {
            "@/*": ["src/*"]
        }
    }
}

在 ./src/router 目录下新建 routes 文件夹,新建 films.js cinemas.js news.js center.js error.js

// 个人中心路由模块
const router = {
    path: "/center",
    name: "Center",
    component: () => import(/* webpackChunkName: "center" */ "@/views/center"),
};
export default router;
// error 错误路由模块
export default {
    path: "*",
    name: "Error",

    component: () => import(/* webpackChunkName: "error" */ "@/views/error"),

    children: [
        // 404
        {
            path: "/404",
            name: 404,

            component: () => import(/* webpackChunkName: "error_404" */ "@/views/error/404.vue"),
        },
        // 403
        {
            path: "/403",
            name: 403,

            component: () => import(/* webpackChunkName: "error_403" */ "@/views/error/403.vue"),
        },
    ],
};

在 ./src/views 目录下新建 films cinemas news center error 文件夹,新建相应的 index.vue

<template lang="zh-CN">
    <div>个人中心</div>
</template>

<script>
    export default {};
</script>

<style lang="scss" scoped></style>

1.6 路由规划

如果项目中所有的路由都写在入口文件中,那么将不便于编写项目和后期维护,因此路由需要进行模块化处理。
可以先行添加以下几个空的路由模块:
电影模块
电影院模块
资讯模块
个人中心模块
error 模块
如果后续还有其他模块,届时再进行增加即可。
创建模块化的目录及路由文件

./src/router/index.js (路由主入口文件) 修改路由配置对象
使用全局自动化状态路由模块好处,可以避免手动导入子路由(避免写入 import 冗余),由代码自动导入
routes 等价于 ./src/router/routes 文件夹下创建的子路由模块

// 全局自动化 状态路由模块
let moduleFn = require.context("@/router/routes", false, /\.js$/);
const routes = moduleFn.keys().reduce((value, item) => {
    let router = moduleFn(item).default;
    if (router) {
        value.push(router);
    }
    return value;
}, []);
npm run serve

运行效果图如下,则成功初始化项目
file

1.7 底部导航

https://www.iconfont.cn/ 下载你需要的字体图标,下载 iconFont.css 文件,放置到 ./src/assets/style 目录下

在 ./src/components 目录下新建 FooterNav.vue

<template lang="zh-CN">
    <footer>
        <ul>
            <router-link tag="li" active-class="active" :to="{name: 'Films'}">
                <i class="iconfont icon-dianying"></i>
                <p>电影</p>
            </router-link>
            <router-link tag="li" active-class="active" :to="{name: 'Cinemas'}">
                <i class="iconfont icon-yingyuan"></i>
                <p>电影院</p>
            </router-link>
            <router-link tag="li" active-class="active" :to="{name: 'News'}">
                <i class="iconfont icon-zixun"></i>
                <p>资讯</p>
            </router-link>
            <router-link tag="li" active-class="active" :to="{name: 'Center'}">
                <i class="iconfont icon-gerenzhongxin"></i>
                <p>个人中心</p>
            </router-link>
        </ul>
    </footer>
</template>

<script>
    import "@/assets/style/iconFont.css";
    export default {};
</script>

<style lang="scss" scoped>
    footer {
        width: 100%;
        position: fixed;
        bottom: 0;

        ul {
            display: flex;
            li {
                margin: 3px 0;
                flex: 1;
                &.active {
                    color: #fe5100;
                }
                p {
                    font-size: 15px;
                }
                i {
                    font-size: 15px;
                }
            }
        }
    }
</style>

https://meyerweb.com/eric/tools/css/reset/ 下载 reset.css 文件,放置到 ./src/assets/style 目录下,在 ./src/main.js 中引入

// 样式重置
import "@/assets/style/reset.css";

将组件 ./src/components/FooterNav.vue 导入到根组件 ./src/App.vue 中并使用

<template>
    <div id="app">
        <router-view></router-view>
        <footer-nav></footer-nav>
    </div>
</template>

<script>
    import FooterNav from "@/components/FooterNav.vue";
    export default {
        components: { FooterNav },
    };
</script>

运行效果图如下
file

1.8 移动站 rem 布局

将代码中的 px 转成 rem

rem/vw(100 份)
postcss 模块,但是 vue-cli 已经安装好了,所以就直接装它的一些扩展
postcss-pxtorem 是一款 PostCSS 插件,用于将 px 单位转化为 rem 单位
lib-flexible 用于设置 rem 基准值

# 注意版本,vue-cli 自带的支持是 5 版本
npm i -D postcss-pxtorem@5
# 阿里出一个类库,解决 html 中的 font-size 基准值
npm i -S amfe-flexible

配置 postcss.config.js

// 专门给postcss所用的配置文件
// 此文件一但修改则需要重启服务  运行在nodejs环境中,所以使用commonjs规范
module.exports = {
    // postcss要使用的插件
    plugins: {
        // px转为rem
        "postcss-pxtorem": {
            // 把一个屏幕分为10等分,以iphone6为基准,ipphone的物理像素就为375px   2倍图布局
            rootValue: 37.5,
            // 所有的有px单位都会转为rem,除style中你所写的px不会转换
            propList: ["*"],
        },
    },
};

在 ./src/main.js 中引入

// 引入计算基准的类加
import "amfe-flexible";

可以很明显的发现,不同终端自适应字体大小,代码中的 px 转成 rem

1.9 网络请求

安装 axios

npm i axios

在 ./src 目录下创建 utils 文件夹,新建 request.js

// 专门用来进行网络请求的封装
import axios from "axios";

// 创建一个新的 axios 对象实例
const service = axios.create({
    // 环境判断
    timeout: process.env.NODE_ENV === "development" ? 5000 : 10000,
    baseURL: process.env.NODE_ENV === "development" ? "" : "https://api.iynn.cn/film",
});

// 请求拦截器
service.interceptors.request.use(
    config => config,
    err => Promise.reject(err)
);

// 响应拦截器
service.interceptors.response.use(
    response => {
        return response.data;
    },
    err => Promise.reject(err)
);

export const get = (url, config = {}) => service.get(url, config);
export const post = (url, data = {}, config = {}) => service.post(url, data, config);

在 ./src 目录下创建 config 文件夹,新建 filmConfig.js

// 电影请求 url 配置
export default {
    films: "https://api.iynn.cn/film/api/v1/getCitiesInfo",
};

在 ./src 目录下创建 api 文件夹,新建 filmApi.js

import config from "@/config/filmConfig";
import { get, post } from "@/utils/request";

export const getFilmsApi = (page = 1) => get(config.films);

在 ./src/views/films/components/NowPlaying.vue 下写入以下测试代码

import { getFilmsApi } from "@/api/filmApi";
export default {
    async mounted() {
        let res = await getFilmsApi();
        console.log(res);
    },
};

file

很明显出现了跨域报错,使用 proxy 代理解决,在 ./src 目录下 新建 vue.config.js

// vue 给开发者暴露出来的增量去配置 webpack 有文件
module.exports = {
    // 代理打包生产环境中将不存在,需要通过 nodejs 来完成
    devServer: {
        // 代理跨域
        proxy: {
            // 代理 url 关键字
            "/getCitiesInfo": {
                // 需要代理的地址
                target: "https://api.iynn.cn/film/api/v1",
                // 如果是 https 接口,需要配置这个参数
                secure: true,
                // 是否跨域
                changeOrigin: true,
                // 地址的重写,匹配地址路径和真实的路径有出入
                // pathRewrite: {
                //  "^/getCitiesInfo": "",
                // },
            },
        },
    },
};

此时访问控制台,可以拿到数据
file

2.电影模块开发

vant 组件库:https://vant-contrib.gitee.io/vant/#/zh-CN/
 安装 vant 组件 有赞团队开源 移动端组件库

npm i -S vant

vant 组件导入方式一: 全量导入
在 ./src/main.js 写入

// vant组件  -- 全量导入,打包时,打包的js文件体积可能过大,原因在于,此组件库中的ui组件过多,而我们用不到哪么多
import Vant from "vant";
import "vant/lib/index.css";

Vue.use(Vant);

在 ./src/views/films/components/NowPlaying.vue 下写入以下测试代码

<template lang="zh-CN">
    <div>
        <p>正在热映</p>
        <van-button type="primary">主要按钮</van-button>
    </div>
</template>

file

为了减小打包文件体积,我采用另外一种引入方式,也是官方推荐
vant 组件导入方式二: 自动按需引入组件 (推荐)

# 安装插件
# babel-plugin-import 是一款 babel 插件,它会在编译过程中将 import 的写法自动转换为按需引入的方式。
npm i babel-plugin-import -D

在 ./src/babel.config.js 写入

// 实现 vant 组件打包时按需加载,打包后的 js 文件就会小
    plugins: [
        [
            "import",
            {
                libraryName: "vant",
                libraryDirectory: "es",
                style: true,
            },
            "vant",
        ],
    ],

在 ./src 创建 plugins 文件夹,新建 vant.js
以后需要用到的组件,直接在里面添加即可

// 专门用来加载 vant 组件
import Vue from "vue";

import { Button } from "vant";

[Button].forEach(cmp => Vue.use(cmp));

在 入口文件 ./src/main.js 写入

// 按需引入
import "@/plugins/vant";

2.1 列表顶部导航

创建电影列表顶部导航组件 ./src/components/FilmListTopNav.vue

星宿君/m.maizuo.huxinfeng.com


博主好穷啊,快点支助一下吧 ε = = (づ′▽`)づ