vue.js的小结

vuejs 李宜发
文章标签: vue.js的小结

vue.js的总结

从初识Vue.js—>vue.js的基础知识—>Vue.js 的组件—>Vue Router(路由)构建单页程序—>使用脚手架搭建单页程序—>Ajax vue-axios—>vuex状态管理

1.初识Vue.js

为什么用Vue.js?

Vue.js是一个强大的数据处理框架,能够很好的提升前端的开发效率

在国内很多企业都用vue.js开发前端项目,需求量非常大。

Vue.js的文档非常详细,生态也非常丰富,要找到的资料也非常多、全,容易学习。遇到的问题也很容易在网上查到。

2.vue.js的基础知识

Vue.js 使用了基于 HTML 的模板语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据。

3.Vue.js 的组件

基本概念

组件是一个可复用的Vue实例,需要挂载到Vue的实例

组件除了el选项外,同样包括有data、computed、watch、methods 以及生命周期钩子等。

4.Vue Router(路由)构建单页程序

Vue Router是什么?

是Vue.js的核心组件,由Vue.js官方维护的路由管理器

通过路由器可以构建用户体验较高的单页应用程序

5.使用脚手架搭建单页程序

为什么使用脚手架

为了使用更先进的技术例如 es5或是es6。都需要借助功能才能够在现有的浏览器运行

需要使用很多工具,例如webpack、babel做编译等工具,配置起来非常繁琐

vue.js 官方为了减轻这些繁琐的配置,将vue.js环境需要的配置配好,方便vue.js项目的开发

脚手架:是一种基于node.js的工具,作用是开发中用到的工具、环境都配置好了。不用在为这些复杂的配置花时间,专注业务开发就好了。

6.Ajax vue-axios官方文档

https://www.npmjs.com/package/axios
使用的步骤

vue-axios是官方推荐的插件

安装文件  npm install --save axios vue-axios

引入文件

import Vue from 'vue'

import axios from 'axios'

import VueAxios from 'vue-axios'

Vue.use(VueAxios, axios)

使用的基本格式

//全局使用

Vue.axios.get(api).then((response) => {

  console.log(response.data)

})

//组件内使用

this.axios.get(api).then((response) => {

  console.log(response.data)

})

//组件内使用$http

this.$http.get(api).then((response) => {

  console.log(response.data)

})

7.vuex状态管理

7.1.vuex概述

vuex是什么?是状态管理模式,用于组件于组件之间的通信

应用场景:大型的单页应用程序

7.2.安装环境

引入文件方式(初学用)

引入脚本
<script src="/path/to/vue.js"></script>
<script src="/path/to/vuex.js"></script>
vuex.js地址:
https://unpkg.com/vuex

npm方式

npm install vuex --save
 
main.js
import Vue from 'vue'
import Vuex from 'vuex' 
Vue.use(Vuex)

7.3.基本案例

<!DOCTYPE html>
<html lang="en">
 
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>数组的操作</title>
    <script src="../js/vue.js"></script>
    <script src="../js/vuex.js"></script>
  </head>
 
  <body>
    <div id="app">
       {{count}} <button @click="increament">计数</button>
    </div>
    <script>
       //定义存储的仓库
       var store = new Vuex.Store({
         state: { //状态管理的数据,类似data
           count: 0,
         },
         mutations: { //对数据改变的操作
           increament(state) { //定义方法,参数一传递state对象
             state.count++;
           }
         },
 
       });
       var vm = new Vue({
         el: "#app",
         store, //状态管理对象
         computed: { //计算属性
           count() {
             return this.$store.state.count;
           }
         },
         methods: {
           increament() {
             //提交状态管理
             this.$store.commit("increament");
           }
         },
       });
    </script>
  </body> 
</html>
 
注意:默认可以直接修改state的数据,如果不允许可以做如下设置
strict: true
下面的赋值方式,将会抛出异常
this.$store.state.count++;



 

7. 4.State 状态数据作用:用来存储共享的数据,类似data数据也是响应式的

如何定义

var store = new Vuex.Store({
    strict: true,
    state: {//状态管理的数据,类似data
        count: 0,
    },  
});

如何使用

  基本的使用方式

在组件上的使用
this.$store.state.count

  mapState 辅助函数

 var mapState = Vuex.mapState;
 
在计算属性上„使用
方式1 数组(最简洁)
 computed: mapState(["count"]) 
方式2 自定义别名:
  computed: mapState({count2:"count"})   
方式3 箭头函数
  computed: mapState({count2:state=>state.count})  
