【实战】Vue全家桶(vue + axios + vue-router + vuex)搭建移动端H5项目

[https://blog.csdn.net/weixin_30478923/article/details/97967687]
转载于:https://www.cnblogs.com/huiwenhua/p/10984352.html

使用Vue全家桶开发移动端页面。
本博文默认已安装node.js。
github链接

一.准备工作

  • 安装vue
npm install vue
  • 安装脚手架vue-cli
npm install -g @vue/cli
  • 创建webpack项目
vue init webpack my-app
image
  • 运行
cd my-appnpm run dev
运行效果

按照提示,在浏览器打开http://localhost:8082/,效果如下:

展示效果

  • 安装状态管理vuex
npm install vuex --save-dev
  • 目录结构
    项目初始目录如下:
    [图片上传失败...(image-27cfb7-1579079412273)]

至此,准备工作已就绪,接下来将进行项目整体的结构设计。

二.项目设计

1.项目目录设计

  • assets目录下创建imagesjscss文件夹。

    • images文件夹下创建index文件夹,用于存放 首页图片(模块化,让项目结构一目了然)。
      [图片上传失败...(image-5022f6-1579079412263)]
  • src目录下创建pages目录,用户存放不同的功能页面。

    • 再在pages目录下创建index首页目录。
      [图片上传失败...(image-b7c3f-1579079412263)]

    • index目录下创建index.vue主文件。
      [图片上传失败...(image-30264c-1579079412263)]

  • 修改router

    • 修改index.js
    import Vue from 'vue'import Router from 'vue-router'import Index from '@/pages/index' Vue.use(Router) export default new Router({  routes: [    {      path: '/',      name: 'Index',      component: Index    }  ]})
    
    • 浏览器效果
      [图片上传失败...(image-94fdd6-1579079412263)]
  • 删除components目录下的文件,将此目录作为页面组件文件夹,在此目录下创建index文件夹,存放index首页的组件。
    [图片上传失败...(image-cf2659-1579079412272)]

  • pages/index/index.vue中引入header组件

<template>  <div class="index-wrap">    <comHeader />    你好,首页  </div></template><script>import header from '@/components/index/header'export default {  data() {    return {    }  },  components: {    comHeader: header  }}</script><style scoped></style>

至此,项目的整个结构被重新设计完成,接下来让我们引入rem.jsless来让我们开发起来更舒服。

2.移动端适配和less编译,让开发变得快乐起来。

  • 移动端适配 rem
    assets/js文件夹下创建common文件夹存放公共js,再在common文件夹下创建rem适配文件js。并在main.js中引入。
// rem.js;(function (designWidth, maxWidth) {    var doc = document,        win = window;    var docEl = doc.documentElement;    var tid;    var rootItem, rootStyle;     function refreshRem() {        var width = docEl.getBoundingClientRect().width;        if (!maxWidth) {            maxWidth = 540;        }        ;        if (width > maxWidth) {            width = maxWidth;        }        //与淘宝做法不同,直接采用简单的rem换算方法1rem=100px        var rem = width * 100 / designWidth;        //兼容UC开始        rootStyle = "html{font-size:" + rem + 'px !important}';        rootItem = document.getElementById('rootsize') || document.createElement("style");        if (!document.getElementById('rootsize')) {            document.getElementsByTagName("head")[0].appendChild(rootItem);            rootItem.id = 'rootsize';        }        if (rootItem.styleSheet) {            rootItem.styleSheet.disabled || (rootItem.styleSheet.cssText = rootStyle)        } else {            try {                rootItem.innerHTML = rootStyle            } catch (f) {                rootItem.innerText = rootStyle            }        }        //兼容UC结束        docEl.style.fontSize = rem + "px";    };    refreshRem();     win.addEventListener("resize", function () {        clearTimeout(tid); //防止执行两次        tid = setTimeout(refreshRem, 300);    }, false);     win.addEventListener("pageshow", function (e) {        if (e.persisted) { // 浏览器后退的时候重新计算            clearTimeout(tid);            tid = setTimeout(refreshRem, 300);        }    }, false);    if (doc.readyState === "complete") {                doc.body.style.fontSize = "16px";    } else {        doc.addEventListener("DOMContentLoaded", function (e) {            doc.body.style.fontSize = "16px";        }, false);    }})(360, 750); // 360为设计图的尺寸,请按照实际设计图修改 // main.jsimport Vue from 'vue'import App from './App'import router from './router'import '@/assets/js/common/rem.js' // 引入rem.js Vue.config.productionTip = false new Vue({  el: '#app',  router,  components: { App },  template: '<App/>'})

至此,rem适配已完成,在写style时便可直接按照 (设计图尺寸 / 100) rem,例如设计图给到元素height为200px,那么用rem则为height: 2rem;

  • less 编译,在写style时,为了高效开发,我们选用less编译。
// 安装less和依赖npm install less less-loader style-loader --save-dev

以header.vue为例

<template>  <div class="header-wrap">    我是头头头    <div class="title">      title    </div>  </div></template> <script> </script> <style scoped lang="less">.header-wrap{  height: 1rem;  background-color: #252627;  .title{    color: #fff;    height: .5rem;  }}</style>

至此就可以开始页面的开发了。

3.状态管理store

  • 安装 vuex
npm install vuex --save
  • 创建store目录结构,至于store原理望大家自已学习掌握。
    [图片上传失败...(image-3daa1d-1579079412272)]

    • index.js
    /** * 组装模块并导出 store */ import Vue from 'vue'import Vuex from 'vuex'import game from './modules/game'import * as actions from './actions'import mutations from './mutations'import getters from './getters' Vue.use(Vuex) const debug = process.env.NODE_ENV !== 'production' const state = {  userInfo:{}} export default new Vuex.Store({  state: state,  actions: actions,  mutations: mutations,  getters:getters,  modules: {    game,  },  strict: debug})
    
  • 使用store

this.$store.dispatch('getData', response.data.data)

4.数据请求 axios

  • src目录下穿件utils目录用于存放工具js。在utils下创建request.jsaxios请求进行封装。
import axios from 'axios'import { Message, MessageBox } from 'element-ui'import config from '../../config/config'import toast from './toast' import store from '@/store' const service = axios.create({  baseURL: 'www.baidu.com',   timeout:0// request timeout})service.interceptors.request.use(    requestConfig => {      let data = {        // 公共请求参数      };      requestConfig.data = Object.assign({}, requestConfig.data, data)      return requestConfig    },    error => {      Promise.reject(error)    })// response interceptorservice.interceptors.response.use(response => {  const res = response.data  if (res.errno === 501) {      MessageBox.alert('系统未登录,请重新登录', '错误', {          confirmButtonText: '确定',          type: 'error'      }).then(() => {      })      return Promise.reject('error')  } else if (res.errno === 502) {      toast.showToast('系统内部错误,请联系管理员维护',1200,'error')      return Promise.reject('error')  } else if (res.errno === 503) {      toast.showToast('请求业务目前未支持',1200,'error')      return Promise.reject('error')  } else if (res.errno === 504) {      toast.showToast('更新数据已经失效,请刷新页面重新操作',1200,'error')      return Promise.reject('error')  } else if (res.errno === 505) {      toast.showToast('更新失败,请再尝试一次',1200,'error')      return Promise.reject('error')  } else if (res.errno === 506) {      toast.showToast('没有操作权限,请联系管理员授权',1200,'error')      return Promise.reject('error')  }  else {      return response    }  }, error => {    toast.showToast('登录连接超时',5 * 1000,'error')    return Promise.reject(error)  })export default service
  • src 目录下常见 api 文件夹,并创建组件index.js
import request from '../utils/request' /** * @method getUserInfo 获取用户信息 * @param query {Object} */export function getUserInfo(query){  return request({    url: 'user/info',    method: 'post',    data: query  })}
  • index.vue中调用
<template>  <div class="index-wrap">    <comHeader />    你好,首页  </div></template> <script>import header from '@/components/index/header'import { getUserInfo } from '@/api/index.js'  // 引入 export default {  data() {    return {     }  },  components: {    comHeader: header  },  methods: {    getInfo(){      getUserInfo()  //业务逻辑      .then(res => {        // do something      })      .catch(response => {})    }  },  created() {    this.getInfo(); //调用  }} </script> <style scoped lang="less"> </style>

三.编译发布

1.编译生成 dist

npm run build //在根目录下生成dis文件夹,可以将此文件夹放到oss上以供不同浏览器浏览。

总结

  • 在开发项目的过程中要考虑项目的模块化。
  • 尽可能的做到代码规范,具体的代码规范可在我的其他博文参考下:
  • 实际项目中的具体问题可私信我,共同解决共同学习。为你能看完本博文而感到愉悦

转载于:https://www.cnblogs.com/huiwenhua/p/10984352.html

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,475评论 4 372
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,744评论 2 307
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,101评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,732评论 0 221
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,141评论 3 297
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,049评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,188评论 2 320
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,965评论 0 213
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,716评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,867评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,341评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,663评论 3 263
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,376评论 3 244
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,200评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,990评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,179评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,979评论 2 279

推荐阅读更多精彩内容