您的位置:首页 > Web前端 > Vue.js

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

2019-08-09 14:49 447 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/lei_0912/article/details/98867087

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

移动端项目

一、关于移动端的一些ui框架
1.Voinc 一个基于 vue.js 和 ionic 样式的 UI 框架(https://wangdahoo.github.io/vonic-documents/#/?id=介绍)
2.Vux 基于WeUI和Vue(2.x)开发的移动端UI组件库 (https://vux.li/#/?id=简介)
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的样式不会随之改变)
}

三、给IDE装vue插件(我现在使用的是vscode,就以vscode为例)
1.在vscode扩展里搜索Vetur

2.安装完成进行配置
文件–>首选项–>用户代码片段–>点击新建代码片段–取名vue.json 确定
3.删除多余代码
4.粘贴下边的代码vue模板

{
"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"
}
}

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')

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

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

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 !== 'produc
7ff7
tion',
// 这个整体做的是:在路由的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

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/>'
})

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

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

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

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;

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}
});
}

4.页面实际应用

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

5.跨域配置

(1)在config文件夹写的index.js里配置跨域

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

注:我写的这个项目里,本身存在/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,接口里就不用写通用前缀了,就按照正常接口写就可以了
})

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

'use strict'
const merge = require('webpack-merge')
const prodEnv = require('./prod.env')

module.exports = merge(prodEnv, {
NODE_ENV: '"development"',
BASE_API: '""',     //这里为空就好了,通用前缀就写在接口里
})

六、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;

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/>'
})

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

<template>
<div class='orderDetails'>
{{$store.state.title}}
</div>
</template>

7.如图所示,刚刚的标题已经设置成功了

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

// 改变state里的初始值 同步的
mutations :{
TITLE(state,title){
return state.title=title
},
},

9.看下测试结

9.从图上可以看出这个已经实现了,接下来看异步操作

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

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

10.vuex同步和异步的区别

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

七、打包上线
1.

执行  npm run build 命令

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

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

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

3.2 设置路由history模式

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

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: