$data
Vue 实例观察的数据对象。Vue 实例代理了对其 data 对象属性的访问。
console.log(this.text === this.$data.text); //true
$props
当前组件接收到的 props 对象。Vue 实例代理了对其 props 对象属性的访问,在子组件上使用
$el
Vue 实例使用的根 DOM 元素。在子组件上就是子组件的根DOM元素
$options
用于当前 Vue 实例的初始化选项。需要在选项中包含自定义属性时会有用处,直接修改$options.data的值不会更改数据,也不会触发视图渲染
$parent
父实例,如果当前实例有的话。
$root
当前组件树的根 Vue 实例。如果当前实例没有父实例,此实例将会是其自己。
const app = new Vue({})
this.$root === this.$root.$children[0].$root // true
this.$root === app //true
$children
当前实例的直接子组件。**需要注意 c h i l d r e n 并 不 保 证 顺 序 , 也 不 是 响 应 式 的 。 ∗ ∗ 如 果 你 发 现 自 己 正 在 尝 试 使 用 ‘ children 并不保证顺序,也不是响应式的。**如果你发现自己正在尝试使用 ` children并不保证顺序,也不是响应式的。∗∗如果你发现自己正在尝试使用‘children来进行数据绑定,考虑使用一个数组配合
v-for` 来生成子组件,并且使用 Array 作为真正的来源。
$slots
用来访问被插槽分发的内容。每个具名插槽 有其相应的属性 (例如:slot="foo"
中的内容将会在 vm.$slots.foo
中被找到)。default
属性包括了所有没有被包含在具名插槽中的节点。
在使用渲染函数书写一个组件时,访问 vm.$slots
最有帮助。
$scopedSlots
用来访问作用域插槽。对于包括 默认 slot
在内的每一个插槽,该对象都包含一个返回相应 VNode 的函数。
vm.$scopedSlots
在使用渲染函数开发一个组件时特别有用。
$refs
一个对象,持有注册过 ref特性的所有 DOM 元素和组件实例。
$isServer
当前 Vue 实例是否运行于服务器。用于服务端渲染
$attrs
包含了父作用域中不作为 prop 被识别 (且获取) 的特性绑定 (class
和 style
除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (class
和 style
除外),并且可以通过 v-bind="$attrs"
传入内部组件——在创建高级别的组件时非常有用。
$listeners
包含了父作用域中的 (不含 .native
修饰器的) v-on
事件监听器。它可以通过 v-on="$listeners"
传入内部组件——在创建更高层次的组件时非常有用。
$watch( expOrFn, callback, [options] )
观察 Vue 实例变化的一个表达式或计算属性函数。回调函数得到的参数为新值和旧值
$on( event, callback )
监听当前实例上的自定义事件。事件可以由vm.$emit
触发。回调函数会接收所有传入事件触发函数的额外参数。
$emit( eventName, […args] )
触发当前实例上的事件。附加参数都会传给监听器回调。
$once( event, callback )
监听一个自定义事件,但是只触发一次,在第一次触发之后移除监听器。
$forceUpdate()
不建议使用,频度控制不好容易造成内存溢出
迫使 Vue 实例重新渲染。注意它仅仅影响实例本身和插入插槽内容的子组件,而不是所有子组件。
如果更改在data中未声明的值,则不会触发视图更新,可以通过这个方法强制渲染,也可以通过$set避免这种情况
$off( [event, callback] )
移除自定义事件监听器。
$set( target, key, value )
Vue.set的别名
向响应式对象中添加一个属性,并确保这个新属性同样是响应式的,且触发视图更新。它必须用于向响应式对象上添加新属性,因为 Vue 无法探测普通的新增属性 (比如 this.myObject.newProperty = 'hi'
)
注意对象不能是 Vue 实例,或者 Vue 实例的根数据对象。
$delete( target, key, value)
Vue.delete的别名
删除对象的属性。如果对象是响应式的,确保删除能触发更新视图。这个方法主要用于避开 Vue 不能检测到属性被删除的限制,但是你应该很少会使用它。
$nextTick([callback])
Vue的渲染是异步的
将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。它跟全局方法 Vue.nextTick
一样,不同的是回调的 this
自动绑定到调用它的实例上。
vue可以访问绑定在this上的变量,无法访问定义在实例外的全局变量
computed
计算属性将被混入到 Vue 实例中。所有 getter 和 setter 的 this 上下文自动地绑定为 Vue 实例。
计算属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算。注意,如果某个依赖 (比如非响应式属性) 在该实例范畴之外,则计算属性是不会被更新的。
如果不指定set,那么默认提供的函数将被用作属性的getter函数
var vm = new Vue({
data: { a: 1 },
computed: {
// 仅读取
aDouble: function () {
return this.a * 2
},
// 读取和设置
aPlus: {
get: function () {
return this.a + 1
},
set: function (v) {
this.a = v - 1
}
}
}
})
vm.aPlus // => 2
vm.aPlus = 3
vm.a // => 2
vm.aDouble // => 4
watch
观察 Vue 实例变化的一个表达式或计算属性函数。回调函数得到的参数为新值和旧值。表达式只接受监督的键路径。对于更复杂的表达式,用一个函数取代。
watch: {
a: function (val, oldVal) {
console.log( val, oldVal)
}
}
选项:deep
为了发现对象内部值的变化,可以在选项参数中指定 deep: true
。注意监听数组的变动不需要这么做。
当更改对象内部值时,vue的watch如果设置在整个对象上,那么将不会监听到变化,这时可以指定deep:true
,但是这么做性能开销较大,因为每次对象中的任意一个值变化都会触发监听,可以在watch中直接监听内部值而不是整个对象
watch:{
'obj.a':{
get:function(){
//do something
}
}
}
选项:immediate
在选项参数中指定 immediate: true
将立即以表达式的当前值触发回调
只有在vue第一次触发数据更新后,监听函数才会执行,制定了immediate
为true
后,会在页面mouted后直接触发监听函数
v-show
根据表达式之真假值,切换元素的 display
CSS 属性。
v-if
根据表达式的值的真假条件渲染元素。在切换时元素及它的数据绑定 / 组件被销毁并重建。如果元素是 ,将提出它的内容作为条件块。
v-else
v-else-if
限制:前一兄弟元素必须有 v-if
或 v-else-if
。
v-for
基于源数据多次渲染元素或模板块。此指令之值,必须使用特定语法 alias in expression
,为当前遍历的元素提供别名
v-for="(item, index) in items" //item:元素,index:索引
如果遍历Object
v-for="(value, key, index) in object" //value:键值,key:键名,index:索引
key
当 Vue.js 用 v-for
正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。
<li v-for="(item,index)in items" :key="item.id">
</li>
v-on
修饰符:
.stop
- 调用 event.stopPropagation()
。.prevent
- 调用 event.preventDefault()
。.capture
- 添加事件侦听器时使用 capture 模式。.self
- 只当事件是从侦听器绑定的元素本身触发时才触发回调。.{keyCode | keyAlias}
- 只当事件是从特定键触发时才触发回调。.native
- 监听组件根元素的原生事件。.once
- 只触发一次回调。.left
- (2.2.0) 只当点击鼠标左键时触发。.right
- (2.2.0) 只当点击鼠标右键时触发。.middle
- (2.2.0) 只当点击鼠标中键时触发。.passive
- (2.3.0) 以 { passive: true }
模式添加侦听器如果使用内联语句,语句可以访问一个 $event
属性:v-on:click="handle('ok', $event)"
<form @submit.prevent>form>
v-bind
动态地绑定一个或多个特性
v-model
在表单控件或者组件上创建双向绑定
修饰符:
.lazy
- 取代 input
监听 change
事件.number
-输入字符串转为有效的数字.trim
输入首尾空格过滤可以用于
components
<input type="radio" value="one" v-model="choose"/>
<input type="radio" value="two" v-model="choose"/>
data(){
return{
choose:''
}
}
v-once
只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。也不会进行虚拟DOM的对比,这可以用于优化更新性能。
v-pre
跳过这个元素和它的子元素的编译过程。可以用来显示原始 Mustache 标签。跳过大量没有指令的节点会加快编译。
<h2 v-pre>{{default}}h2>
html
{{default}}
v-text
<span v-text="msg"></span>
<!-- 和下面的一样 -->
<span>{{msg}}</span>
v-html
内容按普通 HTML 插入 - 不会作为 Vue 模板进行编译
易导致XSS攻击,不建议使用
Vue.component( id, [definition] )
为了使每个重复生命的组件有独立的数据,在组件中定义data要使用return一个对象的形式定义
data(){
return {
//do something
}
}
props
props: ['size', 'myMessage']
props: {
// 检测类型
height: Number,
// 检测类型 + 其他验证
age: {
type: Number,
//不传递属性值时的默认值,一般与required不同时使用
default: 0,
//规定属性为必须传递的
required: true,
//自定义的验证,如果不通过vue会在控制台报告错误
validator: function (value) {
return value >= 0
}
}
传递数据需要通过v-bind
的形式传递,否则默认传递String
类型
//传递Boolean
<com :size="true" />
//传递String
<com size="true" />
如果需要在子组件上更改父组件的数据时,可以通过$emit
的形式触发事件
const com = {
template: `
THIS IS COM COMPONENT
`,
methods: {
sonchange() {
this.$emit('change')
}
}
}
const app = new Vue({
data() {
return {
text: 0
}
},
components: {
com
},
template: `
{{text}}
`,
methods: {
handlechange() {
this.text += 1;
}
}
}).$mount('#root')
使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象。
data
选项是特例,需要注意 - 在 Vue.extend()
中它必须是函数
// 创建构造器
var Profile = Vue.extend({
template: '{{firstName}}
',
data: function () {
return {
firstName: 'Walter'
}
}
})
// 创建 Profile 实例,并挂载到一个元素上。
new Profile().$mount('#root')
也可以创建一个组件的子类,子类拥有对父类的属性和方法的访问权限,如果子类声明了父类中已经声明过的数据,那么子类将会覆盖父类
如果父类定义了必须传递的参数,也就是required:true
时,直接传递props
父组件将不会接收到数据,可以使用propsData
传递数据,一般用于测试
const ComVue = Vue.extend('com');
new Comvue({
propsData:{
text:'111'
}
}).$mount('#root')
组件的扩展
const com = {
extends:comvue,
data(){
return{
}
}
}
parent
const com = {
parent:comvue,
methods:{
log(){
console.log(this.$parent.$options.name)
}
}
}
节制地使用 $parent
和 $children
- 它们的主要目的是作为访问组件的应急方法。更推荐用 props 和 events 实现父子组件通信
与extends
不同,parent
只会在子组件和父组件之间建立一层联系,可以通过$parent
读写父组件的数据
const com = {
template: `
`,
methods: {
handleinput(e) {
this.$emit('input', e.target.value)
}
}
}
new Vue({
components: {
com
},
data() {
return {
value: 0
}
},
template: `
{{value}}
`
}).$mount('#root')
slot
<div class="container">
<header>
header>
<main>
main>
<footer>
footer>
div>
对于这样的情况,
元素有一个特殊的特性:name
。这个特性可以用来定义额外的插槽:
<div class="container">
<header>
<slot name="header">slot>
header>
<main>
<slot>slot>
main>
<footer>
<slot name="footer">slot>
footer>
div>
在向具名插槽提供内容的时候,我们可以在一个父组件的 元素上使用
slot
特性:
<base-layout>
<template slot="header">
<h1>Here might be a page titleh1>
template>
<p>A paragraph for the main content.p>
<p>And another one.p>
<template slot="footer">
<p>Here's some contact infop>
template>
base-layout>
如果想要在实例的插槽中使用子组件中定义的数据,可以通过slot-scope
const com = {
template:`
`
}
new Vue({
data(){
return{
value:'222'
}
}
template:`
{{props.value}}+{{value}} //111 222
`
}).$mount('#root')
provide/inject
provide
和 inject
主要为高阶插件/组件库提供用例。并不推荐直接用于应用程序代码中。
在子组件上使用父组件,或者祖先组件上的数据
new Vue({
data(){
return{
value:0
}
},
provide(){
reutrn{
value:this.value
}
},
})
const com = {
components:{
childcom
},
template:` `
}
const childcom = {
template:``,
inject:['value'],
mouted(){
console.log(this.value); //0
}
}
provide
和 inject
绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。
如果需要javascript的完全编程的能力,可以用render
函数
Vue Render Document
new Vue({
// template: `
// {{value}}
// `
render(createElement) {
return createElement(
'comp-one', {
ref: 'comp'
}, [
createElement('span', {
ref: 'span'
}, this.value)
]
)
}
})
routes
接收一个路由配置的数组,类似这样
routes: [{
path: '/',
redirect: '/home'
},
{
path: '/home',
name: 'home',
component: Home
},
{
path: '/about',
name: 'about',
component: () =>
import ('./views/About.vue')
}
]
mode
接收一个字符串,用于配置路由的模式,简单来说就是hash
会在url和路由之间加入#
,不利于seo
。abstract
路由的切换不会反映在url上
hash
: 使用 URL hash 值来作路由。支持所有浏览器,包括不支持 HTML5 History Api 的浏览器。history
: 依赖 HTML5 History API 和服务器配置。查看 HTML5 History 模式。abstract
: 支持所有 JavaScript 运行环境,如 Node.js 服务器端。如果发现没有浏览器的 API,路由会自动强制进入这个模式。base
接受一个字符串,配置应用的基路径。例如,如果整个单页应用服务在 /app/
下,然后 base
就应该设为 "/app/"
。
linkActiveClass
全局配置
的默认“激活 class 类名”。只要URL路径中包含路由链接,都会添加这个类,也就是路径配置为/
的router-link
会一直存在这个类
linkExactActiveClass
全局配置
精确激活的默认的 class。
scrollBehavior
当切换到新路由时,想要页面滚到顶部,或者是保持原先的滚动位置
scrollBehavior
方法接收 to
和 from
路由对象。第三个参数 savedPosition
当且仅当 popstate
导航 (通过浏览器的 前进/后退 按钮触发) 时才可用。
to
表示跳转到哪个路由页面
form
表示从哪个路由页面跳转来
这个方法返回滚动位置的对象信息
scrollBehavior (to, from, savedPosition) {
if (savedPosition) {
return savedPosition
} else {
return { x: 0, y: 0 }
}
}
parseQuery / stringifyQuery
提供自定义查询字符串的解析/反解析函数。覆盖默认行为。
?
连接的数据叫做Query
fallback
当浏览器不支持 history.pushState
控制路由是否应该回退到 hash
模式。默认值为 true
路由配置项
name
命名路由,通过一个名称来标识一个路由显得更方便一些
routes:[
{
path:'/home',
name:'hame',
component:Home
}
]
<router-link :to="{name:'home'}">Home</router-link>
meta
用于配置路由一些额外的自定义信息
routes:[
{
path:'/home',
name:'hame',
component:Home,
meta:{
title:'this is home'
}
}
]
children
用于配置嵌套路由,在路由页面新增自路由,这个子路由会在路由页面的router-view
中显示
routes:[
{
path:'/home',
name:'hame',
component:Home,
children:{
path:'/app',
component:app
}
}
]
路由传参
routes:[
{
path:'/home:id',
component:Home,
}
]
//通过全局的$route访问
mouted(){
console.log(this.$route.params)
}
而且,参数一旦指定,必须传递,否则vue将无法匹配到路由页面
$route
还有一个叫做query
的对象,它包含了URL?
后连接的键值对
props
解耦
当设置了props
,就可以不需要使用$route
,直接作为props
传递到组件内,在子组件上直接指定props
{
path:'/app:id',
props:true,
}
{
path:'/app:id',
props:{
id:456
},
}
{
path:'/app:id',
props:()=>({id:route.query.b})
}
具名路由
如果页面中存在多个router-view
,可以通过设置名字来区别显示不同的组件
<router-view />
<router-view name="app"/>
routes:[
{
path:'/home',
components:{
default:home,
app:app
}
}
]
router.beforeEach((to, from, next) => {
// ...
next();
})
每个守卫方法接收三个参数:
next
方法的调用参数。
from
路由对应的地址。next
传递任意位置对象,且允许设置诸如 replace: true
、name: 'home'
之类的选项以及任何用在 router-link
的 to
prop 或 router.push中的选项。next
的参数是一个 Error
实例,则导航会被终止且该错误会被传递给 router.onError()注册过的回调。next()一定要被调用,否则钩子将不会被resolved
next也可以传递一个对象
next({
path:'/app',
replace:''
})
设置了replace后路由页面就会替换当前的路由页面,也就是使用浏览器的back会返回到上一个的上一个路由页面
router.beforeResolve((to, from, next) => {
// ...
next();
})
在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用
router.afterEach((to, from) => {
// ...
})
后置守卫不接收next()
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
beforeRouteEnter
beforeRouteUpdate
(2.2 新增)beforeRouteLeave
const Foo = {
template: `...`,
beforeRouteEnter (to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
},
beforeRouteUpdate (to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
},
beforeRouteLeave (to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
}
}
beforeEach
beforeEnter
beforeRouteEnter
beforeResolve
afterEach
beforeRouteLeave
beforeRouteUpdate会在路由的传参变化时触发,这时如果组件是复用的,那么生命周期钩子将不会被再次触发,此时需要监听beforeRouteUpdate
beforeEach
守卫。beforeRouteUpdate
守卫 (2.2+)。beforeEnter
。beforeRouteEnter
。beforeResolve
守卫 (2.5+)。afterEach
钩子。beforeRouteEnter
守卫中传给 next
的回调函数。这种形式会使用按需加载,也就是只加载当前路由的组件,提高首屏加载速度
{
path: '/about',
name: 'about',
component: () =>import ('./views/About.vue')
},
export default new Vuex.Store({
state: {
count: 0
},
mutations: {
updateCount(state, num) {
state.count = num
}
},
actions: {
}
})
state
接收一个对象,存储全局的数据
this.$store.state.count
mutations
接收一个对象,用于存放一些改变数据的方法,他接受两个参数,第一个是所要调用的方法名,第二个被vue称为载荷(payload),也就是一些额外的数据
this.$store.commit("updateCount",i)
mutations
只接收两个参数,如果需要传递多个多个值,第二个参数为一个对象
mutations:{
updateCount(state,{num,num1}){
}
}
getters
如果需要对数据进行过滤处理,可以在getters
中定义,getters
接收state作为第一个参数,mutations
和getters
的区别在于,mutations
是对store中状态的改变操作,而getters
更类似于vue中的computed
export default new Vuex.Store({
getters:{
changestate:(state)=>{
return //do something
}
}
})
this.$store.getters.changestate
actions
Action 类似于 mutation,不同在于:
this.$store.dispatch("updateCountSync", {
num: 10,
time: 2000
});
actions: {
updateCountSync(store, data) {
setTimeout(() => {
store.commit('updateCount', data.num)
}, data.time);
}
}
当一个组件需要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余。
import {
mapState,
mapGetters
} from 'vuex'
当映射的计算属性的名称与 state 的子节点名称相同时,可以简单的传递一个数组
<template>
<div>
{{count}}
</div>
</template>
<script>
export default{
computed:{
...mapState(['count'])
}
}
</script>
如果需要给传递进来的数据设置一个别名,可以传递一个对象
<template>
<div>
{{counter}}
</div>
</template>
<script>
export default{
computed:{
...mapState({
counter:'count'
})
}
}
</script>
还可以接收一个参数,用于对数据的处理
<template>
<div>
{{counter}}
</div>
</template>
<script>
export default{
computed:{
...mapState({
counter:(state)=>state.count++;
})
}
}
</script>
mapGetters与mapState的用法相同,这两种方法都是求值,所以放在computed中,mapActions和mapMutations是对数据的操作,需要放在methods中methods
mutations: {
updateCount(state,num) {
state.count = num
},
changeString(state, {
firstname,
lastname
}) {
state.name = `${firstname}-${lastname}`
}
},
actions: {
updateCountSync(store, data) {
setTimeout(() => {
store.commit('updateCount', data.num)}, data.time);}
}
mounted(){
this.updateCountSync({
num:50,
time:2000
})
this.updateCount(100);
}
methods:{
...mapActions(['updateCountSync']),
...mapMutations(['updateCount'])
}
const store = new Vuex.Store({
// ...
strict: true
})
在严格模式下,无论何时发生了状态变更且不是由 mutation 函数引起的,将会抛出错误。这能保证所有的状态变更都能被调试工具跟踪到。
不可以在生产环境中启用严格模式
const store = new Vuex.Store({
// ...
strict: process.env.NODE_ENV !== 'production'
})
Module
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割
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 的状态
namespaced
默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的——这样使得多个模块能够对同一 mutation 或 action 作出响应。
如果希望你的模块具有更高的封装度和复用性,你可以通过添加 namespaced: true
的方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名
modules:{
account:{
namespaced:true,
state:{
},
actions:{
changeString(store,state){
}
}
}
}
methods:{
...mapAction(['account/changeString'])
}
computed:{
this['account/changeString']('123')
}
如果希望在模块中访问全局的getters
和actions
,rootState
都将作为第三个参数被传入。
const moduleA = {
// ...
getters: {
sumWithRootCount (state, getters, rootState) {
return state.count + rootState.count
}
}
}
const moduleA = {
// ...
actions: {
incrementIfOddOnRootSum ({ state, commit, rootState }) {
if ((state.count + rootState.count) % 2 === 1) {
commit('increment')
}
}
}
}
如果希望在一个模块中访问另一个模块的内容,也可以通过rootState
进行操作
在模块内部调用全局mutations
//模块内访问全局mutations
const a = {
namespaced:true,
actions:{
add({state,commit,rootState}){
commit('updateState',{num:123},{root:true})
}
}
}
//一个模块访问另一个模块的mutations
const a = {
namespaced:true,
actions:{
add({state,commit,rootState}){
commit('a/updateState',{num:123},{root:true})
}
}
}
store.registerModule('com', {
state:{
a:1
}
})
computed:{
...mapState({
text:state=>state.com.a
})
}
//卸载模块
unregisterModule
使用 webpack 的 Hot Module Replacement API,Vuex 支持在开发过程中热重载 mutation、module、action 和 getter。你也可以在 Browserify 中使用 browserify-hmr 插件。
对于 mutation 和模块,你需要使用 store.hotUpdate()
方法:
// store.js
import Vue from 'vue'
import Vuex from 'vuex'
import mutations from './mutations'
import moduleA from './modules/a'
Vue.use(Vuex)
const state = { ... }
const store = new Vuex.Store({
state,
mutations,
modules: {
a: moduleA
}
})
if (module.hot) {
// 使 action 和 mutation 成为可热重载模块
module.hot.accept(['./mutations', './modules/a'], () => {
// 获取更新后的模块
// 因为 babel 6 的模块编译格式问题,这里需要加上 `.default`
const newMutations = require('./mutations').default
const newModuleA = require('./modules/a').default
// 加载新模块
store.hotUpdate({
mutations: newMutations,
modules: {
a: newModuleA
}
})
})
}
watch
store.watch((state) => state.count, (count) => {
console.log(`state has changed:${count}`);
})
响应式地侦听第一个函数参数的返回值,当值改变时调用回调函数,也就是第二个参数。fn
接收 store 的 state 作为第一个参数,其 getter 作为第二个参数。最后接收一个可选的对象参数表示 Vue 的 vm.$watch
方法的参数。
要停止侦听,调用此方法返回的函数即可停止侦听。
subscribe
订阅 store 的 mutation。handler
会在每个 mutation 完成后调用,接收 mutation 和经过 mutation 后的状态作为参数
store.subscribe((mutation, state) => {
console.log(mutation.type);
console.log(mutation.payload);
})
当每次mutations
被调用时触发,返回两个参数,第一个参数是一个对象,包含mutation
的名字,和传递的参数,第二个参数是经过mutation
的```state``
subscribeAction
store.subscribeAction((action, state) => {
console.log(action.type)
console.log(action.payload)
})
订阅 store 的 action。handler
会在每个 action 分发的时候调用并接收 action 描述和当前的 store 的 state 这两个参数,与上一个订阅用法相同