Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nuxt之上下文对象context #120

Open
ddd-000 opened this issue Jan 26, 2022 · 2 comments
Open

nuxt之上下文对象context #120

ddd-000 opened this issue Jan 26, 2022 · 2 comments

Comments

@ddd-000
Copy link

ddd-000 commented Jan 26, 2022

https://www.nuxtjs.cn/api/context

@ddd-000 ddd-000 closed this as completed Jan 26, 2022
@ddd-000 ddd-000 reopened this Jan 26, 2022
@ddd-000
Copy link
Author

ddd-000 commented Jan 27, 2022

服务端&客户端常用属性:

  1. app---包含所有插件的vue根实例。
  • 类似于vue中的this
  • 很多nuxt生命周期运行在服务端,先于vue实例创建,无法通过this去获取,可通过app属性去访问
  • 常用:

const { head, store, router, data, $axios } = context.app

  1. store---vuex相关属性
    image
    const { store } = context

  2. route--路由相关属性
    image
    const { route } = context

  3. $axios
    image
    context.$axios
    插件同上,如$device、$dayjs等

  4. error--状态码报错相关属性(是一个函数)
    image

context.error
404页面的处理

context.error({
  statusCode: 404,
  message: 'not Found'
})
  1. env--获取访问地址
    context.env
//获取某个访问地址
context.env.CART
//推荐:
process.env.CART
  1. params --获取params传递的参数(:id)
context.params.id
  1. query--获取params传递的参数(?id=${id}&cid=${cid})
context.query
  1. redirect--路由重定向
    image
    context.redirect('/xx/xxx')

  2. $config--运行时配置

  • 运行时配置允许将动态配置和环境变量传递给 nuxt 上下文
  • '$config': { app: { basePath: '/', assetsPath: '/_nuxt/', cdnURL: null } }
    image
    image
  1. isDev--是否是开发 dev 模式,在生产环境的数据缓存中用到
  2. isHMR--是否是通过模块热替换 webpack hot module replacement (仅在客户端以 dev 模式)

服务端访问的属性

if (process.server) {
    const { req, res, beforeNuxtRender } = context
  }
  1. req--数据请求
const {headers, url, method, statusCode, authKey} = context.req
  1. res--数据响应
const { statusCode, socket} = context.res

// 处理 404,不上架的都是
  if (res.data.status != 'OnShelf') {

    if (process.server) {
      context.res.statusCode = 404
    }

    context.error({
      statusCode: 404,
      message: 'not Found'
    })
  }
  1. beforeNuxtRender--在nuxt渲染之前
    image
    server.js中声明
const beforeRender = async () => {
    // Call beforeNuxtRender() methods
    await Promise.all(ssrContext.beforeRenderFns.map(fn => promisify(fn, { Components, nuxtState: ssrContext.nuxt })))

    ssrContext.rendered = () => {
      // Add the state from the vuex store
      ssrContext.nuxt.state = store.state
    }
  }
  1. ssrContext
    //server.js
    image

客户端访问的属性

if (process.client) {
    const { from, nuxtState } = context
  }
  1. from--导航路线(从哪里来)
    //client.js
    image

  2. nuxtState--获取nuxt状态
    image

context.nuxtState

@ddd-000
Copy link
Author

ddd-000 commented Jan 27, 2022

context实现:

.nuxt/utils.js

export async function setContext (app, context) {
  // If context not defined, create it
  if (!app.context) {
    app.context = {
      isStatic: process.static,
      isDev: true,
      isHMR: false,
      app,
      store: app.store,
      payload: context.payload,
      error: context.error,
      base: app.router.options.base,
      env: {"ENVELOPE":"https://oss-wf12.xpccdn.com/dev","CART":"https://next.vmovier.cc","USERCENTER":"http://user-center.wkm.vmovier.cc/api/v2","STOCK":"http://dev-stock-api.vmovier.cc","PASSPORT_URL":"https://dev-passport.vmovier.cc","SNS_URL":"http://dev-sns.vmovier.cc","EDU_URL":"http://dev-school.vmovier.cc","RESOURCE_URL":"http://dev-resource.vmovier.cc","VIP_URL":"http://dev-vip.vmovier.cc","MALL":"http://dev-mall.vmovier.cc","LOCATION":"http://assets.local.vmovier.cc:4000","PAY":"https://dev-paycenter.vmovier.cc","APP":"http://dev-xpc-api.vmovier.cc","cookieprefix":"LOCAL-","musicProductIds":["yQLGsSBZPfyHhmH3ir3vxiVEBWcqlM","yQLGsSBZQGk130jQEAl9UMgPtUlK9x","yQLGsSBZNtIvbWvIKT302r84FXh4QT","yQLGsSBZI8LV2N6DxnTuXh99VfFghD","RUwZts9dcWFtKeUwvzfoKUUWyAk49yY","yQLGsSBZNOUyQzPE6EiX0WPmlSiA7m","yQLGsSBZLBEMWUR1iAbiqJqlR68Aje"]}
    }
    // Only set once

    if (context.req) {
      app.context.req = context.req
    }
    if (context.res) {
      app.context.res = context.res
    }

    if (context.ssrContext) {
      app.context.ssrContext = context.ssrContext
    }
    app.context.redirect = (status, path, query) => {
      if (!status) {
        return
      }
      app.context._redirected = true
      // if only 1 or 2 arguments: redirect('/') or redirect('/', { foo: 'bar' })
      let pathType = typeof path
      if (typeof status !== 'number' && (pathType === 'undefined' || pathType === 'object')) {
        query = path || {}
        path = status
        pathType = typeof path
        status = 302
      }
      if (pathType === 'object') {
        path = app.router.resolve(path).route.fullPath
      }
      // "/absolute/route", "./relative/route" or "../relative/route"
      if (/(^[.]{1,2}\/)|(^\/(?!\/))/.test(path)) {
        app.context.next({
          path,
          query,
          status
        })
      } else {
        path = withQuery(path, query)
        if (process.server) {
          app.context.next({
            path,
            status
          })
        }
        if (process.client) {
          // https://developer.mozilla.org/en-US/docs/Web/API/Location/replace
          window.location.replace(path)

          // Throw a redirect error
          throw new Error('ERR_REDIRECT')
        }
      }
    }
    if (process.server) {
      app.context.beforeNuxtRender = fn => context.beforeRenderFns.push(fn)
    }
    if (process.client) {
      app.context.nuxtState = window.__NUXT__
    }
  }

  // Dynamic keys
  const [currentRouteData, fromRouteData] = await Promise.all([
    getRouteData(context.route),
    getRouteData(context.from)
  ])

  if (context.route) {
    app.context.route = currentRouteData
  }

  if (context.from) {
    app.context.from = fromRouteData
  }

  app.context.next = context.next
  app.context._redirected = false
  app.context._errored = false
  app.context.isHMR = Boolean(context.isHMR)
  app.context.params = app.context.route.params || {}
  app.context.query = app.context.route.query || {}
}

在client.js调用和更新:

await setContext(app, {
    route: to,
    from,
    next: _next.bind(this)
  })

await setContext(app, {
      route: router.currentRoute,
      isHMR: true,
      next: next.bind(this)
    })

asyncData&fetch相关配置---server.js

const asyncDatas = await Promise.all(Components.map((Component) => {
    const promises = []

    // Call asyncData(context)
    if (Component.options.asyncData && typeof Component.options.asyncData === 'function') {
      const promise = promisify(Component.options.asyncData, app.context)
      promise.then((asyncDataResult) => {
        ssrContext.asyncData[Component.cid] = asyncDataResult
        applyAsyncData(Component)
        return asyncDataResult
      })
      promises.push(promise)
    } else {
      promises.push(null)
    }

    // Call fetch(context)
    if (Component.options.fetch && Component.options.fetch.length) {
      promises.push(Component.options.fetch(app.context))
    } else {
      promises.push(null)
    }

    return Promise.all(promises)
  }))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant