一篇文章搞定nuxt

2022-02-20  本文已影响0人  申_9a33

1. 初探

1.1 先创建项目,执行 yarn create nuxt-app nuxt-demo

屏幕截图 2022-02-19 141642.png

1.2 执行npm run dev

屏幕截图 2022-02-19 144539.png

2.router

//pages\product.vue
<template>
  <div>
    <div>
      Produt page
    </div>
    <div>
      <NuxtLink to="/product/id1">
        产品1
      </NuxtLink>
      <NuxtLink to="/product/id2">
        产品2
      </NuxtLink>
      <NuxtLink to="/product/id3">
        产品3
      </NuxtLink>
    </div>
    <div>
      <NuxtChild />
    </div>
  </div>
</template>

<script lang="ts">
import Vue from 'vue'

export default Vue.extend({
  name: 'ProdutPage'
})
</script>
// pages\product\index.vue
<template>
  <div />
</template>
// pages\product\_id.vue
<template>
  <div>
    ProductDetail - {{ id }}
  </div>
</template>

<script lang="ts">
import Vue from 'vue'

export default Vue.extend({
  name: 'ProductDetail',
  computed: {
    id () {
      return this.$route.params?.id || ''
    }
  }
})
</script>

3.layout

// layouts\menu.vue
<template>
  <div class="menu-layout">
    <div class="menu">
      <div>导航栏</div>
      <NuxtLink to="/">
        Home
      </NuxtLink>
      <NuxtLink to="/login">
        Login
      </NuxtLink>
      <NuxtLink to="/product">
        Product
      </NuxtLink>
    </div>
    <div class="container">
      <nuxt />
    </div>
  </div>
</template>

<script lang="ts">
import Vue from 'vue'

export default Vue.extend({
  name: 'MenuLayout'
})
</script>

<style scoped>
.menu-layout {
  width: 100%;
  height: 100%;
  display: flex;
  flex-flow: row;
  justify-content: flex-start;
  align-content: center;
}

.menu {
  width: 200px;
  height: 100%;
  display: flex;
  flex-flow: column;
}

.container {
  display: flex;
  flex-grow: 1;
}
</style>

4.store

// store\index.ts

// state 每次客户端请求都会创建一个全新的
export const state = () => ({
  visitsNumber: 0
})

export const mutations = {
  increment (state:any) {
    state.visitsNumber++
  }
}
// store\todos.ts

// 每次客户端请求都会创建一个全新的 state
export const state = () => ({
  curTime: 0
})

export const mutations = {
  changeTime (state:any, time:number) {
    state.curTime = time
  }
}

export const actions = {
  async getTime ({ commit }:any) {
    // 模拟接口请求
    const time = await new Promise((resolve) => {
      setTimeout(() => {
        resolve(Date.now())
      }, 1000)
    })

    commit('changeTime', time)

    return time
  }
}
// pages\index.vue

<template>
  <div>
    HomePage

    <p>
      访问次数:{{ visitsNumber }}
    </p>

    <p>
      vuex储存时间:{{ curTime }}
      <a-button type="primary" @click="handleClick">
        本地改变时间
      </a-button>
    </p>

    <p>
      接口调用时间:{{ time }}
    </p>
  </div>
</template>

<script lang="ts">
import Vue from 'vue'
import { mapState, mapActions } from 'vuex'

export default Vue.extend({
  name: 'IndexPage',
  layout: 'menu',
  // 只会在服务端执行
  async asyncData ({ store }) {
    // 模拟接口请求和store方法调用
    const time = await store.dispatch('todos/getTime')

    return {
      time
    }
  },
  data () {
    return {
      time: 0
    }
  },
  computed: {
    ...mapState(['visitsNumber']),
    ...mapState('todos', ['curTime'])
  },
  methods: {
    ...mapActions('todos', ['getTime']),
    handleClick () {
      this.getTime()
    }
  }

})
</script>


5. middleware

// middleware\router.middleware.ts
// 可以是异步的
export default function ({ route }:any) {
  console.log(route.path, 'router.middleware')
}
// nuxt.config.js
  router: {
    middleware: 'router.middleware'
  }
// middleware\layout.middware.ts
// 可以是异步的
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export default function ({ store, redirect }:any) {
  console.log('layout.middware')
}
// layouts\menu.vue
export default Vue.extend({
  middleware: ['layout.middware']
})
// pages\index.vue
  middleware (context) {
    console.log('home 匿名middleware')
  },

6.serverMiddleware

// server-middleware\visitsNumber.ts
let visitsNumber = 0

// eslint-disable-next-line @typescript-eslint/no-unused-vars
export default function (req:any, res:any) {
  res.setHeader('Content-Type', 'application/json')
  res.write(JSON.stringify({ visitsNumber: visitsNumber++ }))
  res.end()
}
// nuxt.config.js

  // 服务端中间件
  serverMiddleware: [
    { path: '/visits', handler: '~/server-middleware/visitsNumber.ts' }
  ]

7.axios

// plugins\axios.ts

export default function ({ $axios, redirect }:any, inject:any) {
  console.log('axios plugins')
  // 可以创建新的实例,然后inject到context上
  const api = $axios.create({
    baseURL: 'http://localhost:3000',
    timeout: 6000
  })
  inject('api', api)
}
// nuxt.config.js

  plugins: [
    '@/plugins/axios',
  ],
// store\index.ts

export const actions = {
  async nuxtServerInit (store:any, context:any) {
    console.log('nuxtServerInit')

    // 每次初始化都调用接口
    const res = await context.$api.get('/visits')
    const { visitsNumber } = res.data
    store.commit('increment', visitsNumber)
  }
}


上一篇 下一篇

猜你喜欢

热点阅读