博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Vue2.6+VueCli4.3+CubeUI 完成小D课堂移动端
阅读量:3946 次
发布时间:2019-05-24

本文共 20235 字,大约阅读时间需要 67 分钟。

Vue2.6+VueCli4.3+CubeUI 完成小D课堂移动端

0. 项目效果

在这里插入图片描述

在这里插入图片描述

1. 搭建项目架构

  • 创建 vue 项目
    • vue create iclass-web
  • 选择 feature 模式,安装 vuex/vue-router
    • 安装 axios
      • npm install axis --save
    • npm install <package_name> --save
      • 表示将这个包名及对应的版本添加到 package.jsondependencies
    • npm install <package_name> --save-dev
      • 表示将这个包名及对应的版本添加到 package.jsondevDependencies
  • 添加 cube-ui 依赖
    • vue add cube-ui

2. 项目目录结构创建

2.1 分析前端需求

  • 底部导航
  • 首页 Banner
  • 首页视频列表
  • 视频详情模块
  • 注册模块
  • 登陆模块
  • 个人信息模块
  • 下单模块
  • 订单列表模块

2.2 介绍目录结构

  • 创建新目录
    • api/router/views
    • views
      • CourseDetail
      • Home
      • Register
      • Login
      • Order
      • Pay
      • Personal

3. 基于浏览器和 nodeJS 的 http 客户端 Axios 模块

3.1 什么是 Axios

  • 基于 promise 用于浏览器nodeJShttp 客户端
    • 支持浏览器nodeJS
    • 支持 Promise API
    • 支持拦截请求和响应
    • 支持转换请求和响应数据
    • JSON 数据的自动转换
    • 客户端支持以防止 XSRF
  • 文档地址:<
  • 安装 Axios
    • npm install axios

3.2 GET 请求

// 为给定 ID 的 user 创建请求axios.get('/user?ID=12345')  .then(function (response) {
console.log(response); }) .catch(function (error) {
console.log(error); });// 上面的请求也可以这样做axios.get('/user', {
params: {
ID: 12345 } }) .then(function (response) {
console.log(response); }) .catch(function (error) {
console.log(error); });

3.3 POST 请求

axios.post('/user', {
firstName: 'Fred', lastName: 'Flintstone' }) .then(function (response) {
console.log(response); }) .catch(function (error) {
console.log(error); });

3.4 创建实例

  • 可以使用自定义配置新建一个 axios 实例
  • axios.create([config])
const instance = axios.create({
baseURL: 'https://some-domain.com/api/', timeout: 1000, headers: {
'X-Custom-Header': 'foobar'}});

4. Axios 封装通用后端请求 API 模块

  • getData.js
import axios from '../request'//注册接口export const registerApi = (phone, pwd , name)=> axios.post("/api/v1/pri/user/register",{
"phone":phone, "pwd":pwd, "name":name})//登录接口export const loginApi = (phone, pwd) => axios.post("/api/v1/pri/user/login",{
phone, pwd})//轮播图接口export const getBanner = () => axios.get("/api/v1/pub/video/list_banner")//视频列表接口export const getVideoList = ()=> axios.get("/api/v1/pub/video/list")//视频详情export const getVideoDetail = (vid)=> axios.get("/api/v1/pub/video/find_detail_by_id?",{
params: {
video_id:vid }})//下单接口export const saveOrder = (token, vid)=>axios.post("/api/v1/pri/order/save",{
"video_id":vid},{
headers:{
"token":token }})//订单列表export const getOrderList = (token)=>axios.get("/api/v1/pri/order/list",{
params:{
"token":token }})//用户信息接口export const getUserInfo = (token)=>axios.get("/api/v1/pri/user/find_by_token",{
params:{
"token":token }})
  • request.js
// 导入 axios 模块import axios from 'axios'// 创建 axios 实例const service = axios.create({
// url = baseURL + request url // 根目录 baseURL: 'xxxx', // 配置请求超时时间 timeout: 5000})// 导出 serviceexport default service

5. Vue-Router 开发路由

5.1 vue-router 介绍

  • Vue.js 官方的路由管理器,和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌
  • 官方文档

5.2 vue-router 常见 API

  • 文档
  • router.path
    • 获取当前的路由
  • router.go(n)
    • 这个方法的参数是一个整数,表示在 history 记录中向前或者向后退多少步
    • 类似 window.history.go(n) 方法
  • router.push(path)
    • 导航到不同的 path 路径
    • 这个方法会向 history 栈添加一个新的记录
    • 所以当用户点击浏览器后退按钮时,则回到之前的 URL