方式4: 普通函数
  computed: mapState({
      getCount(state){
          return state.count+this.count; 
          // this指向组件对象,不能使用箭头函数,箭头函数this==undefined
      }
  })  

  定义mapState 与组件的属性

    computed: mapState(["count"])  一个mapState返回的对象占用了整个computed,如果想定义其它的计算属性怎么办?

    使用对象展开符... 将mapState函数返回的对象的属性,向外面的对象展开,这是es6的语法

var obj={name:"小智",age:20}
var stu={address:'深圳市',...obj}
stu;//{address: "深圳市", name: "小智", age: 20}
 
计算属§的代码如下:
computed: {
  //本地计算属性
  localComputed () { /* ... */ },
  // 使用对象展开运算符将此对象混入到外部对象中
  ...mapState({
    // ...
  })
}

7.5.Getter 作用:增强对state数据处理,例如过滤,计算。类似计算属性,具有缓存作用。

定义getter

const store = new Vuex.Store({
  state: {
    todos: [
      { id: 1, text: '...', done: true },
      { id: 2, text: '...', done: false }
    ]
  },
  getters: {
    doneTodos: state => {
      return state.todos.filter(todo => todo.done)
    }
  }
})

如何使用

  基本的使用方式

this.$store.getters.doneTodos

  通过方法访问

让 getter 返回一个函数,来实现给 getter 传参
getters: {
  // ...
  getTodoById: (state) => (id) => {
    return state.todos.find(todo => todo.id === id)
  }
}
 
使用
  this.$store.getters.getTodoById(1)

  mapGetters 辅助函数

mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性:
 
var mapGetters = Vuex.mapGetters;
 
  computed: {
  // 使用对象展开运算符将 getter 混入 computed 对象中
    ...mapGetters([
      'doneTodosCount',
      'anotherGetter',
      // ...
    ])
  } 

7.6.Mutation作用:更改 Vuex 的 store 中的状态的唯一方法,类似自定义事件。

如何定义

const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    //参数1就是state对象
    increment (state) {
      // 变更状态
      state.count++
    }
  }
})

如何使用

store.commit('increment')

 提交载荷(额外参数)

// ...
mutations: {
  increment (state, n) {
    state.count += n
  }
}
 
store.commit('increment', 10)
 
参数作为对象
// ...
mutations: {
  increment (state, payload) {
    state.count += payload.amount
  }
}
store.commit('increment', {
  amount: 10
}) 

  对象风格的提交方式

store.commit({
  type: 'increment',
  amount: 10
})

  使用常量替代 Mutation 事件类型

// mutation-types.js
export const SOME_MUTATION = 'SOME_MUTATION'
 
// store.js
import Vuex from 'vuex'
import { SOME_MUTATION } from './mutation-types'
 
const store = new Vuex.Store({
  state: { ... },
  mutations: {
    // 我们可以使用 ES2015 风格的计算属性命名功能来使用一个常量作为函数名
    [SOME_MUTATION] (state) {
      // mutate state
    }
  }
})

  mapMutations 辅助函数

var mapMutations  = Vuex.mapMutations ;
 
export default {
  // ...
  methods: {
    ...mapMutations([
      'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')` 
      // `mapMutations` 也支持载荷:
      'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)`
    ]),
    ...mapMutations({
      add: 'increment' // 将 `this.add()` 映射为 `this.$store.commit('increment')`
    })
  }
}

注意:Mutation 必须是同步函数,便于跟踪状态信息

7.7.Action:作用:类似于 mutation,用于异步处理状态的更改。

如何定义

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment (context) {
      context.commit('increment') //改变状态唯€途径就是mutation
    }
  }
})
 
context对象
context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。
简化代码
actions: {
  increment ({ commit }) {//解构对象
    commit('increment')
  }
}

分发 Action

store.dispatch('increment')
 
支持同样的载÷方式和对象方式进行分发: 
// 以载荷形式分发
store.dispatch('incrementAsync', {
  amount: 10
})
 
// 以对象形式分发
store.dispatch({
  type: 'incrementAsync',
  amount: 10
})

mapActions 辅助函数

