zoukankan      html  css  js  c++  java
  • vue-cli安装以及创建一个简单的项目(二)(vuex使用、发行一个简单的app)

    1.vuex的使用

      vuex是vue的状态管理中心,vuex来保存我们需要管理的状态值,值一旦被修改,所有引用该值的地方就会自动更新,常用于:

    1.多个视图依赖同一状态(l例:菜单导航)

    2.来自不同视图的行为需要变更同一状态(例如评论弹幕)

    上篇创建的vue项目目录结构:

      在上一节我们已经安装了vuex模块。查看store/index.js内容,如下:

    import Vue from 'vue';
    import Vuex from 'vuex';
    
    Vue.use(Vuex);
    
    export default new Vuex.Store({
      state: {
      },
      mutations: {
      },
      actions: {
      },
      modules: {
      },
    });

      上面引入Vue模块和Vuex模块,并将Vuex安装到Vue中。

    下面使用vuex。在Test路由中改变值,在about模块中接收,代码如下:

    (1)修改store/index.js

    import Vue from 'vue';
    import Vuex from 'vuex';
    
    Vue.use(Vuex);
    
    export default new Vuex.Store({
      state: {
        count: 0,
      },
      mutations: {
        increase() {
          this.state.count = this.state.count + 1;
        },
      },
      actions: {
      },
      modules: {
      },
    });

      定义一个状态count,mutations中是修改状态的唯一入口。

    (2)修改Test.vue

    <template>
      <div class="test">
          这是Test
          <button tybe="button" @click="addOne()">点击我</button>
      </div>
    </template>
    
    <script>
    import store from '@/store';
    
    export default {
      name: 'Test',
      store,
      methods: {
        addOne() {
          console.log('add');
          store.commit('increase');
        },
      },
    };
    </script>

      点击按钮的时候调用方法addOne()。addOne()中调用store.commit("increase") 提交该方法进行修改状态,相当于调用 Vuex.Store 实例的 increase() 方法。

    (3)修改About.vue接收状态count

    <template>
      <div class="about">
        <h1>This is an about page</h1>
        {{msg}}
      </div>
    </template>
    
    <script>
    import store from '@/store';
    
    export default {
      name: 'About',
      store,
      data() {
        return {
          msg: store.state.count,
        };
      },
    };
    </script>

    (4)测试:

    补充:关于vuex调用函数传递参数。比如我们传递一个username参数到vuex中,如:

    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: {
      },
    });

    调用方法如下:(登录成功之后跳转到首页并记录登录的用户)=如下面红色代码

        login() {
          this.isReg = false;
          var nameLocal = localStorage.getItem("name");
          var passwordLocal = localStorage.getItem("name");
          if (nameLocal == '' || passwordLocal == '') {
            alert("您还没注册!");
            return;
          }
    
          if (nameLocal === this.name || passwordLocal === this.password) {
            store.dispatch("setLoginUsernameFun", nameLocal);
            this.$router.push('/home')
            return;
          }
    
          alert("账号或者密码错误");
        },

    补充:vueX的五个核心属性

    (1)state:

    state即Vuex中的基本数据!
    state就是用来存放数据,若是对数据进行处理输出,比如数据要过滤,一般我们可以写到computed中。

    (2)getters(相当于State的计算属性) :

    基础用法:

    index.js

    const store = new Vuex.Store({
      state: {
        list: [1, 3, 5, 7, 9, 20, 30]
      },
      getters: {
        filteredList: state => {
          return state.list.filter(item => item > 5)
        },
        listCount: (state, getters) => {
          return getters.filteredList.length;
        }
      }
    })

    vue中:

    <template>
     
      <div>
        过滤后的列表:{{list}}
        <br>
        列表长度:{{listCount}}
      </div>
    </template>
     
    <script>
      export default {
        name: "index.vue",
        computed: {
          list() {
            return this.$store.getters.filteredList;
          },
          listCount() {
            return this.$store.getters.listCount;
          }
        }
      }
    </script>

    (3)mutation(提交更改数据的方法,同步!必须是同步函数) 

    使用vuex修改state时,有两种方式:
    1)可以直接使用 this.$store.state.变量 = xxx;
    2)this.$store.dispatch(actionType, payload)或者 this.$store.commit(commitType, payload)
    异同点:
    1)共同点: 能够修改state里的变量,并且是响应式的(能触发视图更新)
    2)不同点:
    若将vue创建 store 的时候传入 strict: true, 开启严格模式,那么任何修改state的操作,只要不经过mutation的函数,
    vue就会 throw error : [vuex] Do not mutate vuex store state outside mutation handlers。

    (4)action(像一个装饰器,包裹mutations,使之可以异步。) 

    action的功能和mutation是类似的,都是去变更store里的state,不过action和mutation有两点不同:
    1)action主要处理的是异步的操作,mutation必须同步执行,而action就不受这样的限制,也就是说action中我们既可以处理同步,也可以处理异步的操作
    2)action改变状态,最后是通过提交mutation。

      Action 通过 store.dispatch 方法触发。

    (5)modules ( 模块化Vuex):

      在Vue中State使用是单一状态树结构,应该的所有的状态都放在state里面,如果项目比较复杂,那state是一个很大的对象,store对象也将对变得非常大,难于管理。
      modules:可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理

    const moduleA = {
      state: { ... },
      mutations: { ... },
      actions: { ... },
      getters: { ... }
    }
    
    const moduleB = {
      state: { ... },
      mutations: { ... },
      actions: { ... }
    }
    
    const store = new Vuex.Store({
      modules: {
        a: moduleA,
        b: moduleB
      }
    })
    
    store.state.a // -> moduleA 的状态
    store.state.b // -> moduleB 的状态

    2. 打包vue项目并制作成app

      vue-cli3之后的打包与之前不一样,配置文件在vue.config.js中,并且这个文件需要自己创建置于与package.json同目录。关于其配置项可参考:

    如果想打包之后静态页面直接点击运行需要将路由改为hash路由:

    (1)修改router/index.js

    const router = new VueRouter({
      mode: 'hash',
      base: process.env.BASE_URL,
      routes,
    });

    (2)vue.config,js修改打包的默认路径:

    module.exports = {
      publicPath:  './',
      lintOnSave: false
    }

       如果将来我们将页面置于项目中,项目名称为exam,我们将publicPath修改为exam即可。默认是/,./是相对路径。

      lintOnSave: false 是关闭eslint验证(这个验证太烦了)

      接下来到项目根路径运行打包命令即可得到正常的html、css等文件。如下:

    E:HBuilderSpacevue-demo>npm run build
    
    > vue-demo@0.1.0 build E:HBuilderSpacevue-demo
    > vue-cli-service build
    
    
    -  Building for production...
    
     DONE  Compiled successfully in 51657ms
    
    
      File                                 Size               Gzipped
    
      distjschunk-vendors.ae7fcf93.js    125.21 KiB         43.38 KiB
      distjsapp.628ec198.js              7.19 KiB           2.75 KiB
      distjsabout.672d2588.js            1.32 KiB           0.59 KiB
      distcssabout.b0b00f5a.css          0.57 KiB           0.31 KiB
      distcssapp.59544d79.css            0.21 KiB           0.15 KiB

    打包后会生成dist目录,并且对文件都进行了压缩,如下:

     index.html内容如下:(原本是一行,这是我格式化后的。可以看到路径是相对路由)

    <!DOCTYPE html>
    <html lang=en>
    <head>
        <meta charset=utf-8>
        <meta http-equiv=X-UA-Compatible content="IE=edge">
        <meta name=viewport content="width=device-width,initial-scale=1">
        <link rel=icon href=favicon.ico>
        <title>vue-demo</title>
        <link href=css/about.b0b00f5a.css rel=prefetch>
        <link href=js/about.672d2588.js rel=prefetch>
        <link href=css/app.59544d79.css rel=preload as=style>
        <link href=js/app.628ec198.js rel=preload as=script>
        <link href=js/chunk-vendors.ae7fcf93.js rel=preload as=script>
        <link href=css/app.59544d79.css rel=stylesheet>
    </head>
    <body>
    <noscript><strong>We're sorry but vue-demo doesn't work properly without JavaScript enabled. Please enable it to
        continue.</strong></noscript>
    <div id=app></div>
    <script src=js/chunk-vendors.ae7fcf93.js></script>
    <script src=js/app.628ec198.js></script>
    </body>
    </html>

    2.制作一个简单的基于localStorage本地登录的小app

      用vue制作一个简单的基于本地登录的app,基于hash的路由。

    1.目录结构:

    2.附上主要代码:

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

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

    Main.js

    import Vue from 'vue';
    import App from './App.vue';
    import router from './router';
    import store from './store';
    
    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管理组件定义了一个属性与修改属性的方法

    vies/Login.vue

    <template>
      <div class="login">
        <form v-if="!isReg">
          <h1>欢迎来到XXX系统</h1>
          <br/>
          <br/>
          <div>用户名: <input type="text" v-model="name"/> </div>
          <br/>
          <div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;码: <input type="password" v-model="password"/> </div>
          <div class="rowBtn" @click="login()">登录</div>
          <div class="rowBtn regBtn" @click="reg()">注册</div>
        </form>
        <form v-else>
          <h1>注册</h1>
          <br/>
          <br/>
          <div>用户名: <input type="text" v-model="name"/> </div>
          <br/>
          <div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;码: <input type="password" v-model="password"/> </div>
          <br/>
          <div>确认密码: <input type="password" v-model="passwordRepeat"/> </div>
          <div class="rowBtn" @click="addUser()">注册</div>
          <div class="rowBtn regBtn" @click="cancel()">取消</div>
        </form>
    
      </div>
    </template>
    
    <script>
    import store from '@/store';
    
    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("name");
          if (nameLocal == '' || passwordLocal == '') {
            alert("您还没注册!");
            return;
          }
    
          if (nameLocal === this.name || passwordLocal === this.password) {
            store.dispatch("setLoginUsernameFun", nameLocal);
            this.$router.push('/home')
            return;
          }
    
          alert("账号或者密码错误");
        },
        reg() {
          this.isReg = true;
        },
        addUser() {
           if (this.name == '' || this.password == '') {
             alert("必填用户名密码!!!");
             return;
           }
    
          if (this.password !== this.passwordRepeat) {
            alert("两次密码不一致!!!");
            return;
          }
    
          localStorage.setItem("name", this.name);
          localStorage.setItem("password", this.password);
          this.name = '';
          this.password = '';
          alert("注册成功!");
          this.isReg = false;
        },
        cancel() {
          this.isReg = false;
        }
      },
    };
    </script>
    
    <style scoped lang="scss">
    .rowBtn{
      width: 100%;
      height: 40px;
      font-size: 20px;
      text-align: center;
      line-height: 40px;
      margin-top: 10px;
      background: #87CEEB;
    
      &.regBtn{
        background: #20B2AA;
      }
    }
    </style>

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

    views/Home.vue

    <template>
      <div class="home">
        <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>

    Contact.vue:

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

    3.效果

    (1)登录

      

    (2)登录之后主页面

      

    4.制作成app-利用hbuilder制作app

    (1)执行 npm run build 之后生成dist文件。

    (2)在hbuilder新建一项目将dist下文件考进去:W表示web项目,A表示APP项目

    (3)右键dist项目然后选择 转换成移动APP

    (4)然后发行为原生app即可。之前已经发行过一个mui的app。

      参考:https://www.cnblogs.com/qlqwjy/p/10428546.html

    (5)手机端效果如下:

    补充:项目中引入jquery

    1.安装jquery

    cnpm install jquery --save-dev

    2.vue.config.js头部声明

    const webpack = require("webpack")
    // vue.config.js
    module.exports = {
      configureWebpack: {
            plugins: [
                new webpack.ProvidePlugin({
                  jQuery: "jquery",
                  $: "jquery"
                })
              ]
      }
    }

    3.使用的地方引入即可:

    import $ from 'jquery'

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

  • 相关阅读:
    CentOS 7 配置hadoop(五) 配置sqoop(伪分布)
    CentOS 7 配置hadoop(四) 配置hive(伪分布)
    CentOS 7 配置hadoop(三) 配置hbase(伪分布)
    java高级之NIO
    字符编码与序列化
    java高级之IO流 -2
    java中的值传递和引用传递
    事务相关知识点
    mybatis中批量更新sql语句,trim、foreach标签,varchar定义理解
    java IO流之File类的使用
  • 原文地址:https://www.cnblogs.com/qlqwjy/p/11938755.html
Copyright © 2011-2022 走看看