Vue 绑定方式
v-model
v-model 是专门用于 input,select,textare 等表单控件的绑定。它可以渲染变量在 dom 上,同时控件的 value 改变时,对应变量也会做出改变。(在表单控件或者组件上创建双向绑定)。
<input type="text" v-model="name">
<textarea v-model="message" placeholder="add multiple lines"></textarea>
<input type="checkbox" id="checkbox" v-model="checked">
<input type="radio" id="one" value="One" v-model="picked">
<select v-model="selected">
<option disabled value> 请选择 </option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
v-bind
动态地绑定一个或多个特性,或一个组件 prop 到表达式。就是把属性变量化,class,style 等可以根据变量来改变。同时也是父组件往子组件传值的方法。
<img v-bind:src="imageSrc" :title="imageNum">
v-bind: 可以简写成:。例子中图片的地址和 title 都是来自于 vue 实例里的变量。
Vuex
vuex 是一个专门为 vue.js 应用程序开发的状态管理模式。
这个状态我们可以理解为在 data 中的属性,需要共享给其他组件使用的部分。
也就是说,是我们需要共享的 data,使用 vuex 进行统一集中式的管理。
vuex 周期的大概流程是,在 vue 实例中调用 store 下的 state 后,想要改变 state,要先通过 store.commit(有异步操作要先 dispath)来改变 state,从而在 vue 页面中渲染。
state
store 里的数据源库(一个全局的 data),可在全局调用 $store.state 访问。
每当 state 变化的时候, 都会重新求取计算属性,并且触发更新相关联的 DOM。
在 store 里
state:{name:"张三"}
vue 实例
<div> 用户名: {{$store.state.name}}</div>
引用 vuex 后,在项目任意 vue 实例里都可以访问到 state 的内容。
Getter
从 store 中的 state 中派生出一些状态。(可以认为是对数据获取之前的再次编译,store 的计算属性)。他并不会改变 state 本身。只有当它的依赖值发生了改变才会被重新计算。(类似于 vue 实例的 computed)
Getter 接受 state 作为其第一个参数, 可以访问 store 里的 state
getters: {
doneTodos: state => {return state.todos.filter(todo => todo.done)
}
}
第二个参数是 getters,可以访问到上下文的 getters。
getters: {doneTodosCount: (state, getters) => {return getters.doneTodos.length}
}
假如需要传参,可以通过方法访问
getters: {getTodoById: (state) => (id) => {return state.todos.find(todo => todo.id === id)
}
}
在 vue 实例中访问 getters
computed:{doneTodosCount () {return this.$store.getters.doneTodosCount}
}
mutation
mutation 是更改 Vuex 的 store 中的状态的唯一方法。需要用 store.commit()触发。
mutations: 第一个参数是 state,第二个参数是载荷(Payload)。即传参,在大多数情况下,载荷应该是一个对象。
非常重要的一点,mutation 内必须是同步函数。
mutations: {increment (state, payload) {state.count += payload.amount}
}
执行时 store.commit()第一个参数是 mutations 的名称(字符串), 第二个是载荷对象。
store.commit('increment', {amount: 10});
Action
Action 是专门处理 store 异步操作的。
Action 提交的是 mutation,而不是直接变更状态。
Action 通过 store.dispatch()触发。
actions 第一个参数是 context(上下文),第二个参数是载荷。
actions: {incrementAsync ({ commit}) {setTimeout(() => {commit('increment')
}, 1000)
}
}
vue 实例里执行 action。
store.dispatch('incrementAsync', {amount: 10})
Module
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
module 可以把 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter。
store.js
const moduleA = {state: { ...},
mutations: {...},
actions: {...},
getters: {...}
}
const moduleB = {state: { ...},
mutations: {...},
actions: {...}
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
在 vue 实例里访问时
$store.state.a // -> moduleA 的状态
$store.state.b // -> moduleB 的状态
这种写法下 state 会区分模块,但 mutation 和 action 的调用时,写法是一样的。
$store.commit(“set”);
$store.dispath(“set”);
命名空间
假如不同的模块里有出现相同名称的 mutations,就会出现问题。为了避免,可以使用命名空间。
在每个模块下添加 namespaced: true。即可实现命名空间。
const moduleA = {
namespaced: true,state: {...},
mutations: {...},
actions: {...},
getters: {...}
}
const moduleB = {
namespaced: true,state: {...},
mutations: {...},
actions: {...}
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
在 vue 实例中调用时改为
$store.commit(“a/set”);
$store.dispath(“b/set”);
vuex 和 data
vuex 是全局存在的,对于一些只在一个 vue 页面 (组件) 中用到的信息,可以只存在对于的页面 (组件) 的 data 中。store 中一般存放一些在多处会读取或者改写的信息,这样可以避免多层的父子传值。一般常见的存放在 store 里的有用户信息,标签信息等。这样可以在不同的地方操作标签。
例子:在一个项目中有一个右键弹出菜单的组件。组件需要传参,来决定传入内容。
store 里
{
state:{
rightMenuData: [{
name: '刷新此窗口',
key: 'refresh'
},
{
name: '关闭此窗口',
key: 'close'
}, {
name: '关闭全部窗口',
key: 'closeAll'
}]
}
}
vue 页面中
<right-menu
:menuData="rightMenuData"
:eventHandler="rightClickHandler"
v-on:handleSelect="handleRightSelect"
></right-menu>
列子中的菜单内容存在 store 里,在一个页面里调用了对应数据。可是实际上项目里只要一个页面需要用到这个数据。这种情况可以把数据只放到页面 data 里,避免 store 过于臃肿。
另一个例子:
vue 页面中
mounted() {let user = global.myLocalStorage.getItem("user");
if (user) {user = JSON.parse(user);
this.sysUserName = user.name || "";
this.sysUserAvatar = user.avatar || "agree.bee.png";
}
//... 省略部分
这里页面中用到一个用户信息,由于本地保存的关系,用户数据被存到 localstorage 里。然后项目在各处拿用户信息的时候会直接从 localstorage 里拿。这种情况,可以考虑,在页面打开时,只从 localstorage 拿一次数据,存在 store 里。在项目运行的过程中就可以直接在 store 里访问用户信息。
多个 store 运用
在一些大型应用中,有可能存在多个 store 的情况,来保持自身的 store 不受影响。
例子:A 实例下面有多个 vue 子页面 b,c,d。它们都需要有自己的 store。则在内部 Vue 实例中 new 一个 vuex.store,并存起来(不一定要存 $store,可以是其他变量)。
beforeCreate(){
this.$store = new Vuex.store({
stata,
mutations,
actions
})
}
此时 vue 实例 b,c,d 中
this.$store
返回的应该是自己的 store。
如果想要访问 A 页面原来的 store,可以用 $root, 访问根部 vue 实例,由于他的 this.$store 并没有被重写,所以指向的还是原来全局的 store。
this.$root.$store