Nuxt

Time:2020-10-24

Server rendering

Server knowledge: koa node.js
SSR principle:
*Render the same components as server-side HTML strings, send them directly to the browser, and finally send these static tags to the browser
“Live” is a fully interactive application on the client. *
Response scenario:

  1. Need better SEO
  2. Faster content arrival time (screen rendering time) is required, especially for slow network conditions or slow running devices.

The limitations of SSR are as follows

  1. More server side load
  2. The cost of learning
  3. Some external extension libraries make it limited

Nuxt installation
NPX create nuxt app
start-up
npm run dev

Recording structure

assets: resources ⽬ record assets ⽤ to organize uncompiled static resources such as less, sass, or JavaScript.

components: components record the components of the organization Vue.js Component. Nuxt.js It will not expand to enhance the recording

Vue.js Components, that is, these components will not have the asyncdata ⽅ method characteristics like ⻚⾯ components.

layouts: layout records the layout components that the organization should use.

middlewareMiddleware is stored in the middleware of the application.

pages:Record the routes and views of pages in the organization. Nuxt.js The frame reads all the. Vue ⽂

The corresponding routing configuration is generated and implemented.

plugins:Plugins to organize those that need to be in the root vue.js Should be run before instantiation

JavaScript plug-in.
static:The static parts are stored in the static parts that should be stored, and such parts will not be Nuxt.js Call webpack to build and compile. When the server is started, the recorded file will map to the root path / path of the application.
store:Store records the vuex status tree files that the organization should. Nuxt.js The framework integrates the related function configuration of vuex state tree, and creates ⼀ in store ⽬ index.js These configurations can be activated.
nuxt.confifig.js: nuxt.config.js Parts in organization Nuxt.js Should be personalized to override the default configuration.

Convention is better than configuration

Convention is better than configuration
Routing: the routing configuration of all *. Vue files in pages ⽬
Navigation:

<nuxt-link to="/">⾸⻚</nuxt-link>

Nesting: make ⼀. Vue ⽂ parts and ⽂ parts of the same name

pages/
--| main/
--| main.vue

Dynamic routing: ⽂ piece name or ⽂ folder name should be carried_

pages/
--| main/
-----| detail/
--------| _id.vue

⻚⾯

⾃ define layout:

  1. Create layouts/ main.vue
<template>
    <div>
    <nav>
      <n-link to="/main">index</n-link>
      <! -- alias -- >
      < n-link to = / main / Admin "no prefetch > Administration
      
      <N-link to="/main/cart">gouwu</N-link>
    </nav>
    <nuxt-child />
    </div>
</template>

<script>
    export default {
        
    }
</script>

<style lang="scss" scoped>

</style>

pages/login.vue

<template>
    <div>
        <h1>User login</h1>
        <el-input v-model="user.username"></el-input>
        <el-input type="password" v-model="user.password"></el-input>
        < El button @ Click = "onlogin" > login < / El button >
    </div>
</template>

<script>
    export default {
        data(){
            return {
                user:{
                    username:"",
                    password:""
                }
            }
        },
        methods:{
            onLogin(){
                this.$store.dispatch("user/login",this.user).then(ok=>{
                    if(ok){
                        this.$router.push("/")
                    }
                })
            }
        }
    }
</script>

<style lang="scss" scoped>

</style>
  1. Pages/ main.vue
export default {
  layout: 'main',
};

main/admin.vue

<template>
    <div>
        <h1>Product management page</h1>
    </div>
</template>

<script>
    export default {
        middleware: 'auth'
    }
</script>

<style lang="scss" scoped>

</style>

/main/cart.vue

<template>
    <div>
        <h1>Shopping cart</h1>
    </div>
</template>

<script>
    export default {
        
    }
</script>

<style lang="scss" scoped>

</style>

mian/index.vue

<template>
  <div>
    <h1>Home page</h1>
    <ul>
      <li v-for="good in goods" :key="good.id">
        <nuxt-link :to="{name:'main-detail-id',params:{id:good.id}}">
        <span>{{good.text}}</span>
        <span>¥{{good.price}}</span>
        < button @ Click = "addcart (good)" > Add shopping cart < / button >
        </nuxt-link>
      </li>
    </ul>
  </div>
</template>

<script>


export default {
  Head() {// head
    return{
      Title: "list,",
      meta:[{name:"description",hid:"description",content:"set page meta"}],
      link:[{rel:"favicon",href:"favicon.ico"}],
      script:[{src:"https://cdn.jsdelivr.net/npm/jquery/dist/jquery.js"}]
    }
  },
  layout:'users',
  //Before the component is created, send the Ajax request data, and then start to create the data whose priority is higher than the following
  async asyncData({$axios,error,redirect}) {
    //Asyncdata is earlier than the point in time, so you cannot use this to access the component instance
    const result = await $axios.$get('/api/goods')
    if(result.ok){
      return {goods: result.goods}
    }
    //Error handling
    Error ({status code: 400, message: "query data failed"})
  },
  data(){
    return {
      goods:[
        {id:1,text:'Web',price:4444},
        {ID: 2, text: 'move', price:5555 }
      ]
    }
  }
}
</script>

<style>
.container {
  margin: 0 auto;
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  text-align: center;
}

.title {
  font-family: 'Quicksand', 'Source Sans Pro', -apple-system, BlinkMacSystemFont,
    'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  display: block;
  font-weight: 300;
  font-size: 100px;
  color: #35495e;
  letter-spacing: 1px;
}

.subtitle {
  font-weight: 300;
  font-size: 42px;
  color: #526488;
  word-spacing: 5px;
  padding-bottom: 15px;
}

.links {
  padding-top: 15px;
}
</style>

mian/detail/_id.vue

<template>
    <div>
        <h2>Product details</h2>
        ${{goodInfo}}
    </div>
</template>

<script>
    export default {
        async asyncData(ctx) {
            console.log(ctx)
            const {$axios,params,error} = ctx
            //The component instance cannot be obtained through this, but the relevant data can be obtained through the context
            const result = await $axios.$get("/api/detail",{params})
            if(result.data){
                return {goodInfo: result.data}
            }
            error({s tatusCode:400 , message: "product details query failed"})
        },
    }
</script>

<style lang="scss" scoped>

</style>

Asynchronous data:
asyncData
It executes ⾏, ⾥⾯, and does not access the component instance before the component is created
The first parameter is up and down
It can be executed on both the server and the client
Asyncdata will merge with data

<template>
  <div>
    <h1>Home page</h1>
    <ul>
      <li v-for="good in goods" :key="good.id">
        <nuxt-link :to="{name:'main-detail-id',params:{id:good.id}}">
        <span>{{good.text}}</span>
        <span>¥{{good.price}}</span>
        < button @ Click = "addcart (good)" > Add shopping cart < / button >
        </nuxt-link>
      </li>
    </ul>
  </div>
</template>

<script>


export default {
  Head() {// head
    return{
      Title: "list,",
      meta:[{name:"description",hid:"description",content:"set page meta"}],
      link:[{rel:"favicon",href:"favicon.ico"}],
      script:[{src:"https://cdn.jsdelivr.net/npm/jquery/dist/jquery.js"}]
    }
  },
  layout:'users',
  //Before the component is created, send the Ajax request data, and then start to create the data whose priority is higher than the following
  async asyncData({$axios,error,redirect}) {
    //Asyncdata is earlier than the point in time, so you cannot use this to access the component instance
    const result = await $axios.$get('/api/goods')
    if(result.ok){
      return {goods: result.goods}
    }
    //Error handling
    Error ({status code: 400, message: "query data failed"})
  },
  data(){
    return {
      goods:[
        {id:1,text:'Web',price:4444},
        {ID: 2, text: 'move', price:5555 }
      ]
    }
  }
}
</script>

<style>
.container {
  margin: 0 auto;
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  text-align: center;
}

.title {
  font-family: 'Quicksand', 'Source Sans Pro', -apple-system, BlinkMacSystemFont,
    'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  display: block;
  font-weight: 300;
  font-size: 100px;
  color: #35495e;
  letter-spacing: 1px;
}

.subtitle {
  font-weight: 300;
  font-size: 42px;
  color: #526488;
  word-spacing: 5px;
  padding-bottom: 15px;
}

