9月8日vue学习笔记

标签

vue

前端

html

css

javascript

发布时间:

本文字数:1,199 字 阅读完需:约 6 分钟

vuex状态管理

当写vue项目时,当涉及到频繁的组件之间的数据通讯、一个组件需要多次派发事件时,我们的代码就会变得复杂、冗余、难以维护。

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。我们可以把一些共享的数据保存至vuex中,方便各个组件修改或获取公共状态。

vuex使用单一状态树state对象来作为“唯一数据源”,专门用于存放数据。
• 在组件中访问state下的数据,通过this.$store.state来访问
• 不能通过this.$store.state进行赋值,会造成显示与存储不统一。
• 一般建议当需要访问state的属性时,通过计算属性访问,避免对数据赋值。

mutations组件:更新state中数据的核心机制,只有正确提交mutations,才能 保证state中的数据在个组件中渲染与存储一致。

安装

package.json

  "dependencies": {
    "axios": "^0.27.2",
    "vue": "^2.5.2",
    "vue-router": "^3.0.1",
    "vuex": "^3.6.2" //添加依赖
  },

运行 npm install,即可

使用

新建store/index.js文件

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
    state:{
        loginName: ''
    },
    mutations:{
        // 给state中的loginName赋值
        loginName(state, param){
            state.loginName = param
        }
    }
})

修改 index.js 文件

new Vue({
  el: '#app',
  router,
  store,
  components: { App },
  template: '<App/>'
})

vuex持久化工具

package.json

  "dependencies": {
    "axios": "^0.27.2",
    "vue": "^2.5.2",
    "vue-router": "^3.0.1",
    "vuex": "^3.6.2",
    "vuex-persistedstate": "^4.1.0"
  },

store/index.js

import Vue from 'vue'
import Vuex from 'vuex'
import createPersistedState from 'vuex-persistedstate'

Vue.use(Vuex)

export default new Vuex.Store({
    state:{
        loginName: ''
    },
    mutations:{
        loginName(state, param){
            state.loginName = param
        }
    },
    plugins:[createPersistedState()] //持久化存储插件
    
})

components/Login.vue

<template>
  <div>
 
    <div class="user">
    <div>账号:<input type="text" v-model="form.userId" ></div>
    <div>密码:<input type="password" v-model="form.password" ></div>
    <div><button @click="login">登录</button></div>
  </div>
  </div>
</template>

<script>

export default {
  name: "Login",
  data() {
    return {
      form:{
        userId:'',
        password: '',
      } //引入form对象进行双向绑定,提交请求时只需提交form即可

    }
  },
  methods:{
    login(){
      this.$axios({
        url:'api/user/login',
        method:'post',
        data: this.form //提交form对象为json格式
      }).then((result) => {
        this.$store.commit('loginName', result.data.object.userName);
        this.$router.push('Home');
      }).catch((err) => {
        console.info(err)
      });

    }
  }
}
</script>

<style scoped>
/*scoped只在当前组件起作用,不影响父组件*/
</style>

components/Home.vue

<template>
  <div>
    主页组件,{{userName}}
    <br>
    {{this.$route.query.userName2}}
    {{this.$store.state.loginName}}
    <br>
    <router-view></router-view>
    
  </div>
</template>

<script>
export default {
  name: "Home",
  data() {
    return {
      userName:''
    }
  },
  created() {
    this.userName = this.$route.params.userName
    this.$router.push('User')
  },
}
</script>

<style scoped>

</style>

效果,登录成功后将username存储,并显示在home主页中。持久化存储的作用在于刷新后存储的值还在。

使用computed :main.js

<template>
  <div>
    主页组件,{{userName}}
    <br>
    {{this.$route.query.userName2}}
    <!-- {{this.$store.state.loginName}} -->
    {{loginName}}
    <br>
    <router-view></router-view>
    
  </div>
</template>

<script>
export default {
  name: "Home",
  data() {
    return {
      userName:''
    }
  },
  computed:{
    loginName(){
      return this.$store.state.loginName;
    }
  },
  created() {
    this.userName = this.$route.params.userName
    this.$router.push('User')
  },
}
</script>

<style scoped>

</style>

ElementUI

安装使用

  1. 执行 npm i element-ui -S
  2. 修改 main.js
import Vue from 'vue';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import App from './App.vue';

Vue.use(ElementUI);

new Vue({
  el: '#app',
  render: h => h(App)
});

这种写法

{
    render:h=>h(App)
}

等价于

{
    render:h=>{
        return h(App);
    }
}

等价于

{
    render:function(h){
        return h(App);
    }
}

也就是

{
    render:function(creatElement){
        return creatElemnt(App);
    }
}

render:h=>h(App) 这是:

1、ES6的写法,表示Vue实例选项对象的render方法作为一个函数,接受传入的参数h函数,返回h(App)的函数调用结果

2、Vue在创建Vue实例时,通过调用render方法来渲染实例的DOM树

3、Vue在调用render方法时,会传入一个createElement函数作为参数,也就是这里的h的实参是createElement函数,然后createElement会以App为参数进行调用

或者 main.js

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import axios from 'axios'
import store from './store'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';