5.3 路由对象属性

5.3.1 $route.path
  • 类型:string
  • 字符串,对应当前路由的路径,总是解析为绝对路径,如:"/foo/bar"
5.3.2 $route.params
  • 类型:Object
  • 一个 key/value 对象,包含了动态片段和全匹配片段如果没有路由参数,就是一个空对象
5.3.3 $route.query
  • 类型:Object
  • 一个 key/value 对象,表示 URL 查询参数
  • 例如,对于路径 /foo?user=1,则有 $route.query.user == 1
  • 如果没有查询参数,则是个空对象
// 引用 vue,vue-router 模块import Vue from 'vue'import VueRouter from 'vue-router'// 引入组件模块import Home from '../views/Home/Home.vue'import CourseDetail from '../views/CourseDetail/CourseDetail.vue'import Login from '../views/Login/Login.vue'import Order from '../views/Order/Order.vue'import Pay from '../views/Pay/Pay.vue'import Personal from '../views/Personal/Personal.vue'import Register from '../views/Register/Register.vue'// 使用 VueRouter Vue.use(VueRouter)// 单独提出 routes// 定义路由关系const routes = [    {
path: "/", name: "Home", component: Home }, {
path: "/coursedetail", name: "CourseDetail", //按需加载 component: () => import("../views/CourseDetail/CourseDetail.vue") //component:CourseDetail }, {
path: "/login", name: "Login", component: Login }, {
path: "/order", name: "Order", component: Order, meta: {
requiresAuth: true } }, {
path: "/pay", name: "Pay", component: Pay, meta: {
requiresAuth: true } }, {
path: "/personal", name: "Personal", component: Personal, meta: {
requiresAuth: true } }, {
path: "/register", name: "Register", component: Register }]// 创建路由实例const router = new VueRouter({
// 定义路由关系 routes})// 导出 routerexport default router

6. 通用底部选项卡 CommonsFooter 开发

6.1 查看 cube-ui 文档

  • 文档

6.2 cube-tab-bar 组件

  • 底部选项卡组件

6.3 底部选项卡 cube-tab-bar

  • template 开发
    • Mac 格式化代码:shift + option + F
    • windows 格式化代码:shift + alt + F
  • script 开发
    • 图标
export default {
data() {
return {
// 默认选中首页 selectedLabelSlots: "/", tabs: [ {
label: "首页", icon: "cubeic-home", path: "/" }, {
label: "我的订单", icon: "cubeic-like", path: "/order" }, {
label: "个人中心", icon: "cubeic-person", path: "/personal" } ] }; }};
  • 开发方法
methods: {
changHandler(path){
//this.$route.path是当前路径 if(path !== this.$route.path){
// 当点击的时,传入对应路径 // 如果页面当前路径不是点击对应的路径 // 则将点击的路径推到路由中 this.$router.push(path) } }}, //vue实例生命周期 created:在模板渲染成html前调用,即通常初始化某些属性值,然后再渲染成视图 //vue实例生命周期 mounted:在模板渲染成html后调用,通常是初始化页面完成后,再对html的dom节点进行额外的操作 //https://cn.vuejs.org/v2/guide/instance.html#%E5%AE%9E%E4%BE%8B%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E9%92%A9%E5%AD%90created(){
//默认路由选择器,比如刷新页面,需要重新进到当前路由 this.selectedLabelSlots = this.$route.path}
  • 配置样式

7. 首页 Home 模块开发

7.1 拆分子组件

  • Home
  • banner
  • videoList
  • 注意点
    • 指令属性里面取data里面的数据是不用加{
      {}}
    • html标签内容体中间则需要加{
      {}}

7.2 template 开发

7.3 await async 知识点

  • async 用于声明一个 function异步
  • await 用于等待一个异步方法执行完成(发起请求,如果查询数据库,发起 http 等)
  • 参考文章
// 导入组件模块import HomeBanner from "./Component/Banner";import VideoList from "./Component/VideoList";import CommonFooter from "@/components/CommonFooter";// 导入接口APIimport {
getBanner, getVideoList } from "@/api/getData.js";export default {
//注册组件 components: {
HomeBanner, VideoList, CommonFooter, }, //声明数据源 data() {
return {
// 轮播图与视频列表数据都是数组形式 banners: [], videoList: [], }; }, // 定义方法 methods: {
// 异步调用 getBanner 接口 // 获取轮播图数据 async getBannerData() {
// 捕获异常 try {
// 等待异步方法执行完成 const result = await getBanner(); console.log(result); console.log(result.data.code == 0) if (result.data.code == 0) {
this.banners = result.data.data; } }catch(error){
console.lo(error) } }, //获取视频列表 async getVList(){
try{
const result = await getVideoList(); if (result.data.code == 0) {
this.videoList = result.data.data; } }catch(error){
console.lo(error) } } }, mounted(){
//当页面渲染完成时调用方法获取数据 this.getBannerData(); this.getVList() } };

8. 首页轮播图 Banner 模块开发

  • 轮播图组件 cube-slide 讲解
    • 文档:
  • 代码编写

9. 首页视频列表 VideoList 模块开发

9.1 router-link 讲解

  • 用于路径跳转
  • 文档:
  • template
  • script
export default {
// 获取父组件传递过来的值 props: {
videoList: {
type: Array, required: true, }, },};
  • style
