Vuex详解
一、什么是Vuex
官网解释如下:
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。
那么什么是“状态管理模式”呢?
状态自管理应用包括以下几个部分:
- state:驱动应用的数据源;
- view:以声明方式将state映射到视图;
- action:响应在view上的用户输入导致的状态变化;
看下面这张表示“单向数据流”理念的简单示意图:

从上面的图中可以看出:整个系统的数据流是单向的:数据(即state)去驱动视图(view)的更新,用户在view上面进行一些操作触发action,通过action去更新state,而不是视图直接更新state。
二、运行机制
下面来看一张官网上面的Vuex运行机制图:

从图中可以看出,Vuex不在和组件强相关。运行机制:Vuex提供数据(state),来驱动视图(这里指的是Vue组件),视图通过Dispatch派发Action,在Action中可以进一步做一些异步的操作(例如通过ajax请求后端的接口数据),然后通过Commit提交给Mutations,由Mutations去最终更改state。那么为什么要经过Mutations呢?这是因为我们要在Vue调试工具(Devtools)中记录数据的变化,这样可以通过插件去进行进一步的调试。所以说Mutations中只能是纯同步的操作,如果是有异步操作,那么就需要在Actions中进行处理。如果说没有异步操作,那么可以直接由组件进行Commit操作Mutations。如下图所示:

三、创建项目
1、使用脚手架搭建Vue项目
在命令行里面输入如下命令即可创建一个Vue项目:
vue init webpack vuex-demo
如下图所示:

然后回车进行安装,选择默认配置即可,出现如下面所示的界面表示创建成功:

2、安装Vuex
新创建的项目里面默认不会安装Vuex,如果要使用Vuex,需要进行手动安装,输入下面的命令:
npm install vuex --save
如下图所示:

注:--save表示进行全局安装
3、启动项目
在第一步创建成功项目以后,最后会提示如何启动项目,如下面所示:

这两行命令表示先进入项目的根目录,然后输入npm run dev命令即可启动项目,如下图所示:

在浏览器窗口里面输入:http://localhost:8080进行浏览:

4、配置使用Vuex
4.1、创建store文件夹
在src目录下面创建一个store文件夹,该文件夹用来存放所有与状态管理有关的文件,然后创建一个index.js文件,Store对象写在index.js文件里面,代码如下:
// 引入Vue
import Vue from 'vue'
// 引入Vuex
import Vuex from 'vuex'
// 添加全局引用
Vue.use(Vuex);
// 创建store对象
const store=new Vuex.Store({ })
// 导出创建的store对象
export default store;
4.2、配置全局使用store对象
在main.js里面配置全局使用store对象:
// 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'
// 引入index.js文件
import store from './store/index' Vue.config.productionTip = false /* eslint-disable no-new */
new Vue({
el: '#app',
router,
store,// 配置全局使用store对象
components: { App },
template: '<App/>'
})
到此为止,一个Vuex项目创建完成,并且安装了Vuex,下面就可以使用该项目演示如何使用Vuex进行状态管理了。
四、Vuex核心概念
1、state
在index.js文件里面添加state,代码如下:
// 引入Vue
import Vue from 'vue'
// 引入Vuex
import Vuex from 'vuex'
// 添加全局引用
Vue.use(Vuex); // 创建state
const state={
// 定义num属性并赋初始值为1
num:1
} // 创建store对象
const store=new Vuex.Store({
// 添加state导出
state
}) // 导出创建的store对象
export default store;
在test.vue中使用展示初始值:
<template>
<p>初始值:{{this.$store.state.num}}</p>
</template> <script>
export default {
name:'test'
}
</script>
页面效果:

注:还可以通过计算属性获取num的值:
<template>
<div>
<p>初始值:{{this.$store.state.num}}</p>
<p>通过计算属性获取初始值:{{count}}</p>
</div>
</template> <script>
export default {
name:'test',
// 计算属性
computed:{
count(){
return this.$store.state.num;
}
}
}
</script>
效果如图所示:

