• vue中引入mintui、vux重构简单的APP项目


      最近在学习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:HBuilderSpacevue-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;
             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.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.11

    总结:

    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

  • 相关阅读:
    设计模式笔记4(工厂模式)
    设计模式笔记4(工厂模式)
    以前写的东东,放在这里个索引吧
    sicily 1001. Black Magic
    沙漠之旅
    hdu 1395(2^x mod n = 1)
    hdu 2161(Primes)
    sicily 8058. Matrix
    十进制转换为二进制
    硬币水题II
  • 原文地址:https://www.cnblogs.com/qlqwjy/p/11954661.html
Copyright © 2020-2023  润新知