//列表包裹层边距.list-content {
margin-top: 20px; padding: 0 13px;}//视频包括层.list {
display: flex; //设置flex布局 flex-wrap: wrap; //换行排列 justify-content: space-between; //两端对齐 padding-bottom: 55px;}//视频个体层.course {
width: 48%; margin-bottom: 17px;}//视频图片.item_img {
font-size: 0; //消除图片元素产生的间隙 box-shadow: 0 4px 11px 0 rgba(43, 51, 59, 0.6); //设置图片阴影,rgba前三个参数是颜色编码,最后一个是透明度 border-radius: 8px; //设置图片圆角 img {
width: 100%; border-radius: 8px; }}.c_title {
//设置超过两行隐藏 start display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; word-break: break-all; //设置超过两行隐藏 end font-size: 11px; height: 26px; line-height: 13px; margin-top: 10px; color: #2b333b;}//价格.price {
margin-top: 8px; font-size: 12px; color: #d93f30;}

10. 视频详情 CourseDetail 模块开发

  • 拆分组件

    • CourseDetail.vue
      • Header.vue
      • Course.vue
      • Tab.vue
        • Summary.vue
        • Calalog
  • 开发 CourseDetailtemplate

  • 开发 CourseDetailscript
//引入组件import DetailHeader from './Components/Header'import DetailCourse from './Components/Course'import DetailTab from './Components/Tab'import {
getVideoDetail } from "@/api/getData.js";export default {
//注册组件 components:{
DetailHeader, DetailCourse, DetailTab }, data(){
return {
//视频信息数据 videoInfo:{
}, //章集数据 chapterList:[] } }, methods:{
// 获取视频详情 // 传入 vid async getDetail(vid){
try{
const result = await getVideoDetail(vid) if(result.data.code == 0){
this.videoInfo = result.data.data; this.chapterList = result.data.data.chapter_list; } }catch(error){
console.log(error) } } }, mounted(){
//渲染完成后拿数据 console.log(this.$route.query.video_id) this.getDetail(this.$route.query.video_id); }}
  • 配置样式
//底部footer {
// fixed固定在底部 position: fixed; bottom: 0; width: 100%; padding: 8px 0; background-color: #fff; z-index: 999; box-shadow: 0 -2px 4px 0 rgba(0, 0, 0, 0.05);}//设置购买按钮样式button {
display: block; color: #fff; margin: 0 auto; background-color: #d93f30; height: 34px; line-height: 34px; border-radius: 17px; width: 80%; border: none; font-size: 15px; text-align: center;}

11. 视频详情页 Header 模块开发

  • 代码

12. 视频详情页 Course 模块开发

  • 代码

13. 视频详情页 Tab 模块开发

13.1 什么是 vue 动态组件

  • 不同组件之间进行动态切换

13.2 组件的过渡

  • template

  • script
import Summary from './Summary'import Catalog from './Catalog'export default {
components:{
Summary, Catalog }, // 获取父组件的数据 props:{
videoInfo:{
type:Object, required:true }, chapterList:{
type:Array, required:true } }, data(){
return{
selectedLabel:"简介", tabs:[ {
label:"简介" },{
label:"目录" } ] } }}

14. 视频详情页 summary 子组件开发

  • template
  • script