2、mutations
在上面使用了state可以获取到属性的值,那么如何修改state中属性的值呢?这时候就要用到mutations了。官网解释如下:
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数。还是以上面的为例子。
修改index.js文件,添加mutations:
// 引入Vue
import Vue from 'vue'
// 引入Vuex
import Vuex from 'vuex'
// 添加全局引用
Vue.use(Vuex); // 创建state
const state={
// 定义num属性并赋初始值为1
num:1
} // 改变状态,通过commit
var mutations={
// state作为第一个参数
ChangeState(state){
// 自增1
state.num++;
}
} // 创建store对象
const store=new Vuex.Store({
// 添加state
state,
// 导出mutations
mutations
}) // 导出创建的store对象
export default store;
修改test.vue文件:
<template>
<div>
<p>初始值:{{this.$store.state.num}}</p>
<p>通过计算属性获取初始值:{{count}}</p>
<button @click="$store.commit('ChangeState')">改变属性值</button>
</div>
</template> <script>
export default {
name:'test',
// 计算属性
computed:{
count(){
return this.$store.state.num;
}
}
}
</script>
效果:

注:改变状态还可以传递参数进行修改,看下面的例子:
修改index.js文件如下:
// 引入Vue
import Vue from 'vue'
// 引入Vuex
import Vuex from 'vuex'
// 添加全局引用
Vue.use(Vuex); // 创建state
const state={
// 定义num属性并赋初始值为1
num:1
} // 改变状态,通过commit
var mutations={
// state作为第一个参数
ChangeState(state){
// 自增1
state.num++;
},
// state作为第一个参数,para作为第二个参数
ChangeStateWithPara(state,para){
// 自增1
state.num += para;
}
} // 创建store对象
const store=new Vuex.Store({
// 添加state
state,
// 导出mutations
mutations
}) // 导出创建的store对象
export default store;
test.vue修改如下:
<template>
<div>
<p>初始值:{{this.$store.state.num}}</p>
<p>通过计算属性获取初始值:{{count}}</p>
<button @click="$store.commit('ChangeState')">改变属性值</button>
<button @click="$store.commit('ChangeStateWithPara',5)">传递参数改变属性值</button>
</div>
</template> <script>
export default {
name:'test',
// 计算属性
computed:{
count(){
return this.$store.state.num;
}
}
}
</script>
效果:

3、Getter
有时候我们需要从store中的state中派生出一些状态,例如根据num的值返回基数或者偶数。如果有多个组件需要用到这个状态,那么我们就需要在每个组件里面都定义重复的一个函数,或者是定义成一个公共的函数,然后在多个组件里面导入,这两种方式无论采用哪种都不是很理想的。这时候我们就需要用到getter了。官网解释如下:
Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。同样,Getter接受state作为第一个参数。看下面的例子:
修改index.js文件如下:
// 引入Vue
import Vue from 'vue'
// 引入Vuex
import Vuex from 'vuex'
// 添加全局引用
Vue.use(Vuex); // 创建state
const state={
// 定义num属性并赋初始值为1
num:1
} // 改变状态,通过commit
var mutations={
// state作为第一个参数
ChangeState(state){
// 自增1
state.num++;
},
// state作为第一个参数,para作为第二个参数
ChangeStateWithPara(state,para){
// 自增1
state.num += para;
}
} // Getter,相当于store里面的计算属性
var getters={
IsOddOrEven(state){
return state.num % 2==0?'偶数':'奇数'
}
}
// 创建store对象
const store=new Vuex.Store({
// 添加state
state,
// 导出mutations
mutations,
// 导出getter
getters
}) // 导出创建的store对象
export default store;
那么该如何访问getters呢?可以通过下面的几种方式进行访问:
3.1、通过属性进行访问
修改test.vue如下:
<template>
<div>
<p>初始值:{{this.$store.state.num}}</p>
<p>通过计算属性获取初始值:{{count}}</p>
<button @click="$store.commit('ChangeState')">改变属性值</button>
<button @click="$store.commit('ChangeStateWithPara',5)">传递参数改变属性值</button>
<!--通过属性访问getters-->
<p>通过属性访问getters:{{$store.getters.IsOddOrEven}}</p>
</div>
</template> <script>
export default {
name:'test',
// 计算属性
computed:{
count(){
return this.$store.state.num;
}
}
}
</script>
效果:

3.2、通过辅助函数进行访问
vuex中提供了mapGetters辅助函数,mapGetters辅助函数仅仅是将store中的getter映射到局部计算属性:
修改text.vue如下:
<template>
<div>
<p>初始值:{{this.$store.state.num}}</p>
<p>通过计算属性获取初始值:{{count}}</p>
<button @click="$store.commit('ChangeState')">改变属性值</button>
<button @click="$store.commit('ChangeStateWithPara',5)">传递参数改变属性值</button>
<!--通过属性访问getters-->
<p>通过属性访问getters:{{$store.getters.IsOddOrEven}}</p>
<!--通过辅助函数访问getters-->
<p>通过辅助函数访问getters:{{IsOddOrEven}}</p>
</div>
</template> <script>
// 导入辅助函数
import {mapGetters} from 'vuex'
export default {
name:'test',
// 计算属性
computed:{
count(){
return this.$store.state.num;
},
// 使用对象展开运算符将 getter 混入 computed 对象中,数组里面是在getters里面定义的方法名称,如果有多个
// 则在数组里面添加多个即可
...mapGetters(['IsOddOrEven'])
}
}
</script>
效果:

可以看出:通过属性访问和通过辅助函数访问实现的效果是一样的。
4、Action
Vuex官网对Action的解释如下:
Action类似于Mutation,两者的不同之处在于:
- Action提交的是Mutation,而不是直接变更状态。也就是说Action是用来管理Mutation的,执行顺序是先执行Action,然后通过Action来触发Mutation,最后在通过Mutation来变更状态。
- Action中可以包含异步操作,Mutation中只能包含同步操作。
看下面的例子:
修改index.js如下:
// 引入Vue
import Vue from 'vue'
// 引入Vuex
import Vuex from 'vuex'
// 添加全局引用
Vue.use(Vuex); // 创建state
const state={
// 定义num属性并赋初始值为1
num:1
} // 改变状态,通过commit
var mutations={
// state作为第一个参数
ChangeState(state){
// 自增1
state.num++;
},
// state作为第一个参数,para作为第二个参数
ChangeStateWithPara(state,para){
// 自增1
state.num += para;
}
} // Getter,相当于store里面的计算属性
var getters={
IsOddOrEven(state){
return state.num % 2==0?'偶数':'奇数'
}
} // 用来管理mutations
var actions={
ExecChangeState({commit}){
// 执行mutations里面定义的ChangeState方法
commit('ChangeState');
}
}
// 创建store对象
const store=new Vuex.Store({
// 添加state
state,
// 导出mutations
mutations,
// 导出getter
getters,
// 导出actions
actions
}) // 导出创建的store对象
export default store;
4.1、通过dispatch触发
修改test.vue如下:
<template>
<div>
<p>初始值:{{this.$store.state.num}}</p>
<p>通过计算属性获取初始值:{{count}}</p>
<button @click="$store.commit('ChangeState')">改变属性值</button>
<button @click="$store.commit('ChangeStateWithPara',5)">传递参数改变属性值</button>
<!--通过属性访问getters-->
<p>通过属性访问getters:{{$store.getters.IsOddOrEven}}</p>
<!--通过辅助函数访问getters-->
<p>通过辅助函数访问getters:{{IsOddOrEven}}</p>
<!--演示Action-->
<div>
<p>属性值:{{count}}</p>
<button @click="add">通过action改变属性值</button>
</div>
</div>
</template> <script>
// 导入辅助函数
import {mapGetters} from 'vuex'
export default {
name:'test',
// 计算属性
computed:{
count(){
return this.$store.state.num;
},
// 使用对象展开运算符将 getter 混入 computed 对象中,数组里面是在getters里面定义的方法名称,如果有多个
// 则在数组里面添加多个即可
...mapGetters(['IsOddOrEven'])
},
methods:{
add(){
// 通过dispatch触发actions里面的ExecChangeState
this.$store.dispatch('ExecChangeState');
}
}
}
</script>
效果:

下面看一下执行顺序:
分别在add()、ExecChangeState()、ChangeState()里面添加一句console.log()来查看执行顺序:
index.js修改如下:
// 引入Vue
import Vue from 'vue'
// 引入Vuex
import Vuex from 'vuex'
// 添加全局引用
Vue.use(Vuex); // 创建state
const state={
// 定义num属性并赋初始值为1
num:1
} // 改变状态,通过commit
var mutations={
// state作为第一个参数
ChangeState(state){
console.log("mutations");
// 自增1
state.num++;
},
// state作为第一个参数,para作为第二个参数
ChangeStateWithPara(state,para){
// 自增1
state.num += para;
}
} // Getter,相当于store里面的计算属性
var getters={
IsOddOrEven(state){
return state.num % 2==0?'偶数':'奇数'
}
} // 用来管理mutations
var actions={
ExecChangeState({commit}){
// 执行mutations里面定义的ChangeState方法
console.log("actions");
commit('ChangeState');
}
}
// 创建store对象
const store=new Vuex.Store({
// 添加state
state,
// 导出mutations
mutations,
// 导出getter
getters,
// 导出actions
actions
}) // 导出创建的store对象
export default store;
test.vue修改如下:
<template>
<div>
<p>初始值:{{this.$store.state.num}}</p>
<p>通过计算属性获取初始值:{{count}}</p>
<button @click="$store.commit('ChangeState')">改变属性值</button>
<button @click="$store.commit('ChangeStateWithPara',5)">传递参数改变属性值</button>
<!--通过属性访问getters-->
<p>通过属性访问getters:{{$store.getters.IsOddOrEven}}</p>
<!--通过辅助函数访问getters-->
<p>通过辅助函数访问getters:{{IsOddOrEven}}</p>
<!--演示Action-->
<div>
<p>属性值:{{count}}</p>
<button @click="add">通过action改变属性值</button>
</div>
</div>
</template> <script>
// 导入辅助函数
import {mapGetters} from 'vuex'
export default {
name:'test',
// 计算属性
computed:{
count(){
return this.$store.state.num;
},
// 使用对象展开运算符将 getter 混入 computed 对象中,数组里面是在getters里面定义的方法名称,如果有多个
// 则在数组里面添加多个即可
...mapGetters(['IsOddOrEven'])
},
methods:{
add(){
// 通过dispatch触发actions里面的ExecChangeState
console.log("触发add()");
this.$store.dispatch('ExecChangeState');
}
}
}
</script>
效果:

从上图可以看出执行顺序是:先执行组件中的方法,然后执行actions,最后在执行mutations,最终通过mutations更新状态。
4.2、通过辅助函数触发
除了使用dispatch()触发actions以外,还可以使用辅助函数mapActions,辅助函数mapActions将组件中的methods映射为store.dispatch。修改test.vue如下:
<template>
<div>
<p>初始值:{{this.$store.state.num}}</p>
<p>通过计算属性获取初始值:{{count}}</p>
<button @click="$store.commit('ChangeState')">改变属性值</button>
<button @click="$store.commit('ChangeStateWithPara',5)">传递参数改变属性值</button>
<!--通过属性访问getters-->
<p>通过属性访问getters:{{$store.getters.IsOddOrEven}}</p>
<!--通过辅助函数访问getters-->
<p>通过辅助函数访问getters:{{IsOddOrEven}}</p>
<!--演示Action-->
<div>
<p>属性值:{{count}}</p>
<button @click="add">通过action改变属性值</button>
</div>
<!--通过辅助函数触发actions-->
<div>
<p>属性值:{{count}}</p>
<button @click="ExecChangeState">通过辅助函数改变属性值</button>
</div>
</div>
</template> <script>
// 导入辅助函数
import {mapGetters, mapActions} from 'vuex'
export default {
name:'test',
// 计算属性
computed:{
count(){
return this.$store.state.num;
},
// 使用对象展开运算符将 getter 混入 computed 对象中,数组里面是在getters里面定义的方法名称,如果有多个
// 则在数组里面添加多个即可
...mapGetters(['IsOddOrEven'])
},
methods:{
add(){
// 通过dispatch触发actions里面的ExecChangeState
console.log("触发add()");
this.$store.dispatch('ExecChangeState');
},
// 辅助函数 mapActions辅助函数将组件中的methods映射为store.dispatch
// 这里表示将'this.ExecChangeState'映射为'this.$store.dispatch('ExecChangeState')'
...mapActions(['ExecChangeState'])
}
}
</script>
效果:

