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