.links {
  padding-top: 15px;
}
</style>

Preparation:

  1. Create server/ api.js
const router = require("koa-router")({prefix:"/api"})
const goods = [
    {id:1,text:"web",price:1999},
    {
      id: 2,
      Text: "move,",
      price: 199
    },
];
router.get("/goods",ctx => {
    ctx.body = {
        ok: 1,
        goods
    }
});
router.get("/detail",ctx => {
    ctx.body = {
        ok:1,
        data:goods.find(good => good.id == ctx.query.id)
    }
});
router.post("/login",ctx => {
    const user = ctx.request.body
    if(user.username === "jerry" && user.password ==='123'){
        //Save token into cookie
        const token = 'a mock token'
        ctx.cookies.set('token',token)
        ctx.body = {
            ok:1,token
        }
    } else {
        ctx.body = {ok: 0}
    }
});
module.exports = router

2. Modify the server configuration/ index.js

const Koa = require('koa')
const consola = require('consola')
const { Nuxt, Builder } = require('nuxt')
//Analysis of post data
const bodyparser = require("koa-bodyparser")
const api = require('./api')
const app = new Koa()
//Set cookie encryption key
app.keys = ["some secret","another secret"]
// Import and Set Nuxt.js options
const config = require('../nuxt.config.js')
config.dev = app.env !== 'production'

async function start () {
  // Instantiate nuxt.js
  const nuxt = new Nuxt(config)

  const {
    host = process.env.HOST || '127.0.0.1',
    port = process.env.PORT || 3000
  } = nuxt.options.server

  await nuxt.ready()
  // Build in development
  if (config.dev) {
    const builder = new Builder(nuxt)
    await builder.build()
  }
//Parse post data and register route
  app.use(bodyparser())
  app.use(api.routes())
  //Page rendering
  
  app.use((ctx) => {
    ctx.status = 200
    ctx.respond = false // Bypass Koa's built-in response handling
    ctx.req.ctx = ctx // This might be useful later on, e.g. in nuxtServerInit or with nuxt-stash
    nuxt.render(ctx.req, ctx.res)
  })

  app.listen(port, host)
  consola.ready({
    message: `Server listening on http://${host}:${port}`,
    badge: true
  })
}

start()

middleware

The middleware will run the functions defined by us before rendering, such as permission control and verification.
⾸⻚ redirection, creating Middleware / index- redirect.js

export default function({route,redirect}){
    //The middleware can obtain the context, which contains all kinds of useful information
    //Commonly used are app, route, redirect, store
    if(route.path === '/'){
        redirect('/main')
    }
}

Register middleware, nuxt.config.js

router: {
  middleware: ['index-redirect']
},

plug-in unit

Nuxt.js The JS plug-in will be executed before the operation of Vue, and the characteristics of Vue plug-in, definition module and third module need to be introduced or set
Don’t have it.
Create plugins / API- inject.js

//Injection interface uses plug-in mechanism to inject service interface into component instance and store instance
export default({$axios},inject) => {
    inject("login",user => {
        return $axios.$post("/api/login",user)
    })
}

Register plug-ins, nuxt.config.js

plugins: [
  "@/plugins/api-inject"
],

vuex

Save user login and login status, and create a store/ user.js

//If the store directory exists in the application root directory, Nuxt.js The number of vuex States will be enabled. When defining each state tree, the state and mutations will be exported, getters.actions that will do
export const state = () => ({
    token:''
})
export const mutations = {
    init(state,token){
        state.token = token
    }
}
export const getters = {
    isLogin(state) {
        return !!state.token
    }
}
export const actions = {
    login({commit},u){
        return this.$login(u).then(({token})=>{
            if(token){
                commit("init",token)
            }
            return !!token
        })
    }
}

Make ⽤ state, create middleware middleware middleware/ auth.js

export default function({redirect,store}){
    console.log("token:" + store.state.user.token)
    //Whether to log in or not is judged by the existence of token in vuex
    if(!store.state.user.token){
        redirect("/login")
    }

}

Register the middleware, admin.vue

export default {
  middleware: 'auth'
}

