最近在学习vue时也了解到一些常用的UI组件,有用于PC的和用于移动端的。用于PC的有:Element(饿了么)、iView等;用于移动端APP的有Vux、Mint UI(饿了么)、Vant(有赞团队)、cube-ui(滴滴)。

  想做一个移动端微信公众号使用的界面,于是选择用mintUI。

  mintUI官网:http://mint-ui.github.io/docs/#/en2/quickstart

1.项目中引入mint-ui

1.下载以及配置

(1)下载:

E:\HBuilderSpace\vue-demo>cnpm install --save mint-ui

(2)引入:可以按需引入,也可以全部引入

全部引入的方式:

main.js:

import Vue from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';
import MintUI from 'mint-ui'
import 'mint-ui/lib/style.css' Vue.config.productionTip = false;
Vue.use(MintUI) new Vue({
router,
store,
render: h => h(App),
}).$mount('#app');

比如我们在home.vue使用头部固定的header:(只是简单的实验,需要的时候到官网查阅即可)

<template>
<div class="home">
<mt-header title="multiple button">
<router-link to="/" slot="left">
<mt-button icon="back">back</mt-button>
<mt-button @click="handleClose">close</mt-button>
</router-link>
<mt-button icon="more" slot="right"></mt-button>
</mt-header>
<ul class="footer">
<router-link class="icons" to="/home/user">个人中心</router-link>
<router-link class="icons" to="/home/contact">通讯录</router-link>
</ul>
<router-view/>
</div>
</template> <script>
export default {
name: 'home',
};
</script> <style scoped lang="scss">
li{
list-style: none;
}
.footer{
position: fixed;
width: 100%;
height: 60px;
line-height:60px;
left: 0px;
bottom: 0px;
display: flex;
flex-flow: row nowrap;
justify-content: space-around;
}
.icons{
font-size: 16px;
flex: 1;
text-align:center;
border-top: 1px solid #42b983;
} a {
color: #42b983;
&.active{
color: #fff;
background:#42b983;
}
}
</style>

最终效果如下:

按需引入的方式:(比如我们按需引入所需的按钮模块)

(1)main.js引入模块和css:

import Vue from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';
import { Button } from 'mint-ui';
import 'mint-ui/lib/style.css' Vue.component(Button.name, Button); Vue.config.productionTip = false; new Vue({
router,
store,
render: h => h(App),
}).$mount('#app');

(2).vue文件直接使用:

<mt-button size="large" type="primary">large</mt-button>

结果:

2. 重构之前的项目,改为mintUI

主要代码如下:

App.vue:只定义了入口,在router/index.js中设置默认路由

<template>
<div id="app">
<router-view/>
</div>
</template> <style lang="scss">
*{
padding: 0px;
text-align: center;
}
</style>

Main.js:按需引入所需的mint模块,并且用Vue.component(name, options)发布为全局组件

import Vue from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';
import 'mint-ui/lib/style.css'
import { Button } from 'mint-ui';
import { Field } from 'mint-ui';
import { Header } from 'mint-ui';
import { Navbar, TabItem } from 'mint-ui'; Vue.component(Navbar.name, Navbar);
Vue.component(TabItem.name, TabItem);
Vue.component(Header.name, Header);
Vue.component(Field.name, Field);
Vue.component(Button.name, Button); Vue.config.productionTip = false; new Vue({
router,
store,
render: h => h(App),
}).$mount('#app');

router/index.js:

import Vue from 'vue';
import VueRouter from 'vue-router';
import Login from '../views/Login.vue'; Vue.use(VueRouter); const routes = [
{
path: '/',
name: 'login',
component: Login,
},
{
path: '/home',
name: 'home',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/Home.vue'),
redirect: '/home/user',
children: [{
path: 'user',
name: 'user',
component: () => import(/* webpackChunkName: "about" */ '../views/User.vue')
}, {
path: 'contact',
name: 'contact',
component: () => import(/* webpackChunkName: "about" */ '../views/Contact.vue')
}]
},
]; const router = new VueRouter({
mode: 'hash',
base: process.env.BASE_URL,
linkActiveClass: 'active',
routes,
}); export default router;

定义了默认路由是Login,Login采用一次性加载,其他采用懒加载。登录成功之后的/home重定向到子路由/home/user。

store/index.js

import Vue from 'vue';
import Vuex from 'vuex'; Vue.use(Vuex); export default new Vuex.Store({
state: {
username: ''
},
mutations: {
setLoginUsername(state, username) {
state.username = username
},
},
actions: {
setLoginUsernameFun(context, username) {
context.commit("setLoginUsername", username);
},
},
modules: {
},
});

  vuex管理组件定义了一个属性与修改属性的方法

views/Login.vue

<template>
<div class="login">
<form v-if="!isReg">
<h1>欢迎来到XXX系统</h1>
<br/>
<mt-field label="用户名" placeholder="Input username" v-model="name"></mt-field>
<mt-field label="密 码" placeholder="Input password" type="password" v-model="password"></mt-field>
<mt-button size="large" type="primary" @click.prevent="login()" key="login">登录</mt-button>
<br/>
<mt-button size="large" type="default" @click.prevent="reg()" key="reg" plain>注册</mt-button>
<br/> </form>
<div v-else>
<h1>注册</h1>
<br/>
<br/>
<mt-field label="用户名" placeholder="Input username" v-model="name"></mt-field>
<mt-field label="密 码" placeholder="Input password" type="password" v-model="password"></mt-field>
<mt-field label="密 码" placeholder="Input passwordRepeat" type="password" v-model="passwordRepeat"></mt-field>
<mt-button size="large" type="primary" @click="addUser()" key="doReg">注册</mt-button>
<br/>
<mt-button size="large" type="default" @click="cancel()" key="cancel" plain>取消</mt-button>
</div> </div>
</template> <script>
import store from '@/store';
import { MessageBox } from 'mint-ui';
import { Toast } from 'mint-ui'; export default {
name: 'login',
store,
data() {
return {
isReg: false,
name: '',
password: '',
};
},
methods: {
login() {
this.isReg = false;
var nameLocal = localStorage.getItem("name");
var passwordLocal = localStorage.getItem("password");
if (nameLocal == '' || passwordLocal == '') {
MessageBox.alert("您还没注册!", "title");
return;
} if (nameLocal === this.name && passwordLocal === this.password) {
store.dispatch("setLoginUsernameFun", nameLocal);
Toast("登录成功");
this.$router.push('/home')
return false;
} MessageBox.alert("账号密码错误");
},
reg() {
this.name = '';
this.password = '';
this.passwordRepeat = '';
this.isReg = true;
},
addUser() {
if (this.name == '' || this.password == '') {
MessageBox.alert("必填用户名密码!!!");
return;
} if (this.password !== this.passwordRepeat) {
MessageBox.alert("两次密码不一致!!!");
return;
} localStorage.setItem("name", this.name);
localStorage.setItem("password", this.password);
this.name = '';
this.password = '';
this.isReg = false;
Toast("注册成功");
},
cancel() {
this.isReg = false;
}
},
};
</script>

  定义了两个表单,登录和注册用的,用isReg属性进行切换。注册成功保存到本地localStorage。

  注意:(1)mint中button默认类型是submit,所以需要阻止事件的默认行为。(2)mintUI的JS组件不可以在main.js中全局引入。比如MessageBox、Toast。

views/Home.vue

<template>
<div class="home">
<mt-header title="XXX管理系统">
<router-link to="/" slot="left">
<mt-button icon="back">back</mt-button>
</router-link>
<mt-button icon="more" slot="right"></mt-button>
</mt-header> <router-view/>
<ul class="footer">
<router-link class="icons" to="/home/user">个人中心</router-link>
<router-link class="icons" to="/home/contact">通讯录</router-link>
</ul>
</div>
</template> <script>
export default {
name: 'home',
};
</script> <style scoped lang="scss">
li {
list-style: none;
} .footer {
position: fixed;
width: 100%;
height: 60px;
line-height: 60px;
left: 0px;
bottom: 0px;
display: flex;
flex-flow: row nowrap;
justify-content: space-around;
} .icons {
font-size: 16px;
flex: 1;
text-align: center;
border-top: 1px solid #42b983;
} a {
color: #42b983;
&.active {
color: #fff;
background: #42b983;
}
}
</style>

  定义了两个子路由,并用secc语法定义了样式。例如样式 a 里面的&.active 会被解析为 a.active,&代表当前选择器。 scoped  代表默认的css作用域是当前页面,如果不写会影响全局css样式,一般为当前页面。

views/Uer.vue

<template>
<div class="user">
个人中心。欢迎您: {{getLoginUsername()}}
</div>
</template> <script>
import store from '@/store'; export default {
name: 'User',
store,
methods: {
getLoginUsername() {
return store.state.username
},
},
};
</script>

views/Contact.vue:

<template>
<div class="user">
通讯录
</div>
</template>

3.最终效果:

(1)登录:

(2)登录之后主页面:

4.引入axios实现前后端分离的注册、登录效果

1.安装axios

cnpm install --save axios

2.目录结构

3.重要代码解释

src/axios/index.js内容如下:

import axios from "axios";
import { MessageBox } from 'mint-ui'; // 引入常量模块
import Constants from '@/Constants.vue'; // 修改axios请求的默认配置(配置会以一个优先顺序进行合并。这个顺序是:在 lib/defaults.js 找到的库的默认值,然后是实例的 defaults 属性,最后是请求的 config 参数。)
//` baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。
axios.defaults.baseURL = Constants.projectBaseAddress; // 添加请求拦截器
axios.interceptors.request.use(function(config) {
// 模拟处理前增加token
return config;
}, function(error) {
// 对请求错误做些什么
return Promise.reject(error);
}); // 添加响应拦截器
axios.interceptors.response.use(function(response) {
// 对响应数据做点什么
if(response.data.success) {
// 如果是成功返回信息之后提取出来返回以供后面的调用链使用(后台返回的JSON数据)
return response.data;
} else {
MessageBox.alert(response.data.msg);
return new Promise(function(resolve, reject) {
// resolve('success1');
// reject('error');
});
}
}, function(error) {
// 对响应错误做点什么
return Promise.reject(error);
}); export default axios;

  对axios进行改造之后重新发布对象。所有的请求前面增加一个baseURL,其值是Constants模块的projectBaseAddress。增加拦截器同一对后台返回false的结果进行弹窗,返回为true的提取返回的数据。

src/Constants.vue:

<script>
export default {
name: 'Constants',
projectBaseAddress: '/api'
};
</script>

  作为一个全局JS工具类发布,使用的方式参考上面axios/index.js中使用。

vue.config.js中使用代理对所有/api/访问进行代理,解决跨域问题。当然跨域也可以后台设置允许跨域。这个参考express跨域设置规则就可以。

module.exports = {
publicPath: './',
lintOnSave: false,
devServer: {
proxy: {
'/api': {
target: 'http://localhost:8088',
ws: true,
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
}
}
}
}

Login.vue进行修改:登录注册采用同步的方式进行登录注册。async关键字+await。登录成功将username、fullname传回前台存入localStorage。

<template>
<div class="login">
<form v-if="!isReg">
<h1>欢迎来到XXX系统</h1>
<br/>
<mt-field label="用户名" placeholder="Input username" v-model="username"></mt-field>
<mt-field label="密 码" placeholder="Input password" type="password" v-model="password"></mt-field>
<mt-button size="large" type="primary" @click.prevent="login()" key="login">登录</mt-button>
<br/>
<mt-button size="large" type="default" @click.prevent="reg()" key="reg" plain>注册</mt-button>
<br/> </form>
<div v-else>
<h1>注册</h1>
<mt-field label="用户名" placeholder="Input username" v-model="username"></mt-field>
<mt-field label="用户姓名" placeholder="Input userfullname" v-model="userfullname"></mt-field>
<mt-field label="密 码" placeholder="Input password" type="password" v-model="password"></mt-field>
<mt-field label="电 话" placeholder="Input phone" v-model="phone"></mt-field>
<mt-radio title="性 别" v-model="sex" :options="sexOptions" align="right">
</mt-radio>
<mt-button size="large" type="primary" @click="addUser()" key="doReg">注册</mt-button>
<br/>
<mt-button size="large" type="default" @click="cancel()" key="cancel" plain>取消</mt-button>
</div> </div>
</template> <script>
import store from '@/store';
import { MessageBox } from 'mint-ui';
import { Toast } from 'mint-ui';
import axios from "@/axios"; var login = {
name: 'login',
store,
data() {
return {
isReg: false,
username: '',
userfullname: '',
password: '',
phone: '',
sex: '',
sexOptions: [{
label: '男性',
value: '男'
},
{
label: '女性',
value: '女'
}
]
};
},
methods: {
async login() {
this.isReg = false;
if(this.username == "" || this.password == "") {
MessageBox.alert("账号密码必须输入");
return;
} var response = await axios.post('/doLoginJSON.html', {
username: this.username,
password: this.password
}); if(response.success) {
Toast("登录成功"); // 将用户存入localStorage
localStorage.setItem("username", response.data.username);
localStorage.setItem("userfullname", response.data.userfullname); // 跳转路由
this.$router.replace("/home");
}
},
reg() {
this.username = '';
this.password = '';
this.isReg = true;
},
async addUser() {
if(this.username == '' || this.password == '' || this.userfullname == '' || this.phone == '' || this.sex == '') {
MessageBox.alert("请检查必填字段!!!");
return;
} var response = await axios.post('/user/addUserJSON.html', {
username: this.username,
userfullname: this.userfullname,
password: this.password,
phone: this.phone,
sex: this.sex,
}); if(response.success) {
this.isReg = false; Toast("注册成功");
}
},
cancel() {
this.isReg = false;
}
}
}
export default login;
</script>

User.vue进行修改:(从localStorage获取当前登录的用户信息)

<template>
<div class="user">
个人中心。欢迎您: {{getLoginUsername()}}
</div>
</template> <script>
import store from '@/store'; export default {
name: 'User',
store,
methods: {
getLoginUsername() {
var username = localStorage.getItem("username");
var userfullname = localStorage.getItem("userfullname");
return userfullname;
},
},
};
</script>

5.引入Vux

vux官网:https://vux.li/

  查看了vux官网发现git上star的人数也不少,组件也满足自己的使用需求,于是选择了vux。而且vux提供了树形插件、图表统计插件以及常用的md5等工具函数。

1.简介

VUX(读音 [v’ju:z],同 views)是基于WeUI和Vue(2.x)开发的移动端UI组件库,主要服务于微信页面。

基于webpack + vue-loader + vux可以快速开发移动端页面,配合vux-loader方便你在WeUI的基础上定制需要的样式。

vux-loader保证了组件按需使用,因此不用担心最终打包了整个vux的组件库代码。

VUX并不完全依赖于WeUI,VUX 在 WeUI 的基础上扩展了多个常用组件,但是尽量保持整体UI样式接近WeUI的设计规范。

几个名词解释:

vue-loader:用于编译 .vue 文件,官方模板已经帮你配置好。

vux-loader:VUX 组件库的 webpack loader,实现按需加载等功能。它不是替代 vue-loader 而是配合 vue-loader 使用。如果你使用 vux2 模板,暂不需要手动使用它。

官网的建议

  VUX 必须配合 vux-loader 使用,如果不使用 vux2 模板请按照文档正确配置。less@3.x 有严重的兼容问题,请暂时使用 less@^2.7.3。暂未适配 vue-cli@3.x。

2.安装

(1)安装vux

npm install vux --save

(2)安装less、less-loader (//安装less,vux使用的是less)

npm install less less-loader --save-dev

(3)安装vux-loader:vux是基于vux-loader的,所以必须要安装这个,否则会报一大堆错

npm install vux-loader --save-dev

(4)安装vue-loader:我没安装的时候报错,所以安装了该模块

npm install vue-loader@14.2. -D

(5)修改配置:vue.config.js:增加如下配置(vue-cli3.x版本的配置方式)

    configureWebpack: config => {
require('vux-loader').merge(config, {
options: {},
plugins: ['vux-ui']
})
}

3.组件的使用:这里使用x-button组件

(1)安装组件,也可以称为注册组件:

局部注册:在模块中引入:

import { XButton } from 'vux'

export default {
components: {
XButton
}
}

全局注册:在main.js中(有点类似于mintui的按需注册组件)

import { XButton } from 'vux'
Vue.component('x-button', XButton)

(2)使用组件:

<x-button type="warn">vux按钮</x-button>

  

至此简单的引入了vux,接下来在使用的时候参考文档使用所需组件即可。

补充:关于vux的不一样的地方

(1)@click 绑定事件不生效。按照Vue文档,在组件上绑定原生点击事件请使用@click.native。

6.错误小记载

(1)npm run build的时候报错:

Invalid options object. CSS Loader has been initialised using an options object that does not match the API schema.
- options has an unknown property 'minimize'

在css-loader1.0版本的时候移除了该属性,我没有找到替代办法,所以我选择了降低css-loader版本解决:

npm install css-loader@0.28.

总结:

0.@代表的是src目录

1.vue中引入全局JS变量和JS方法有两种:

(1)将全局的东西提取到单独的模块中,比如:抽到Constants.vue中,内容如下

<script>
export default {
name: 'Constants',
projectBaseAddress: '/api',
method1() {
return "method1";
}
};
</script>

其他模块使用的方法:引入模块,使用即可:

import Constants from '@/Constants.vue';
console.log(Constants.projectBaseAddress);
console.log(Constants.method1());

(2)通过Vue.prototype挂载到Vue实例中。可以挂载对象、函数、变量等,也可以是从模块中引入的对象。

var Constants = {
name: 'Constants',
projectBaseAddress: '/api',
method1() {
return "method1";
}
};
Vue.prototype.Constants = Constants;

组件中调用即可:

console.log(this.Constants);

2.axios是基于Promise的ajax库,可以用async+await实现同步请求,其拦截器也可以做一些统一处理。

3.axios跨域请求可以在后台设置允许跨域+携带cookie,之后设置axios携带cookie。也可以使用代理,上面是使用了代理。

前台git地址:https://github.com/qiao-zhi/vue-demo.git

后台git地址:https://github.com/qiao-zhi/springboot-ssm

vue中引入mintui、vux重构简单的APP项目的更多相关文章

  1. vue中引入babel步骤

    vue中引入babel步骤 vue项目中普遍使用es6语法,但有时我们的项目需要兼容低版本浏览器,这时就需要引入babel插件,将es6转成es5. 1.安装babel-polyfill插件 npm ...

  2. vue中引入json数据,不用本地请求

    1.我的项目结构,需要在Daily.vue中引入daily.js中的json数据 2.把json数据放入一个js文件中,用exports导出,vscode的json格式太严格了,很多数据,调了一个多小 ...

  3. vue中引入mui报Uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them的错误

    在vue中引入mui的js文件的时候,报如下的错误: 那是因为我们在用webpack打包项目时默认的是严格模式,我们把严格模式去掉就ok了 第一步:npm install babel-plugin-t ...

  4. vue中引入css文件

    两种方式引入css文件,一种是直接在main.js中引入(也可以在其他的.vue文件中的<script></script>标签中),即下面这种写法: import 'eleme ...

  5. Vue中引入TradingView制作K线图

    **前言: 本文使用的是1.10版本 , 可通过TradingView.version()查看当前版本. 附上开发文档地址:https://zlq4863947.gitbooks.i...** 一.修 ...

  6. vue中引入swiper(vue中的滑块组件vue-awesome-swiper)

    第一步安装 npm install vue-awesome-swiper --save 第二部在main.js中引入 import VueAwesomeSwiper from 'vue-awesome ...

  7. Vue中引入bootstrap导致的CSS问题

    最近在进行vue.js+webpack进行模块化开发的时候,遇到一个奇怪的问题. 问题是这样的: 1. 在main.js文件中引入bootstrap的js和css. 2. 自己写了一个Header.v ...

  8. vue中引入js,然后new js里的方法

    阿里云Web播放器Web端使用SDK说明:https://help.aliyun.com/document_detail/51991.html?spm=5176.11065259.1996646101 ...

  9. Visual Studio 2013中引入Web Service的简单方法visual studio 引用 wsdl

    http://blog.csdn.net/wangzhongbo_24/article/details/49954191 Web Service有三种表示方式 三种方式分别为WSDL.Endpoint ...

随机推荐

  1. java获取下一天的日期

    我们来看看Java怎么获取下一天的日期: 哈哈哈,开玩笑啦,这个只是个段子. "哪怕悲伤有1000种,快乐有1种就够了."

  2. [debug]ubuntu共享文件夹所在目录

    使用Vmware虚拟机,Vmware Tools工具的复制粘贴一直无效,之后采用共享文件夹. 其默认的是在 \mnt\hgfs 下,在Vmware的设置中建立好文件夹,将文件传入进去,之后就可以去 \ ...

  3. MySQL 联表查询

    关系型数据库,免不了表之间存在各种引用与关联.这些关联是通过主键与外键搭配来形成的.所以,取数据时,很大情况下单张表无法满足需求,额外的数据则需要将其他表加入到查询中来,这便是 JOIN 关键字完成的 ...

  4. 2018-8-10-win10-uwp-进度条-Marquez-

    原文:2018-8-10-win10-uwp-进度条-Marquez- title author date CreateTime categories win10 uwp 进度条 Marquez li ...

  5. char.IsWhiteSpace(str,num),TimeSpan

    IsWhiteSpace(String, Int32) 指示指定字符串中位于指定位置处的字符是否属于空格类别. TimeSpan TimeSpan ts=new TimeSpan(4,30,0); C ...

  6. PHP面试题2019年奇虎360面试题及答案解析

    一.单选题(共29题,每题5分) 1.以下代码 a.php 输出的结果是? a.php 的代码如下: b.php的代码如下: A.foo in a B.什么也不输出 C.报错 D.foo in b 参 ...

  7. 协议分析中的TCP/IP网络协议

    - 链路层 第一层包含源mac及目的mac,随着传输路径的变化会发生变化,在mac之后,是下层网络协议的类型,图中,下层为IP协议. 在协议解析中,需要关注的是图中type这个字段的内容. - 网络层 ...

  8. 告诉你如何在Xcode中安装炫酷的插件!!!!!

    (如果你已经有了自己喜欢的插件,你可以直接找到该插件的下载地址,下载下来,参照下面的步骤来安装到Xcode工程之中) 如果还没有找到自己想要的插件,那么推荐你在开源中国社区http://www.osc ...

  9. 彻底解决Python3写爬虫或网站时的乱码问题

    第一次写贴子,试试水 很多玩Python3的都会遇到编码问题,如果直接去处理未知编码的网页,不是Python内部编码格式utf8会出现乱码,下面介绍一种将未知编码的字串转换为utf8来避免乱码的方法, ...

  10. [转]Eclipse插件开发之基础篇(6) SWT简介

    原文地址:http://www.cnblogs.com/liuzhuo/archive/2010/09/01/eclipse_plugin_1_3_1.html SWT(Standard Widget ...