创建一个完整的vue移动端项目配置


vue的安装及创建一个新项目前一篇文章已经介绍过了,有需要的请看之前的文章

移动端项目

一、关于移动端的一些ui框架
1.Voinc 一个基于 vue.js 和 ionic 样式的 UI 框架(https://wangdahoo.github.io/vonic-documents/#/?id=%E4%BB%8B%E7%BB%8D)
2.Vux 基于WeUI和Vue(2.x)开发的移动端UI组件库 (https://vux.li/#/?id=%E7%AE%80%E4%BB%8B)
3. NutUI 京东轻量级移动端Vue组件库(https://nutui.jd.com/#/index)
4. .Mint UI 由饿了么前端团队推出的 Mint UI (http://mint-ui.github.io/docs/#/zh-cn2)
5. Vant是有赞前端团队基于有赞统一的规范实现的 Vue 组件库(https://github.com/youzan/zent)
6. Cube UI 滴滴 WebApp实现的移动端组件库(https://didi.github.io/cube-ui/#/zh-CN/docs/quick-start)

二、移动端适配

方案:lib-flexible会自动在html的head中添加一个meta name="viewport"的标签,同时会自动设置html的font-size为屏幕宽度除以10,也就是1rem等于html根节点的font-size。使用postcss-px2rem-exclude自动将css中的px转成rem

步骤:1.项目中引入lib-flexible npm install lib-flexible --save
2.在项目的入口main.js文件中引入lib-flexible import ‘lib-flexible/flexible.js’
3.安装postcss-px2rem-exclude npm install postcss-px2rem-exclude --save
4.在项目的根目录下找到文件.postcssrc.js,在里面添加如下代码

"postcss-px2rem-exclude": { remUnit: 75, exclude: /node_modules|folder_name/i // 忽略node_modules目录下的文件(引入的第三方ui的样式不会随之改变) } 
  • 1
  • 2
  • 3
  • 4
  • 5

5.在依赖文件node_modules中找到postcss-px2rem-exclude文件中的lib下的index.js添加以下代码(引入的第三方ui的样式不会随之改变)

try { var flag = options.exclude.includes('/') if (flag) { var arr = options.exclude.split('/') options.exclude = new RegExp(arr[1], arr[2]) } } catch (error) {} 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

在这里插入图片描述

二.一 安装sass-loader(如果使用到了sass编译再安装,不使用无需安装)

npm install --save-dev sass-loader //sass-loader依赖于node-sass ,所以继续安装node-sass npm install --save-dev node-sass //注意1.安装node-sass会报错的原因,一般是因为网慢,所以安装node-sass的时候可以使用cnpm安装 //注意2.sass-loader安装了但是编译还是报错,原因可能是sass-loader版本的问题(8.0.0),在package.json中把sass-loader的版本改成7.3.1,然后删除依赖项,重新安装依赖 
  • 1
  • 2
  • 3
  • 4
  • 5

三、给IDE装vue插件(我现在使用的是vscode,就以vscode为例)
1.在vscode扩展里搜索Vetur
在这里插入图片描述
2.安装完成进行配置
文件–>首选项–>用户代码片段–>点击新建代码片段–取名vue.json 确定
3.删除多余代码
4.粘贴下边的代码vue模板 (如果使用css预编译,则style的类型是scss,如不使用改为css)

{ "Print to console": { "prefix": "vue", "body": [ "<!-- $1 -->", "<template>", "<div class='$2'>$5</div>", "</template>", "", "<script>", "//这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)", "//例如:import 《组件名称》 from '《组件路径》';", "", "export default {", "//import引入的组件需要注入到对象中才能使用", "components: {},", "data() {", "//这里存放数据", "return {", "", "};", "},", "//监听属性 类似于data概念", "computed: {},", "//监控data中的数据变化", "watch: {},", "//方法集合", "methods: {", "", "},", "//生命周期 - 创建完成(可以访问当前this实例)", "created() {", "", "},", "//生命周期 - 挂载完成(可以访问DOM元素)", "mounted() {", "", "},", "beforeCreate() {}, //生命周期 - 创建之前", "beforeMount() {}, //生命周期 - 挂载之前", "beforeUpdate() {}, //生命周期 - 更新之前", "updated() {}, //生命周期 - 更新之后", "beforeDestroy() {}, //生命周期 - 销毁之前", "destroyed() {}, //生命周期 - 销毁完成", "activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发", "}", "</script>", "<style lang='scss' scoped>", "//@import url($3); 引入公共css类", "$4", "</style>" ], "description": "Log output to console" } } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55

6.上面代码中的 “prefix”: “vue”, 就是快捷键;保存好之后新建.vue结尾的文件试试(输入vue 按tab键就可以)

在这里插入图片描述
四、vue路由
1.定义组件,刚刚已经用模板定义了一个组件
2.在router index.js文件里引入刚刚写好的组件
在这里插入图片描述
我在这里是用的vue-router提供的按模块加载方式
下面2行代码,没有指定webpackChunkName,每个组件打包成一个js文件。

const ImportFuncDemo1 = () => import('../components/ImportFuncDemo1')
const ImportFuncDemo2 = () => import('../components/ImportFuncDemo2')
  • 1
  • 2

下面2行代码,指定了相同的webpackChunkName,会合并打包成一个js文件。

// const ImportFuncDemo = () => import(/* webpackChunkName: 'ImportFuncDemo' */ '../components/ImportFuncDemo')
// const ImportFuncDemo2 = () => import(/* webpackChunkName: 'ImportFuncDemo' */ '../components/ImportFuncDemo2')
  • 1
  • 2

3.配置


import Vue from "vue"; import VueRouter from "vue-router"; Vue.use(VueRouter) // 按模块加载... const HelloWorld= () => import('../components/HelloWorld') const routes=[{ path: '/', redirect: '/HelloWorld', name:'HelloWorld' },{ path:'/HelloWorld', component: HelloWorld, name:'HelloWorld' } ] const router = new VueRouter({ routes, mode: 'history', // vuex的严格模式 strict: process.env.NODE_ENV !== 'production', // 这个整体做的是:在路由的history模式下,一些列表页利用缓存模式来记录位置(一般是返回不刷新,前进刷新),一般用了scrollBehavior, //同时还用keep-alive(缓存),activated(缓存下触发的钩子)配合做列表页的返回记录位置。缓存模式也有坑,就是何时清除缓存,一般是从新进入页面就清除。 //回到主题,滚动行为就是:例如一个列表页,滑动了很多,点进去、再返回记录刚刚的位置 scrollBehavior (to, from, savedPosition) { if (savedPosition) { return savedPosition } else { if (from.meta.keepAlive) { from.meta.savedPosition = document.body.scrollTop; } return { x: 0, y: to.meta.savedPosition ||0} } } }) export default router 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

4.路由文件注入到main.js文件中

import Vue from 'vue'; import router from './router/index'; import 'lib-flexible/flexible.js'; import App from './App' new Vue({ el: '#app', router, components: { App }, template: '<App/>' }) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

5.在 app.vue里配置router-view

<template> <div id="app"> <router-view></router-view> </div> </template> 
  • 1
  • 2
  • 3
  • 4
  • 5

6.路由跳转及传参方式

 1.$router为VueRouter实例,想要导航到不同URL,则使用$router.push方法
 2.$route为当前router跳转对象,里面可以获取name、path、query、params等


(1)设置动态路由
        {
    		path:'/shopDetails/:id',
   	 		component: shopDetails,
   			 name:'shopDetails'
         }
        跳转this.$router.push('/shopDetails/'+id)
        获取id通过   this.$route.params.id
       
(2)通过params携带参数 ,路由属性中的name来匹配路由    
        
         {
    	 	path:'/shopDetails',
		   	 component: shopDetails,
		   	 name:'shopDetails'
         }
         跳转 this.$router.push({name:'shopDetails',params:{id:id}})  
         获取  this.$route.params.id
(3)通过path匹配路由,query携带参数 这种情况下 query传递的参数会显示在url后面?id=?
         {
	    	 path:'/shopDetails',
		   	 component: shopDetails,
		   	 name:'shopDetails'
         }
         跳转 this.$router.push({path:'/shopDetails',query:{id:id}})  
         获取  this.$route.query.id
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

7.query和params的区别

1.动态路由和query属性传值 页面刷新参数不会丢失, params会丢失 2.动态路由一般用来传一个参数时居多(如详情页的id), query、params可以传递一个也可以传递多个参数 。
2.直白的来说query相当于get请求,页面跳转的时候,可以在地址栏看到请求参数,而params相当于post请求,参数不会再地址栏中显示

8.路由的模式

五、axios请求

axios文档上的教程在这里就不重复叙述了,需要的看文档,我在这里贴下我的使用教程
axios文档地址:https://www.npmjs.com/package/axios

1.安装 npm install axios
2.在utils下新建一个axios文件用来配置axios

import axios from 'axios'; const qs = require('qs'); const service=axios.create({ baseURL: process.env.BASE_API, //请求公共地址,baseURL`将被添加到`url`,所以后边请求只需api的方式即可 timeout: 5000, //请求响应时间 }) // 是否携带cookie信息,默认为false,根据项目需求设置 service.defaults.withCredentials = true; // 添加一个请求拦截器 service.interceptors.request.use(function (config) { // 对请求数据做些事 if(config.method === 'post'){ //post传参序列化 config.data = qs.stringify(config.data); } return config; }, function (error) { return Promise.reject(error); }); // 添加一个响应拦截器 service.interceptors.response.use(function (response) { // 对响应数据做些事 return response; }, function (error) { console.log(error) // Do something with response error return Promise.reject(error); }); export default service; 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

3.新建一个api文件,这里边存放所有的请求函数,方便查找管理

import axios from '../utils/axios'; // 首页banner export function banner(){ return axios({ url:'/wxchat/xxx.action', //请求的地址 method:'POST' }) } // post请求带参数 export function qiang(activityStatusType){ return axios({ url:'/wxchat/xxx.action', method:'POST', data:{activityStatusType:activityStatusType} }) } // get请求 export function moneys(){ return axios({ url: '/sd-web/xxx', method: 'get' }); } // get请求带参数 export function moneys(ids){ return axios({ url: '/sd-web/xxx', method: 'get', params:{id:ids} }); } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

4.页面实际应用

 import {banner} from '../../api/api'; //在页面上引入需要的请求函数 //在生命周期函数或者需要的方法里运用 mounted() { banner().then(response => { this.banner=response.data.data.SlAdvertisTabList }).catch(err=>{ console.log(err) }); }, 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

5.跨域配置

(1)在config文件夹写的index.js里配置跨域
在这里插入图片描述

proxyTable: { '/wxchat': { target: 'xxx', //目标接口域名 changeOrigin: true, //是否跨域 secure: false, //target默认情况下,不接受运行在HTTPS上,且使用了无效证书的后端服务器。如果你想要接受, 则需设置该项为false // pathRewrite: { // 如果接口本身没有/wxchat需要通过pathRewrite来重写了地址 重写接口 // '^/wxchat: ' ' // } } }, 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

注:我写的这个项目里,本身存在/wechat通用前缀,所以我没有用pathRewrite重写,如果你们接口里没有通用前缀的话,是要进行重写的

上面配置中,’^/wxchat’ 其实是一个正则表达式

‘^/wxchat’ 应该拆分成 ‘^’ 和 ‘/wxchat’ 两个字符串,其中 ‘^’ 匹配的是字符串最开始的位置。

‘/wxchat’: {}, 就是告诉node, 我接口只要是’/wxchat’开头的才用代理.所以你的接口就要这么写/wxchat/xx/xx. 最后代理的路径就是 http://xxx.xx.com/wxchat/xx/xx.
可是不对啊, 我正确的接口路径里面没有/wxchat啊. 所以就需要 pathRewrite,用’’^/wxchat’’:’’, 把’/wxchat’去掉, 这样既能有正确标识, 又能在请求接口的时候去掉wxchat

接口没有通用前缀的开发环境的配置

'use strict' const merge = require('webpack-merge') const prodEnv = require('./prod.env') module.exports = merge(prodEnv, { NODE_ENV: '"development"', BASE_API: '"/wechat"', //在跨域里配置的//wechat,接口里就不用写通用前缀了,就按照正常接口写就可以了 }) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

接口有通用前缀的开发环境配置

'use strict' const merge = require('webpack-merge') const prodEnv = require('./prod.env') module.exports = merge(prodEnv, { NODE_ENV: '"development"', BASE_API: '""', //这里为空就好了,通用前缀就写在接口里 }) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

六、vuex的使用

关于vuex的使用 ,什么时候该使用vuex? 当你觉得需要全局的状态,但是通过别的方式又太麻烦的时候,你就需要了,比如说我现在做的一个app项目,header组件是一个公共组件,那么header组件里边的标题怎么能随着页面的跳转而改变呢,vuex就可以做到 (个人理解,有不同理解的可以评论)
缺点:vuex页面重新刷新,数据会丢失 解决方法:存本地,state数据可以从本地获取

1.vuex中,有默认的五种基本的对象:

  • state 全局要访问的值
  • getters 实时监听state值的变化,对数据获取之前的再次编译,可以理解为state的计算属性。
  • mutations 改变state里的初始值 同步的
  • actions 异步触发mutations里面的方法
  • modules:store的子模块,为了开发大型项目,方便状态管理而使用的。这里我们就不解释了,用起来和上面的一样。

2.下载安装vuex npm install vuex --save
3.在src下新建一个store文件夹创建一个index.js 用来配置.
4.引入vue,vuex,使用use全局注入插件

import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex); const store=new Vuex.Store({ // 设置全局要访问的state值 state:{ title:'测试标题', //头部标题 } }) export default store; 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

5.在main.js里引入store,并全局注入

import Vue from 'vue'; import router from './router/index'; import store from './store'; import 'lib-flexible/flexible.js'; import App from './App' new Vue({ el: '#app', router, store, components: { App }, template: '<App/>' }) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

6.在任意组件内测试刚刚写的标题

<template> <div class='orderDetails'> {{$store.state.title}} </div> </template> 
  • 1
  • 2
  • 3
  • 4
  • 5

7.如图所示,刚刚的标题已经设置成功了
在这里插入图片描述
8.上图所示已经成功设置了标题,那怎么让它的标题改变呢,就要用到mutations对象了,我们在mutations对象里定义一个改变标题的方法,mutations里面的参数,第一个默认为state,接下来的为自定义参数。

 // 改变state里的初始值 同步的 mutations :{ TITLE(state,title){ return state.title=title }, }, 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

9.看下测试结
在这里插入图片描述在这里插入图片描述
9.从图上可以看出这个已经实现了,接下来看异步操作

 // 异步触发mutations里面的方法 在外部组件里进行全局执行actions里面方法的时候,你只需要用执行this.$store.dispatch('title',132) 这样就可以全局改变改变标题的值了 actions:{ title({commit},title){ commit('TITLE',title) }, } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

就不上图了,跟之前同步操作是一样的结果

10.vuex同步和异步的区别

1、当点发送过快,页面中渲染的内容与state中的数据不一致,vuex里面的state变得慢,且不持续更新
2、action中是可以做到页面中state中数据保持一致
3、当你的操作行为中含有异步操作,比如向后台发送请求获取数据,就需要使用action的dispatch去完成了。其他使用commit即可。

七、打包上线
1.

执行  npm run build 命令
  • 1

2.执行完成后,你会发现你的目录下多了一个dist的文件夹,这个就是打包的数据

3.打包之后出现页面空白的原因
3.1 css,js路径引用错误的问题

解决:到config文件夹中打开index.js文件。
文件里面有两个assetsPublicPath属性,更改第一个,也就是更改build里面的assetsPublicPath属性:
assetsPublicPath属性作用是指定编译发布的根目录,‘/’指的是项目的根目录 ,’./’指的是当前目录。
在这里插入图片描述

3.2 设置路由history模式

解决:改为hash或者直接把模式配置删除,让它默认的就行 。如果非要使用history模式的话,需要你在服务端加一个覆盖所有的情况的候选资源:如果URL匹配不到任何静态资源,则应该返回一个index.html,这个页面就是你app依赖页面。

3.3 在css中引入的背景图片的路径问题

解决:到build文件夹中打开util.js文件,添加路径代码

在这里插入图片描述


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM