Nuxt.js(imgs)
- 概述:Nuxt是一个做Vue SSR的框架
- 包含功能:
- 基于Vue2版本框架来做的
- 包含Vue router(Vue本身是不带路由,Vue是通过插件的方式做路由,但是Nuxt已经把这部分整合进去了,同时是它将Vue配置化变得非常简单,甚至可以不用配就能用)
- 支持Vuex(Vuex是跨组件状态管理工具)
- 支持Vue Server render(SSR)
- 支持vue-meta
- 中文文档:
https://zh.nuxtjs.org/guide/
英文文档:https://nuxtjs.org/api
Nuxt.js工作流(imgs)
Nuxt.js从浏览器发请求,到最终服务端渲染完页面给你中间经历了什么,准确地说,在这个经历中Nuxt.js的生命周期是什么
- Incoming Request指的是浏览器发出一个请求,那么服务端接收到这个请求之后呢
- 它要检查当前有没有nuxtServerInit这个配置项,如果有的话就先执行这个函数。Store action是用来操作vuex的
- middleware中间件,这个中间件是和路由相关,在这里可以做任何你想要的功能
- 验证:validate(),可以配合高级动态路由去做验证,比如说这个页面是否允许跳到别的页面上去,如果没有得到我的校验的话,我可以跳走之类的等等
- 获取数据,又分两个函数,第一个是aysncData(),第二个是fetch(),他们两个实现的是同样的功能,都是获取数据,区别是aysncData()获取的数据是渲染vue组件的,fetch通常是修改vuex的也就是store这些东西的,
- Render:渲染,有模板,有数据进行渲染了
- 其中有一个nuxt-link,如果是发起一个新的路由,那么这个时候要从头开始循环
Nuxt.js中的路由
- Nuxt.js安装:
- 前提:在node环境做,其他环境不支持SSR
- 官网安装:
https://zh.nuxtjs.org/guide/installation
(不带koa,但是我们需要koa2,所以这里暂不用官网的方式安装) - 步骤:
vue init nuxt-community/koa-template 项目名:nuxt-learn 项目描述 nuxt.js Project npm install npm install --uqdate-binary npm install eslint-plugin-html@^3 报错:...... 解决:将nuxt版本降低 npm uninstall nuxt npm install [email protected] 访问localhoost:3000 ----->运行成功
- 目录介绍:
README .md 辅助文档 assets 放置静态资源文件,比如说css文件等 backpack.config.js 后端编译脚本 build 所有编译完后的目录 components 放置vue组件 layouts 模板 node_modules 安装包 nuxt.config.js nuxt配置文件 package-lock.json package.json pages 页面入口 server koa相关程序 static 放置静态文件 store 放置vuex
- 新建一个文件,文件名即是路由,重要一句话:创建即配置
- 例1:
我在pages文件夹下创建search.vue文件,那么 访问http://localhost:3000/search,就直接能访问到search.vue文件 考虑:创建文件,它做了几部分工作呢 第一部分,帮我们自动加路由,让search这个路由配置了search.vue文件,也就是做了映射 第二部分,它会把search.vue文件作为你配置的一个入口文件 然后我们要是还想配置子组件,直接加components选项配置,和vue用法一样
- layouts/default.vue:没有声明模版的时候,都是使用这个模板
pages中的vue文件,如果没有配置模板的话,默认使用layouts/default.vue模板 layouts/default.vue模版内容: <template> <div> //这个nuxt就是放置page中的vue文件的位置,相当于router-link,router-view的原理 <nuxt/> <my-footer/> </div> </template> 访问localhost:3000/index: 上面:page/index.vue 下面:layouts/default.vue模板中内容 同理pages下的其他文件也都一样
- 例2:
1. 在pages下建立search.vue <template> <div> search </div> </template> <script> export default { //这里声明我用search模板,那就不是用default模板了 layout: 'search' } </script> <style lang="css"> </style> 2. 在layouts下建立search.vue <template> <div class="layout-search"> <h1>header</h1> <nuxt/> <footer>footer</footer> </div> </template> <script> export default { } </script> <style lang="css"> .layout-search{ color:red } </style> 3. npm run dev -->得到结果 4. 注意:空格,格式什么东东的一定要注意,多一个空格都不行
- 例1:
- 配置文件:nuxt.config.js
- 英文文档:
https://nuxtjs.org/api
-->CONFIGURATION - 解释:
module.exports = { /* ** Headers of the page */ head: { // 页面名称 title: 'starter', // 整合了vue-meta这部分的功能 meta: [ { charset: 'utf-8' }, { name: 'viewport', content: 'width=device-width, initial-scale=1' }, { hid: 'description', name: 'description', content: 'Nuxt.js project' } ], link: [ { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' } ] }, // 注意,这里配置的css是全局的css文件,也就是全局都能用 /* ** Global CSS:全局css文件 */ // 这就是css文件能生效的原因 css: ['~assets/css/main.css'], /* ** Customize the progress-bar color */ loading: { color: '#3B8070' }, /* ** Build configuration */ //配置eslint build: { /* ** Run ESLINT on save */ extend (config, ctx) { if (ctx.isClient) { config.module.rules.push({ enforce: 'pre', test: /\.(js|vue)$/, loader: 'eslint-loader', exclude: /(node_modules)/ }) } } } }
- 英文文档:
Nuxt获取异步数据
- 之前的做法
- 第一步:编写路由
1. server下新建interface,interface下建立city.js 2. server/interface/city.js: import Router from 'koa-router' const router = new Router({ prefix:'/city' }) //这个就是客户端访问地址,我返回给它的数据 router.get('/list' , async (ctx)=>{ ctx.body = ['A', 'B', 'C'] }) export default router
- 第二步:在server/index.js中引入路由
server/index.js import cityInterface from './interface/city.js' app.use(cityInterface.routes()).use(cityInterface.allowedMethods())
- 第三步:测试
npm run dev http://localhost:3000/city/list --> 得到数据['A', 'B', 'C']
- 第四步:浏览器获得数据,pages/search.vue
search.vue: <template> <div> <ul> <li v-for="(item,index) in list" :key="index">{{item}}</li> </ul> </div> </template> <script> import axios from 'axios' export default { layout: 'search', data() { return { list: [] } }, //在mounted生命周期函数 async mounted() { let self = this //可以查询一下axios包返回的状态码,更好的理解status等参数 let {status, data: [...list]} = await axios.get('/city/list') // let res = await axios.get('/city/list') console.log(list) if (status === 200) { self.list = list } } } </script> <style lang="css"> </style>
- 缺点:服务端没有在渲染的时候把你的数据扔进去,是你在浏览器端发出的请求获得的数据,最后渲染到页面上的(只有页面里有数据,网页 源码里没有)
- 原因是:因为服务器端渲染是不执行mounted的,mounted是在浏览器端执行的,只有created是在开启SSR过程中也就是服务器端渲染时执行的
- 第一步:编写路由
- 现在的做法
- 改进:用SSR
上面的都一样,只有pages/search.vue中async mounted()更改成了asyncData(nuxt工作流中出现的) // 允许 asyncData在render之前的,也就是服务器渲染(SSR),可以请求异步数据的 //不能用fetch,因为fetch是处理vuex相关数据的,而asyncData是处理组件相关的数据 //具体可以查看官网:https://nuxtjs.org/api/搜索fetch和asyncData async asyncData() { // let self = this 这时候是没有app实例的是,所以没有this的 let {status, data: [...list]} = await axios.get('http://localhost:3000/city/list') // let res = await axios.get('/city/list') console.log(list) if (status === 200) { return { // 等价于把list赋值给data list } } }
- 服务器把它编译好的内容下发给你
- 服务器端把异步获取到的数据也同时扔给浏览器端
数据是怎么扔给你的呢? 通过下发一个script标签,然后在window上挂了一个对象 这个对象,第一个是告诉你模板,用的是search,第二个给你的是数据
- 改进:用SSR
Nuxt.js中使用Vuex
- 中文文档:
https://zh.nuxtjs.org/guide/vuex-store
- 创建文件
- store文件夹,下面包括modules文件夹和index.js文件
- modules文件夹下有两个文件分别是city.js和navbar.js
-
- 例
store/modules/city.js: const state = () => ({ list: ['a', 'b'] }) const mutations = { add(state, text){ state.list.push(text) } } const actions = { add: ({commit} , text) =>{ commit('add' , text) } } export default { namespaced:true, state, mutations, actions } store/modules/navbar.js: const state = () => ({ app: ['我'] }) const mutations = { add(state, text) { state.app.push(text) } } const actions = { add: ({commit} , text) => { commit('add' , text) } } export default { namespaced:true, state, mutations, actions } store/index.js: import Vue from 'vue' import Vuex from 'vuex' import city from './modules/city.js' import navbar from './modules/navbar.js' Vue.use(Vuex) const store = () => new Vuex.Store({ modules: { city, navbar }, actions: { } }) export default store pages/search.vue:(部分代码) <template> <div> <ul> <li v-for="(item,index) in $store.state.navbar.app" :key="index">{{item}}</li> </ul> </div> </template>
- 和上面的data下发数据一样高:服务器端把异步获取到的数据也同时扔给浏览器端
数据是怎么扔给你的呢? 通过下发一个script标签,然后在window上挂了一个对象 这个对象,第一个是告诉你模板,用的是search,第二个给你的是数据
- 例
- npm run dev – http://localhost:3000/search — 正确返回数据
- actions:
https://nuxtjs.org/guide/vuex-store#the-nuxtserverinit-action
SSR工作原理
https://ssr.vuejs.org/zh/