export default {
props:{
videoInfo:{
type:Object, required:true } }}
  • style
.summary {
width:100%; padding-bottom:50px; margin:15px 0;}

15. 视频详情页 Catalog 目录子组件开发

  • template
  • script
export default {
//从父组获取章集信息 props:{
chapterList:{
type:Array, required:true } }}
  • style
// 目录包裹层设置边距.cate_box {
padding: 0 15px 50px; background-color: #fff; margin: 15px 0;}//每一章包裹层.content {
padding: 10px; // 章标题 & h1 {
font-size: 16px; width: 100%; margin-bottom: 15px; font-weight: bolder; // 设置章标题过长,超过行宽度省略隐藏 text-overflow: ellipsis; overflow: hidden; white-space: nowrap; }}//集包裹层.sub_cate {
font-size: 12px; padding: 10px 0; //集标题 .sub_title {
// 设置集标题过长,超过行宽度省略隐藏 display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; }}

16. 视频详情页 footer 立刻购买按钮开发

  • CourseDetail.vue
...
...

17. 用户模块注册功能开发

17.1 Cube-UI 的 form 表单

  • template
  • script
//注册接口import {
registerApi } from "@/api/getData.js";export default {
data() {
return {
model: {
phoneValue: "", pwdValue: "", nameValue: "", }, // 校验规则部分 fields: [ {
type: "input", modelKey: "nameValue", label: "名称", props: {
// 属性 placeholder: "请输入名称", }, rules: {
// 规则 required: true, notWhitespace: true, }, messages: {
// 错误信息 required: "名称不能为空", notWhitespace: "名称不能为空白符", }, }, {
type: "input", modelKey: "phoneValue", label: "手机号", props: {
placeholder: "请输入手机", }, rules: {
required: true, len: 11, pattern: /^1[3456789]\d{9}$/, }, messages: {
pattern: "请输入正确的手机号", }, }, {
type: "input", modelKey: "pwdValue", label: "密码", props: {
placeholder: "请输入密码", type: "password", eye: {
open: false, }, }, rules: {
pattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[^]{8,16}$/, }, messages: {
pattern: "密码至少8-16个字符,包含大小字母和数字", }, }, ], }; }, methods: {
// 传入 model 参数 submitHandler(e, model) {
// preventDefault 方法 // 取消事件的默认动作(阻止冒泡) e.preventDefault(); //调用注册接口 registerApi(model.phoneValue, model.pwdValue, model.nameValue).then( (res) => {
if (res.data.code === 0) {
// Toast组件主要用于非模态信息提醒,无需用户交互 // time 字段决定了 Toast 显示的时间,如果设置为 0,则不会消失,需要手动调用组件的 hide 方法 const toast = this.$createToast({
txt: "注册成功", type: "correct", time: 1500, onTimeout: () => {
this.$router.push({
path: "login" }); }, }); toast.show(); } } ); }, },};
  • style
.main {
padding: 50px 5% 0; text-align: center;}//注册.cube-btn {
margin-top: 20px;}// 登录.reg {
display: inline-block; margin-top: 30px; font-size: 18px;}

18. 用户模块注登陆功能开发

19. Vuex 状态管理

19.1 vuex 是什么?

  • vuex 是适用于在 Vue 项目开发时使用的状态管理工具
  • 官方文档:

19.2 开发 store 中 index.js

import Vue from 'vue'import Vuex from 'vuex'Vue.use(Vuex)export default new Vuex.Store({
state: {
// 拿到 token 值 token: localStorage.getItem("token") || '' }, // 同步修改state里面的值 mutations: {
SET_TOKEN:(state, token)=>{
state.token = token } }, // 异步调用mutations里面的方法 // contxt.commit 利用上下文触发mutations某个方法 // vue代码里面 this.$store.dispatch触发action里面的定义的方法 actions: {
setToken(context,token){
context.commit('SET_TOKEN',token) }, clearToken(context){
context.commit('SET_TOKEN','') } }, modules: {
}})

19.3 整合 Login 登陆存储 token

  • Login.vue
methods: {
submitHandler(e, model) {
e.preventDefault(); //调用登陆接口 loginApi(model.phoneValue, model.pwdValue).then( res => {
if (res.data.code === 0) {
// 登录成功,跳转到个人中心 // 拿到 token,存储到本地 localStorage.setItem('token',res.data.data) // 触发 Vuex 定义的方法 this.$store.dispatch('setToken',res.data.data) // 跳转页面, 根据业务需要 this.$router.push({
path:'/personal'}) }else{
const toast = this.$createToast({
txt: "登录失败", type: "error", time: 1500 }); toast.show(); } } ); } }