到了这里,可能有人会问:通过actions的方式进行管理mutations比直接使用mutations更复杂了,为什么还要这么做呢?实际上并非如此,mutations只能执行同步方法,Action就不受此限制,我们可以在actions内部执行异步方法,看下面的例子:
修改index.js,添加异步方法,代码如下:
// 引入Vue
import Vue from 'vue'
// 引入Vuex
import Vuex from 'vuex'
// 添加全局引用
Vue.use(Vuex); // 创建state
const state={
// 定义num属性并赋初始值为1
num:1
} // 改变状态,通过commit
var mutations={
// state作为第一个参数
ChangeState(state){
console.log("mutations");
// 自增1
state.num++;
},
// state作为第一个参数,para作为第二个参数
ChangeStateWithPara(state,para){
// 自增1
state.num += para;
}
} // Getter,相当于store里面的计算属性
var getters={
IsOddOrEven(state){
return state.num % 2==0?'偶数':'奇数'
}
} // 用来管理mutations
var actions={
ExecChangeState({commit}){
// 执行mutations里面定义的ChangeState方法
console.log("actions");
commit('ChangeState');
},
// 执行异步方法:点击按钮5秒之后再改变属性的值
ExecChangeStateAsync({commit}){
setTimeout(() => {
commit('ChangeState')
}, 5000);
}
}
// 创建store对象
const store=new Vuex.Store({
// 添加state
state,
// 导出mutations
mutations,
// 导出getter
getters,
// 导出actions
actions
}) // 导出创建的store对象
export default store;
修改test.vue文件:
<template>
<div>
<p>初始值:{{this.$store.state.num}}</p>
<p>通过计算属性获取初始值:{{count}}</p>
<button @click="$store.commit('ChangeState')">改变属性值</button>
<button @click="$store.commit('ChangeStateWithPara',5)">传递参数改变属性值</button>
<!--通过属性访问getters-->
<p>通过属性访问getters:{{$store.getters.IsOddOrEven}}</p>
<!--通过辅助函数访问getters-->
<p>通过辅助函数访问getters:{{IsOddOrEven}}</p>
<!--演示Action-->
<div>
<p>属性值:{{count}}</p>
<button @click="add">通过action改变属性值</button>
</div>
<!--通过辅助函数触发actions-->
<div>
<p>属性值:{{count}}</p>
<button @click="ExecChangeState">通过辅助函数改变属性值</button>
</div>
<!--执行异步actions-->
<div>
<p>属性值:{{count}}</p>
<button @click="ExecChangeStateAsync">通过异步方法改变属性值</button>
</div>
</div>
</template> <script>
// 导入辅助函数
import {mapGetters, mapActions} from 'vuex'
export default {
name:'test',
// 计算属性
computed:{
count(){
return this.$store.state.num;
},
// 使用对象展开运算符将 getter 混入 computed 对象中,数组里面是在getters里面定义的方法名称,如果有多个
// 则在数组里面添加多个即可
...mapGetters(['IsOddOrEven'])
},
methods:{
add(){
// 通过dispatch触发actions里面的ExecChangeState
console.log("触发add()");
this.$store.dispatch('ExecChangeState');
},
// 辅助函数 mapActions辅助函数将组件中的methods映射为store.dispatch
// 这里表示将'this.ExecChangeState'映射为'this.$store.dispatch('ExecChangeState')'
// 这里表示将'this.ExecChangeStateAsync'映射为'this.$store.dispatch('ExecChangeStateAsync')'
...mapActions(['ExecChangeState','ExecChangeStateAsync'])
}
}
</script>
效果:

