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

原文地址:https://www.cnblogs.com/qlqwjy/p/11938755.html