20. 用户模块个人中心开发

21. 路由拦截功能开发

21. 前置守卫

  • 前置守卫文档
  • router 里面配置需要登陆的路由
    • meta: {requiresAuth: true}
  • main.js 里面配置路由拦截
// 路由拦截,拦截全部路由,每次操作路由都是被拦截进行判断// 路由前置守卫router.beforeEach((to,from,next)=>{
// 从本地存储中拿token const token = localStorage.getItem("token") // 筛选需要传token的路由,匹配route里面需要登陆的路径,如果匹配到的就是true if( to.matched.some(record => record.meta.requiresAuth)){
// 如果登陆了,执行下一步,没有登陆,跳转到登陆路由 // 根据token是否有,判断是否需要调到登录页面 if(token){
next() }else{
next({
path:'/login'}) } }else{
next() }})

22. 下单模块开发

23. 订单模块开发

24. 前后端项目云服务器生产环境部署核心知识

24.1 应用部署到公网访问需要的知识

24.1.1 http 请求基本流程
  • 客户端通过发起域名资源请求 -> DNS 解析获得IP -> 寻找服务器获得资源
24.1.2 域名和 IP 的关系,DNS 作用
  • DNS
    • Domain Name Server 域名服务器
    • 域名虽然便于人们记忆,但网络中的计算机之间只能互相认识 IP 地址
    • 它们之间的转换工作称为域名解析
      • 域名解析需要由专门的域名解析服务器来完成
      • DNS 就是进行域名解析的服务器
24.1.3 什么是 cname 和 a 记录
  • a 记录
    • 用户可以在此设置域名指向到自己的目标主机地址
    • 从而实现通过域名找到服务器(也叫 ip 指向域名配置
  • cname
    • 别名指向,可以为一个主机设置别名
    • 比如设置 open1024.com,用来指向一个主机 xdclass.net,那么以后就可以用 open1024.com 来代替访问 xdclass.net
    • http://www.xdclass.net --> xdclass.net
24.1.4 购买服务器,阿里云,腾讯云,亚马逊云 aws
  • 阿里云
  • 腾讯云
  • 亚马逊云
24.1.5 购买域名,备案
  • 阿里云备案地址
24.1.6 安装项目依赖的基本环境
24.1.7 配置域名解析到服务器

24.2 阿里云服务器远程登陆和常用工具

24.2.1 控制台修改阿里云远程连接密码
24.2.2 windows 工具
  • putty
  • xshell
  • security
  • 参考资料
24.2.3 苹果系统 MAC
  • 终端登陆
    • ssh root@ip 回车后输入密码
    • cd / (根路径)
    • cd software/
    • cd 项目路径
    • pwd(查看当前文件夹的路径)
    • vim nginx.conf (编辑)
    • ../sbin/nginx -s reload
24.2.4 linux 图形操作工具 (用于远程连接上传文件)
  • Mac: filezilla
  • windows: winscp
  • 资料

25. 前端部署线上Linux云服务器

25.1 前端项目总体部署架构和阿里云域名解析A记录配置

转载地址:http://ccqwi.baihongyu.com/

你可能感兴趣的文章
Android电话功能各部分深入探讨
查看>>
Android应用技巧总结
查看>>
Android创建sdcard详细图解
查看>>
Android开发:如何实现TCP和UDP传输
查看>>
Android电源管理相关应用技巧分享
查看>>
Android录音失真具体解决方案
查看>>
Android根文件系统相关应用介绍
查看>>
Android文件系统深入剖析
查看>>
Android判断网络状态方法详解
查看>>
在Android上实现Junit单元测试的四部曲
查看>>
有效控制Android应用程序的耗电量
查看>>
Android术语列表概览
查看>>
全方位解读Android多媒体框架源码
查看>>
Android音乐编程的管理音频硬件
查看>>
Android UI控件组合应用之一:建立数据模型
查看>>
避免Andriod平台图片失真的图片形式
查看>>
Android之Gridview图片列表
查看>>
objdump的使用方法
查看>>
编译错误处理noproguard.classes-with-local.dex已杀死
查看>>
LTE - CSFB技术
查看>>