使用Vue全家桶开发移动端页面。
本博文默认已安装node.js。
github链接
npm install vue
npm install -g @vue/cli
vue init webpack my-app
cd my-appnpm run dev
按照提示,在浏览器打开http://localhost:8082/,效果如下:
npm install vuex --save-dev
至此,准备工作已就绪,接下来将进行项目整体的结构设计。
assets
目录下创建images
、js
、css
文件夹。images
文件夹下创建index
文件夹,用于存放 首页图片(模块化,让项目结构一目了然)。src
目录下创建pages
目录,用户存放不同的功能页面。pages
目录下创建index
首页目录。index
目录下创建index.vue
主文件。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 } ]})
删除components
目录下的文件,将此目录作为页面组件文件夹,在此目录下创建index
文件夹,存放index
首页的组件。
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.js
和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.jsVue.config.productionTip = falsenew Vue({ el: '#app', router, components: { App }, template: '<App/>'})
至此,rem适配已完成,在写style时便可直接按照 (设计图尺寸 / 100) rem,例如设计图给到元素height为200px,那么用rem则为height: 2rem
;
// 安装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>
至此就可以开始页面的开发了。
store
vuex
npm install vuex --save
/** * 组装模块并导出 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})
this.$store.dispatch('getData', response.data.data)
axios
src
目录下穿件utils
目录用于存放工具js。在utils
下创建request.js
对axios
请求进行封装。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.jsimport 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>
dist
npm run build//在根目录下生成dis文件夹,可以将此文件夹放到oss上以供不同浏览器浏览。