export default {
  // ...
  methods: {
    ...mapActions([
      'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')` 
      // `mapActions` 也支持载荷:
      'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
    ]),
    ...mapActions({
      add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
    })
  }
}

结合Promise

actions: {
  actionA ({ commit }) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        commit('someMutation')
        resolve()
      }, 1000)
    })
  }
}
使用
store.dispatch('actionA').then(() => {
  // ...
})

7.8.Module:作用:可以根据功能划分多个模块来管理状态,避免臃肿。

如何定义

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 的状态

如何使用Module的state

const moduleA = {
  state: { age:18 }, 
}
 
const store = new Vuex.Store({
  modules: {
    moduleA, 
  }
})
 
需要使用模×名来调用
  store.state.moduleA.age // -> moduleA 的状态
使用mapState
var mapState = Vuex.mapState;
var vm = new Vue({
    el: "#app",
    store,//状态管理对象         
    computed: mapState({
        age: state => state.moduleA.age,//箭头函数
        age2(state) {//普通方法
            return state.moduleA.age;
        },
    })
});

如何使用Module的getter

var moduleA = {
    state: {
        age: 18
    },
    getters:{
        getAge(state){
                return state.age+2;   
        }
    }
}
//定义模块  
var moduleA = {
    state: {
        age: 18
    },
    getters: {
        getAge(state) {
            return state.age + 2;
        }
    }
}
var moduleB = { 
    getters: {
        getAge(state) {
            return 0;
        }
    }
}
--------------------------------------------------
var store = new Vuex.Store({
    modules: {
        moduleA,
        moduleB
    }
});

如何使用Module的mutation和action

//定义模块  
var moduleA = {
    mutations: {
        addAge() {
            console.log("mduleA mutations addAge")
        }
    },
    actions: {
        addAge() {
            console.log("mduleA actions addAge")
        }
    }
}
//定É存储的仓库
var store = new Vuex.Store({
    modules: {
        moduleA,
    }
});
var vm = new Vue({
    el: "#app",
    store,//状态管理对象          
    created() {
        this.$store.commit("addAge");
        this.$store.dispatch("addAge");
    }
});
问题:这里依然不用指定模块,像以前那样使用,如果模块B也有相同的会做什么样的处理?
var moduleB = {
    mutations: {
        addAge() {
            console.log("mduleB mutations addAge")
        }
    },
    actions: {
        addAge() {
            console.log("mduleB actions addAge")
        }
    }
}
 
var store = new Vuex.Store({
    modules: {
        moduleA,
        moduleB,
    }
});
 
 created() {
    this.$store.commit("addAge");
    this.$store.dispatch("addAge");
}
输出结果
 
说明:可以定义相同的action和mutation,并且都会执行。

问题:多个模块有相同的action或mutation如何执行其中的一个了?

使用命名空间å划分,也就是像state那样指定模块的名称å使用
 
namespaced的使用
var moduleA = {
    namespaced: true,
    state:{
        age:18
    },
    getters: {
        getAge() {
            console.log("mduleA getters getAge")
            return 20;
        }
    },
    mutations: {
        addAge() {
            console.log("mduleA mutations addAge")
        }
    },
    actions: {
        addAge() {
            console.log("mduleA actions addAge")
        }
    }
}
具体的使用方式
created() {
    this.$store.state.moduleA.age; //
    this.$store.getters['moduleA/getAge'];//使用模块名称
    this.$store.commit("moduleA/addAge");//使用模块名称
    this.$store.dispatch("moduleA/addAge");//使用模块名称
}
 
使用mapxxx的方式
computed: {
    //state的映射
    ...mapState({ age: state => state.moduleA.age }),// 使用 this.age
    //getter的映射1
    ...mapGetters({ getAge: 'moduleA/getAge' }),//使用 this.getAge
    //getter的映射2
    //...mapGetters(['moduleA/getAge']),//使用 this['moduleA/getAge']
},
methods: {
    //mutation映射
    ...mapMutations({ add: 'moduleA/addAge' }),//使用 this.add()
        //这种方式不推荐使用
    ...mapMutations(['moduleA/addAge']), //使用 this["moduleA/addAge"]()
    //action 映射
    ...mapActions({ aAddAge: 'moduleA/addAge' }),//使用 this.aAddAge()
    //这种方式不推荐使用
    //...mapActions(['moduleA/addAge']),//使用 this["moduleA/addAge"]()
},
 

7.9.项目结构

7.9.1Vuex 项目结构的一些基本规则

7.9.1.1应用层级的状态应该集中到单个 store 对象中

7.9.1.2提交 mutation 是更改状态的唯一方法,并且这个过程是同步的

7.9.1.3异步逻辑都应该封装到 action 里面。

7.9.2项目结构图

图像.bmp

还能输出{{restrictNumber}}个字符  
  • {{reply.author}}

    {{CommonUtil.formateDate(reply.ac_CommentDate).shortTime}}
  • 回复了{{Comments.author}} :