5、Module
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store对象就有可能变得相当臃肿。为了解决上面的问题,Vuex允许我们将store分割成模块(Module)。每个模块都有自己的state、mutation、action、getter。
五、总结
通过上面的基本讲解,了解了Vuex的一些基本用法,Vuex在进行状态管理方面很方便,但并不是说Vue项目中就一定要使用Vuex,在Vuex中也可以不使用Vuex。下面总结一下Vuex中的核心概念和底层原理
1、核心概念
- State:this.$store.state.xxx 取值
- Getter:this.$store.getters.xxx 取值
- Mutation:this.$store.commit('xxx') 赋值改变状态,只能调用同步方法
- Action:this.$store.dispatch('xxx') 赋值,不能直接更改状态,最后还是要通过commit更改状态,可以操作异步方法。
- Module:模块
2、底层原理
- State:提供一个响应式数据;
- Getter:借助Vue的计算属性computed来实现缓存;
- Mutation:更改State状态;
- Action:触发mutation方法;
- Module:Vue.set动态添加state到响应式数据中;
Vuex详解的更多相关文章
- vue:vuex详解
一.什么是Vuex? https://vuex.vuejs.org/zh-cn 官方说法:Vuex 是一个专为 Vue.js应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相 ...
- Vuex详解笔记2
关于 state 每个vuex 应用只有一个 store 实例,所以使用起来不会太复杂,对于定位错误状态和操作会很方便. 简单用法:在vuex 的计算属性中返回vuex 的状态 最基本的使用方式,通过 ...
- 九. Vuex详解
1. 理解Vuex 1.1 Vuex功能 官方解释 Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用 集中式存储 管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方 ...
- Vuex详解笔记1
vuex 是什么Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化. 什么是状态?状态这里泛指 ...
- 【转】VueJS中学习使用Vuex详解
转自:https://segmentfault.com/a/1190000015782272 在SPA单页面组件的开发中 Vue的vuex和React的Redux 都统称为同一状态管理,个人的理解 ...
- Vue.js中学习使用Vuex详解
在SPA单页面组件的开发中 Vue的vuex和React的Redux 都统称为同一状态管理,个人的理解是全局状态管理更合适:简单的理解就是你在state中定义了一个数据之后,你可以在所在项目中的任何一 ...
- vuex详解vue简单使用
vue概念:vuex 是 Vue 配套的 公共数据管理工具,它可以把一些共享的数据,保存到 vuex 中,方便 整个程序中的任何组件直接获取或修改我们的公共数据: 配置vuex的步骤: 1.运行cnp ...
- VueJS中学习使用Vuex详解
转载自:https://segmentfault.com/a/1190000015782272,做了部分修改(这里建议不要用所谓的getters,一来多次一举,二来模块化时会产生很不协调的用法) 在S ...
- 详解vuex结合localstorage动态监听storage的变化
这篇文章主要介绍了详解vuex结合localstorage动态监听storage的变化,小编觉得挺不错的,现在分享给大家,也给大家做个参考.一起跟随小编过来看看吧 需求:不同组件间共用同一数据,当一个 ...
随机推荐
- BZOJ.5290.[AHOI/HNOI2018]道路(树形DP)
BZOJ LOJ 洛谷 老年退役选手,都写不出普及提高DP= = 在儿子那统计贡献,不是在父亲那统计啊!!!(这样的话不写这个提高DP写记忆化都能过= =) 然后就令\(f[x][a][b]\)表示在 ...
- Scrapy基础(十三)————ItemLoader的简单使用
ItemLoader的简单使用:目的是解决在爬虫文件中代码结构杂乱,无序,可读性差的缺点 经过之前的基础,我们可以爬取一些不用登录,没有Ajax的,等等其他的简单的爬虫回顾我们的代码,是不是有点冗长, ...
- c# Array、ArrayList、List
1.Array:在内存中连续存储.索引速度快.赋值,修改元素简单. 不足:(1)插入数据麻烦 (2)声明时必须指定长度 2.ArrayList:解决了Array的不足 不足:(1)类型不安全 (2)存 ...
- BZOJ4223 : Tourists
将位置划分成$O(m)$段区间,每段最早被阻挡的时间可以用堆维护. 那么每段区间对询问的贡献独立,扫描线处理即可. 时间复杂度$O(m\log m)$. #include<cstdio> ...
- Expedition [POJ2431] [贪心]
题目大意: 有n个加油站,每个加油站的加油的油量有限,距离终点都有一个距离. 一个卡车的油箱无限,每走一个单元要消耗一单元的油,问卡车到达终点的最少加多少次油. 分析: 我们希望的是走到没油的时候就尽 ...
- 【转】java日志组件介绍(common-logging,log4j,slf4j,logback )
common-logging common-logging是apache提供的一个通用的日志接口.用户可以自由选择第三方的日志组件作为具体实现,像log4j,或者jdk自带的logging, comm ...
- 大神们都在用的两个国外的免费离线下载:Rain& LoadBT
大神们都在用的两个国外的免费离线下载:Rain& LoadBT 最近QQ离线和迅雷离线也都挂了,115还死贵,所以分享两个国外免费的网站.希望可以为大家提供一些帮助,同时也借此机会同大家相互交 ...
- SpringCloud无废话入门01:最简SpringCloud应用
1.创建Parent Parent很简单,创建一个空的maven项目,pom如下: <?xml version="1.0" encoding="UTF-8" ...
- Android: Android Studio签名打包的两种方式(zz)
注:给我们自己开发的app签名,就代表着我自己的版权,以后要进行升级,也必须要使用相同的签名才行.签名就代表着自己的身份(即keystore),多个app可以使用同一个签名. 如果不知道签名是啥意思, ...
- Jetpack 架构组件 LiveData ViewModel MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...