Vue.config.productionTip = false
//设置axios为Vue的属性$axios
Vue.prototype.$axios = axios 

Vue.use(ElementUI);

new Vue({
  el: '#app',
  router,
  store,
  components: { App },
  template: '<App/>'
})

官方网站:https://element.eleme.cn/#/zh-CN

实例

home.vue

<template>
  <div>
    <el-container>
      <el-header>{{loginName}}</el-header>
      <el-container>
        <el-aside width="240px">
          <el-menu
            default-active="User"
            class="el-menu-vertical-demo"
            background-color="#545c64"
            text-color="#fff"
            @select="menu"
            active-text-color="#ffd04b">
            <el-submenu index="1">
              <template slot="title">
                <i class="el-icon-s-tools"></i>
                <span>系统设置</span>
              </template>
              <el-menu-item-group>
                <el-menu-item index="Usersetting">用户设置</el-menu-item>
                <el-menu-item index="Role" >角色设置</el-menu-item>
              </el-menu-item-group>
            </el-submenu>
            <el-submenu index="2">
              <template slot="title">
                <i class="el-icon-s-check"></i>
                <span>业务办理</span>
              </template>
              <el-menu-item-group>
                <el-menu-item index="2-1">业务一</el-menu-item>
                <el-menu-item index="2-2">业务二</el-menu-item>
              </el-menu-item-group>
            </el-submenu>
          </el-menu>
        </el-aside>
        <el-main><router-view></router-view></el-main>
      </el-container>
    </el-container>
  </div>
</template>

<script>
export default {
  name: "Home",
  computed:{
    loginName() {
      return this.$store.state.loginName;
    }
  },
  methods: {
    menu(index){
      this.$router.push(index)
    }
  },
}
</script>

<style scoped>
.el-header{
  height: 5vh
}
.el-aside{
  height: 95vh;
  background-color: #545c64;
}
.el-main{
  height: 95vh
}
</style>

Usersetting.vue

<template>
  <div>
    <el-form :inline="true" :model="queryForm" class="demo-form-inline">
      <el-form-item label="账号">
        <el-input v-model="queryForm.userId" placeholder="账号"></el-input>
      </el-form-item>
      <el-form-item label="姓名">
        <el-input v-model="queryForm.userName" placeholder="姓名"></el-input>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="getList">查询</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<script>
export default {
  name: "UserSetting",
  created() {},
  data() {
    return {
      queryForm:{
        userId:'',
        userName:''
      },
    };
  },
  props: {},
  methods: {
    getList(){}
  },
};
</script>

<style scoped></style>

login.vue

<template>
  <div class="login">
  <el-input placeholder="输入账号" v-model="form.userId" clearable></el-input>
  <el-input placeholder="请输入密码" v-model="form.password" show-password></el-input>
  <el-button type="success" @click="login" :loading="loading" :disabled="disabled">登录</el-button><br>
  <el-button type="primary">注册</el-button>
  </div>
</template>

<script>
import md5 from '../../static/md5';

export default {
  name: "Login",
  data() {
    return {
      form: {
        userId: '',
        password: '',
      },
      loading: false,
      disabled: false,


    }
  },
  methods: {
    login() {
      this.loading = true;
      
      this.$axios({
        url: 'api/user/login',
        method: 'post',
        data: this.form
      }).then((result) => {
        // this.loading = false;
        // this.disabled = true;
        this.$message({
          message: '欢迎您'+result.data.object.userName+',登录成功',
          type: 'success'
        });
        this.$store.commit('loginName', result.data.object.userName);
        this.$router.push('Home');
      }).catch((err) => {
        // setTimeout(() => {
          this.loading = false;
        // }, 1000);
        // 

        this.$message.error(err);
      });

    }
  }
  // methods: {
  //   toHome() {
  //     this.$router.push({ name: 'Home', params: { userName: '李雷' } })
  //   }
  // },
}
</script>

<style scoped>
/*scoped只在当前组件起作用,不影响父组件*/

.login{
    width: 300px;
    margin: 10% auto;
    text-align: center;
  }
.el-input{
  margin: 10px;
}
.el-button{
  margin: 10px;
  width: 100%;
}
</style>

router/index.js

import Vue from 'vue'
import Router from 'vue-router'
import Login from '@/components/Login'
import Home from '@/components/Home'
import User from '@/components/sys/User'
import Role from '@/components/sys/Role'
import UserSetting from '@/components/sys/UserSetting'


Vue.use(Router)

export default new Router({
  // mode: ,
  routes: [
    {
      path:'/',
      redirect:'/Login'
    },
    {
      path:'/Login',
      name:'Login',
      component: Login
    },{
      path:'/Home',
      name:'Home',
      component: Home,
      children: [
        {
          path:'/User',
          name:'User',
          component: User
        },{
          path:'/Role',
          name:'Role',
          component: Role
        },{
          path:'/UserSetting',
          name:'UserSetting',
          component: UserSetting
        }
      ]
    }
  ]
})

基本思路:把子页面放在children路由中,借助 @select="menu",实现点击目录,右侧跳转子页面,具体参考以上代码