1. Vuex状态树
对于每个大项目来说,使用状态树(store)和管理状态(state)十分有必要。这也就是为什么Nuxt.js内核实现了Vuex。
1.1 简单用法
nuxt中的vuex在使用方法上与vue上相似
1.1.1 定义一个store
- /store/index.js
export const state = () => ({
counter: 0
})
export const mutations = {
setIniteCount(state, parmas) {
state.counter = parmas
},
increment(state) {
state.counter ++
}
}
1.1.2 在页面中使用
<h3 @click="addOne">该用户拥有的水果种类有:{{counter}}</h3>
import {mapState} from 'vuex'
export default Vue.extend({
computed: {
...mapState(['counter'])
},
async asyncData(context) {
try {
let { data } = await myAxios.get('/fruits')
context.store.commit('setIniteCount', data.dataSource.length) // asyncData中使用context来访问store
return {
list: data.dataSource || []
}
}catch (err) {
console.log(err.message)
// alert(err.message)
}
},
methods: {
addOne() {
this.$store.commit('increment')
}
},
})
1.2 模块化
上述示例中,只创建了一个store/index.js文件,后续堆砌会变得非常的冗余,此时我们需要将功能提炼一下,将相同功能的相关状态和操作放在单独的文件中,便于维护和扩充以及定位问题。例如,我们需要创建一个todo事项的存储信息
1.2.1 定义状态及操作
- store/todo.js 定义待办项的列表信息、增加、删除、修改状态功能
// todos.js 将todo页面所涉及到的store内容封装在一个文件中
export const state = ({
list: []
})
export const mutations = {
add(state, text) {
state.list.push({
text,
done: false
})
},
remove(state, todo) {
state.list.splice(state.list.indexOf(todo), 1)
},
toggle(state, todo) {
todo.done = !todo.done
}
}
1.2.2 页面中使用
- 在页面中通过this.$store.state.模块名称.状态名称来访问store中存储的状态
- 在页面中通过this.$store.commit(‘模块名称/方法名称’, 参数)
- 通过mapState将状态信息提取出来
- 通过mapMutations将方法重命名可以在html结构中直接调用
<template>
<div>
<h1>以下是今天需要的工作事项:</h1>
<ul>
<li v-for="(item, index) in list" :key="`${item}${Math.random()}${index}`">
<input type="checkbox" :checked="item.done">{{item.done}}
<span>{{item.text}}</span>
<button @click.prevent="toggle(item)">切换当前状态</button>
<button @click.prevent="remove(item)">删除当前待办项</button>
</li>
</ul>
<input type="text" @keyup.enter="addTodo" placeholder="增加待办项">
</div>
</template>
<script>
import Vue from "vue";
import { mapMutations } from 'vuex'
export default Vue.extend({
computed: {
list() {
return this.$store.state.todos.list
}
},
methods: {
addTodo(e) {
this.$store.commit('todos/add', e.target.value)
e.target.value = ''
},
// 将vuex中的方法重命名可以在页面html结构上进行使用
...mapMutations({
toggle: 'todos/toggle',
remove: 'todos/remove'
})
},
})
</script>
1.3 在vuex中使用fetch
- fetch 方法会在渲染页面前被调用,作用是填充状态树 (store) 数据,与 asyncData 方法类似,不同的是它不会设置组件的数据。
- 在 Nuxt.js 中,fetch 方法是一个特别为服务器端渲染(SSR)和数据预取设计的特殊方法。它允许你在组件渲染之前从服务器获取数据,并且这些数据会作为组件的上下文数据(context data)可用,但不会被包含在客户端的 Vuex store 中(除非你显式地将数据添加到 Vuex store)。
1.3.1 新建模块,定义state、mutations、actions
- store/usefetch.js 定义usefetch模块,将使用fetch逻辑的放入一个文件中
import myAxios from "~/request";
export const state = ({
fruits: [{
fruitsname: 'useFetch'
}]
})
export const mutations = {
SET_FRUITS(state, fruits) {
state.fruits = fruits
}
}
export const actions = {
async fetchFruits({commit}) {
const res = await myAxios.get('http://127.0.0.1:8090/api/fruits')
const getFruits = res.data.dataSource || []
commit('SET_FRUITS',getFruits)
}
}
1.3.2 在页面中使用
在页面中类似于asyncData,也可以使用fetch的方法。
- fetch 方法仅在服务器端和客户端首次加载组件时调用。如果你需要响应用户交互来更新数据,你应该使用 Vuex 的 actions 和 mutations,并在组件的方法中调用它们。
- 使用 fetch 方法时,请注意它的执行时机和上下文。在 Nuxt 中,fetch 方法是服务器端渲染的一部分,因此它会在服务器和客户端的首次渲染时被调用。
<template>
<ul>
<h3>以下是新进水果:</h3>
<li v-for="(item,index) in fruits" :key="index">
{{ item.fruitsname }}
</li>
</ul>
</template>
<script>
import Vue from "vue";
export default Vue.extend({
computed: {
fruits() {
return this.$store.state.usefetch.fruits
}
},
async fetch({store}) {
// 调用非store/index.js 而是不同模块下定义的actions
await store.dispatch('usefetch/fetchFruits')
}
})
</script>
1.4 Vuex严格模式
默认情况下,在开发模式下启用严格模式,在生产模式下关闭模式。要在 dev 中禁用严格模式,请遵循以下示例。
export const strict = false
1.5 const a = ({}) 与 const a = {} 的区别
我们在vuex中定义的时候,定义state使用的是前面的写法,而定义mutations则是后面的写法,那么这两个写法到底有什么区别呢
-
在 JavaScript 中,const a = ({}) 和 const a = {} 之间的主要区别在于括号的使用,但在这个特定的上下文中,它们的行为实际上是相同的,并且都创建了一个新的空对象。然而,这种括号的使用通常是不必要的,并且可能会引起一些混淆。
-
const a = {}:
- 这行代码直接创建了一个空对象,并将其赋值给常量 a。
- 这是定义空对象或任何对象字面量的标准方式。
-
const a = ({}):
- 在这里,括号被用于包围对象字面量 {}。
- 在 JavaScript 中,括号通常用于分组表达式或函数调用的参数列表。然而,在这个特定的例子中,括号并不改变 {} 的含义或行为。它们仅仅是将对象字面量包围起来,但 {} 仍然被解释为一个对象字面量。
- 这种写法在某些情况下可能会引起混淆,特别是对于那些不熟悉 JavaScript 的人来说,他们可能会误以为这是某种特殊的语法或函数调用。
1.5.1 总结
-
在定义 Vuex 的 state、mutations、actions 或任何其他 JavaScript 对象时,应该避免使用不必要的括号。直接使用 const a = {} 来定义对象是最清晰、最标准的方式。如果你在使用括号,请确保你有充分的理由,并且这样做不会降低代码的可读性或引起误解。
-
在 Nuxt.js 和 Vuex 的上下文中,特别是在定义 store 的 state 和 mutations 时,你应该始终遵循标准的 JavaScript 对象字面量语法,即 const state = {} 和 const mutations = {}。
2. 命令
我们可以在package.json中的scripts上配置指令,然后通过npm run xx / yarn xx 的方式来执行,在scripts中可以配置的指令有哪些呢?
nuxt
启动一个热加载的web服务器(开发模式) localhost: 3000nuxt build
利用webpack编译应用,压缩JS和css资源(用于发布)nuxt start
以生产模式启动一个web服务器(需要先执行nuxt build)nuxt generate
编译应用,并依据路由配置生成对应的html文件(用于静态站点的部署)
如果使用的Koa、Express等Node.js Web开发框架,并使用Nuxt作为中间件,可以自定义Web服务器的启动入口
NODE_ENV=development nodemon server/index.js
启动一个热加载的自定义Web服务器(开发模式)NODE_ENV=production node server/index.js
以生产模式启动一个自定义Web服务器(需要先执行nuxt build)
若对于命令了解的不多,想要查看更多命令,可以在package.json中配置"help": "nuxt --help",
就可以在终端上打印全部指令
- –config-file 或 -c: 指定 nuxt.config.js 的文件路径。
- –spa 或 -s: 禁用服务器端渲染,使用 SPA 模式
- –unix-socket 或 -n: 指定 UNIX Socket 的路径。
上面指令实例我们会发现,要将参数传递给 npm 命令,您需要一个额外的--
注意事项
- 因为asyncData在beforeCreate钩子调用前调用,此时还没有this,如果想要访问vuex,可以通过asyncData中的上下文对象来进行访问
如果有用,点个赞呗~
总结用法,希望可以帮助到你,
我是Ably,你无须超越谁,只要超越昨天的自己就好~