仿美团项目基础准备之Nuxt.js

Nuxt.js(imgs)

  1. 概述:Nuxt是一个做Vue SSR的框架
  2. 包含功能:
    • 基于Vue2版本框架来做的
    • 包含Vue router(Vue本身是不带路由,Vue是通过插件的方式做路由,但是Nuxt已经把这部分整合进去了,同时是它将Vue配置化变得非常简单,甚至可以不用配就能用)
    • 支持Vuex(Vuex是跨组件状态管理工具)
    • 支持Vue Server render(SSR)
    • 支持vue-meta
  3. 中文文档:https://zh.nuxtjs.org/guide/
    英文文档:https://nuxtjs.org/api

Nuxt.js工作流(imgs)

Nuxt.js从浏览器发请求,到最终服务端渲染完页面给你中间经历了什么,准确地说,在这个经历中Nuxt.js的生命周期是什么

  1. Incoming Request指的是浏览器发出一个请求,那么服务端接收到这个请求之后呢
  2. 它要检查当前有没有nuxtServerInit这个配置项,如果有的话就先执行这个函数。Store action是用来操作vuex的
  3. middleware中间件,这个中间件是和路由相关,在这里可以做任何你想要的功能
  4. 验证:validate(),可以配合高级动态路由去做验证,比如说这个页面是否允许跳到别的页面上去,如果没有得到我的校验的话,我可以跳走之类的等等
  5. 获取数据,又分两个函数,第一个是aysncData(),第二个是fetch(),他们两个实现的是同样的功能,都是获取数据,区别是aysncData()获取的数据是渲染vue组件的,fetch通常是修改vuex的也就是store这些东西的,
  6. Render:渲染,有模板,有数据进行渲染了
  7. 其中有一个nuxt-link,如果是发起一个新的路由,那么这个时候要从头开始循环仿美团项目基础准备之Nuxt.js_第1张图片

Nuxt.js中的路由

  1. 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     ----->运行成功
      
  2. 目录介绍:
    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
    
  3. 新建一个文件,文件名即是路由,重要一句话:创建即配置
    • 例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模版内容:
        
      访问localhost:3000/index:
          上面:page/index.vue
          下面:layouts/default.vue模板中内容
      同理pages下的其他文件也都一样
      
    • 例2:
      1. 在pages下建立search.vue
          
      
          
      
          
      2. 在layouts下建立search.vue
          
          
          
      
      3. npm run dev  -->得到结果
      4. 注意:空格,格式什么东东的一定要注意,多一个空格都不行
      
  4. 配置文件: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. 之前的做法
    • 第一步:编写路由
      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:
          
      
          
      
          
      
    • 缺点:服务端没有在渲染的时候把你的数据扔进去,是你在浏览器端发出的请求获得的数据,最后渲染到页面上的(只有页面里有数据,网页 源码里没有)
    • 原因是:因为服务器端渲染是不执行mounted的,mounted是在浏览器端执行的,只有created是在开启SSR过程中也就是服务器端渲染时执行的
  2. 现在的做法
    • 改进:用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,第二个给你的是数据
      

Nuxt.js中使用Vuex

  1. 中文文档:https://zh.nuxtjs.org/guide/vuex-store
  2. 创建文件
    • 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:(部分代码)
        
      
    • 和上面的data下发数据一样高:服务器端把异步获取到的数据也同时扔给浏览器端
      数据是怎么扔给你的呢?
      通过下发一个script标签,然后在window上挂了一个对象
      这个对象,第一个是告诉你模板,用的是search,第二个给你的是数据
      
  3. npm run dev – http://localhost:3000/search — 正确返回数据
  4. actions: https://nuxtjs.org/guide/vuex-store#the-nuxtserverinit-action

SSR工作原理

https://ssr.vuejs.org/zh/

你可能感兴趣的:(关于《仿美团》项目系列文章)