State initialization, store/ index.js

export const actions = {
    nuxtServerInit({commit},{req}){
        //The server fills the vuex state
        //Parameter 1 is the context of vuex
        //Parameter 2 is the context of nuxt
        // req.ctx Is the context of KOA, because the value assigned in server / index
        const token = req.ctx.cookies.get('token')
        if(token){
            console.log ("initialization token")
            console.log(token)
            commit('user/init',token)
        }
    }
}

nuxt.config.js

module.exports = {
  mode: 'universal',
  /*
  ** Headers of the page
  */
  head: {
    title: process.env.npm_package_name || '',
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      { hid: 'description', name: 'description', content: process.env.npm_package_description || '' }
    ],
    link: [
      { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
    ]
  },
  /*
  ** Customize the progress-bar color
  */
  loading: { color: '#fff' },
  /*
  ** Global CSS
  */
  css: [
    'element-ui/lib/theme-chalk/index.css'
  ],
  //Routing configuration
  router: {
    //Sequence from front to back
    middleware: ['index-redirect']
  },
  /*
  ** Plugins to load before mounting the App
  */
  plugins: [
    '@/plugins/element-ui',
    '@/plugins/api-inject',
    {src:"@/ plugins.axios ", mode:" client "} // client only
  ],
  /*
  ** Nuxt.js dev-modules
  */
  buildModules: [
  ],
  /*
  ** Nuxt.js modules
  */
  modules: ['@nuxtjs/axios'],
  // axios: {
  //   proxy: true
  // },
  // proxy: {
  //   "api": "http://localhost:8080"
  // },
  /*
  ** Build configuration
  */
  build: {
    transpile: [/^element-ui/],
    /*
    ** You can extend webpack config here
    */
    extend (config, ctx) {
    }
  }
}

pluygins/axios.js

export default function({$axios}){
    //Set global request header by using $Axios modular quick help method settoken
    //The token interception logic is omitted here
    $axios.setToken(document.cookie,'Bearer')
}

layout

Overall layout default
layouts/default.vue

<template>
  <div>
    <nuxt />
  </div>
</template>

<style>
html {
  font-family: 'Source Sans Pro', -apple-system, BlinkMacSystemFont, 'Segoe UI',
    Roboto, 'Helvetica Neue', Arial, sans-serif;
  font-size: 16px;
  word-spacing: 1px;
  -ms-text-size-adjust: 100%;
  -webkit-text-size-adjust: 100%;
  -moz-osx-font-smoothing: grayscale;
  -webkit-font-smoothing: antialiased;
  box-sizing: border-box;
}

*,
*:before,
*:after {
  box-sizing: border-box;
  margin: 0;
}

.button--green {
  display: inline-block;
  border-radius: 4px;
  border: 1px solid #3b8070;
  color: #3b8070;
  text-decoration: none;
  padding: 10px 30px;
}

.button--green:hover {
  color: #fff;
  background-color: #3b8070;
}

.button--grey {
  display: inline-block;
  border-radius: 4px;
  border: 1px solid #35495e;
  color: #35495e;
  text-decoration: none;
  padding: 10px 30px;
  margin-left: 15px;
}

.button--grey:hover {
  color: #fff;
  background-color: #35495e;
}
</style>

custom layout
layouts/error.vue

<template>
    <div class="container">
        <h1 v-if=" error.statusCode  ===404 "> page does not exist</h1>
        < H1 v-else > application error exception</h1>
        < nuxt link to = / "> Home Page < / nuxt link >
    </div>
</template>

<script>
    export default {
        props:['error']
    }
</script>

<style lang="scss" scoped>

</style>

/layouts/users.vue

<template>
<div>
    <h1>Custom layout</h1>
    <nuxt></nuxt>
</div>
</template>

Nuxt

Recommended Today

Elasticsearch learning one (basic introduction)

1、 Introduction to elasticsearch You can describe elasticsearch as follows: A distributed real-time document storage, each field can be indexed and searched A distributed real time analysis search engine It is capable of extending hundreds of service nodes and supports Pb level structured or unstructured data Elasticsearch is a real-time distributed search and analysis engine […]