关于javascript:nuxt构建项目和中间用到的高级方法

4次阅读

共计 11486 个字符,预计需要花费 29 分钟才能阅读完成。

一、引入并创立 nuxt 我的项目

确认曾经装置 npx (npx 依附于 npm 5.2.0 装置引入 )

npx create-nuxt-app <my-project>

或者在 npm v6.1 版本后 能够这样创立:

npm init nuxt-app@latest <my-project>

或者用:yarn:

yarn create nuxt-app <my-project>

二、引入 axios 库

1、应用 nuxt 自带模块

npm i @nuxtjs/axios -s

1)、在 nuxt.config.js 中引入

export default {
  /*
   ** Runtime Config
   */
  publicRuntimeConfig: {
    axios: {baseURL: 'https://api.nuxtjs.dev'}
  },
  /*
   ** Modules - https://nuxtjs.org/docs/2.x/directory-structure/modules
   */
  modules: ['@nuxtjs/axios']
}

2)、页面内应用 $axios 获取数据,并用 $config 获取 API 接口的 URL

async asyncData({$axios}) {let { res} = await $axios.get(`https://xxx.com/api/xxx`) 
  console.log(res)    
}

3)、设置公共拦挡

~/plugins 创立 axios.js 文件

export default function ({store, redirect, req, router, $axios})  {
    // baseUrl 能够在下面的配置中,也可在这儿配置
    $axios.defaults.baseURL = 'http://XXX/api';
    if(process.server){
        // 获取服务端的 token,对应函数请自行封装
        var token = getcookiesInServer(req).token;
    }
    if(process.client){
        // 获取客户端 token,对应函数请自行封装
        var token = getcookiesInClient('token');
    }
    // request 拦截器
    $axios.onRequest(config => {if(process.client){
            // 客户端下,申请进度条开始
            NProgress.start();}
        // 将获取到 token 退出到申请头中
        config.headers.common['Authorization'] = token;
    });
    // response 拦截器,数据返回后,能够先在这里进行一个简略的判断
    $axios.interceptors.response.use(
        response => {if(process.client){
                // 客户端下,申请进度条完结
                NProgress.done();}
            // return response
            if(response.data.code == 401){
                // 返回 401,token 验证失败
                removeToken("token");
                  // 重定向到登录页面,这里做一个判断,容错:req.url 未定义
                if(req.url){redirect("/sign?ref="+req.url)
                }else{redirect("/sign")
                }
            }else if(response.data.code == 404){
                // 重定向到 404 页面
                redirect("/")
            }
            else{
                // 申请接口数据失常,返回数据
                return response
            }
        },
        error => {if(process.client){NProgress.done();
            }
            if(error.response.status == 500){
                // http 状态 500,服务器外部谬误,重定向到 500 页面
                redirect("/500.htm")
            }
            if(error.response.status == 404){
                // http 状态 500,申请 API 找不到,重定向到 404 页面
                redirect("/404.html")
            }
            return Promise.reject(error.response)   // 返回接口返回的错误信息
        })
}

2、内部引入 axios

npm i axios -s

1)、创立 request 文件夹

在文件夹内创立 http.js 文件, urls 文件夹, apis 文件夹

http.js

import axios from 'axios'
import Vue from 'vue'

const ajax = axios.create({
    baseURL: process.env.baseUrl,
    timeout: 30 * 1000
})

// 申请拦截器
ajax.interceptors.request.use(
    config => {// const Token = getToken()
        // if (Token) {//     config.headers['token'] = getToken()
        // }
        config.headers['Content-Type'] = 'application/json;chartset=utf-8'
        // config.headers["Authorization"] = "Bearer atwerjjhqkwehtjhsdfqwehjhwrgqre";
        return config
    },
    error => {throw new Error(` 申请谬误: ${error}`)
    }
)
// 响应拦截器
ajax.interceptors.response.use(
    response => {if (response.status === 200) {
            // 解决返回流文件报错
            if (response.config.responseType === 'blob') {var reader = new FileReader()
                reader.readAsText(response.data)
                reader.onload = e => {const result = JSON.parse(e.target.result)
                    if (result.code !== 200) {Vue.prototype.$message.error(result.msg)
                    }
                }
            }
            if (response.data.code === 200) {return response.data.data} else {Vue.prototype.$message.error(response.data.message)
                return Promise.reject(response.data)
            }
        } else {return response}
    },
    error => {throw new Error(error)
        // throw new Error(` 申请谬误: ${error}`)
    }
)

/*
 * @params {config} 参数从 API 传递过去
 * @params @{config} {url} 申请地址
 * @params @{config} {data} 申请数据
 */
export function get(config) {
    let obj = {
        url: config.url,
        method: 'get',
        params: {...config.data,}
    }
    return ajax(obj)
}

export function post(config) {
    let obj = {
        url: config.url,
        method: 'post',
        data: {...config.data,}
    }
    return ajax(obj)
}

export function upload(config) {
    let obj = {
        url: config.url,
        method: 'post',
        data: config.data,
        headers: {'Content-Type': 'multipart/form-data'}
    }
    return ajax(obj)
}

urls 文件夹下创立对应模块的 url 信息

例如 urls/user.js

export default {
    userinfo: '/user/userinfo',
    userList: '/user/userList'
}

apis 文件夹下创立对应模块的 api 函数

例如 apis/user.js

import {get, post} from '../http.js'
import user from '../urls/user'

export function getUserinfo(params) {return get({ url: userUrls.userinfo, params})
}

export function getUserList(params) {return post({ url: userUrls.userList, params})
}

页面内失常应用咱们熟知的形式引入 api 函数去调接口获取数据

3、axios 跨域配置

1)、应用官网 axios 模块时的配置

export default {
    axios: {
        proxy: true,
        prefix: '/api', // baseURL
        credentials: true,
        retry: {retries: 3}
    },
    proxy: {
        '/api': {
            target: 'http://192.168.xxx.xxx:xxxx', // 代理地址
            changeOrigin: true,
            pathRewrite: {'^/api': '', // 将 /api 替换掉}
        },
    }
}

2)、应用官网 axios 模块,引入官网模块 @nuxtjs/proxy 配置

npm i @nuxtjs/proxy -D

nuxt.config.js 中配置

modules: [
    '@nuxtjs/axios',
    '@nuxtjs/proxy'
],
proxy: [
    [
        '/api', 
        { 
            target: 'http://localhost:3001', // api 主机
            pathRewrite: {'^/api' : '/'}
        }
    ]
]

3)、应用内部引入的形式

配合后端部署设置 nginx

三、登录状态长久化

npm i -S cookie-universal-nuxt

nuxt.config.js 中配置

modules: [
    // 登录状态长久化
    ['cookie-universal-nuxt', { parseJSON: true}]
],

四、引入 ant-design-vue 组件库

npm i -S ant-design-vue
npm install babel-plugin-import --save-dev

1、按需引入配置

// nuxt.config.js
{
    build: {
        babel: {
            plugins: [
                [
                    'import',
                    {
                        libraryName: 'ant-design-vue',
                        libraryDirectory: 'es',
                        style: true
                        // 默认不应用该选项,即不导入款式 , 留神 ant-design-vue 应用 js 文件引入款式
                        // true 示意 import 'ant-design-vue/es/component/style'
                        // 'css' 示意 import 'ant-design-vue/es/component/style/css'
                    }
                ]
            ]
        }
    }
}

~/plugins 文件夹创立 antd-ui.js 文件

import Vue from 'vue'

Vue.config.productionTip = false

import {Button} from 'ant-dsign-vue'

Vue.use(Button)

2、antd-icon 过大

不是所有的图标咱们都能用到

~/plugins 文件夹创立 antd-icons.js 文件

export {
    // 须要应用到的 Icons
    InfoCircleFill,
    DownOutline,
    UpOutline,
    RightOutline,
    LeftOutline
} from '@ant-design/icons'
// nuxt.config.js
const CompressionPlugin = require('compression-webpack-plugin')
const path = require('path')

export default {
    build: {vendor: ['axios', 'ant-design-vue'],
        // 解决 less 加载应用不了的问题
        loaders: {
            less: {javascriptEnabled: true}
        },
        analyze: {analyzerMode: 'static'},
        // 应用 Babel 与特定的依赖关系进行转换
        transpile: [/ant-design-vue/],
        extend(config, ctx) {
            // 配置 eslint
            if (ctx.isClient) {
                config.module.rules.push({
                    enforce: 'pre',
                    test: /\.(js|vue)$/,
                    loader: 'eslint-loader',
                    exclude: /(node_modules)/
                })
                // ant-design-vue 的 icon 组件,按需引入须要的图标,文件太大
                config.resolve.alias['@ant-design/icons/lib/dist$'] = path.resolve(__dirname, './plugins/antd-icons.js') // 引入须要的
            }
        },
        // 打包构建优化
        plugins: [
            new CompressionPlugin({
                test: /\.js$|\.html$|\.css/, // 匹配文件名
                threshold: 10240, // 对超过 10kb 的数据进行压缩
                deleteOriginalAssets: false // 是否删除原文件
            })
        ],
        optimization: {
            splitChunks: {
                minSize: 10000,
                maxSize: 250000
            }
        }
    }
}

留神:这儿装置 compression-webpack-plugin 插件会报错,指定插件版本就行了

npm i --save-dev compression-webpack-plugin@6.1.1

揭示:图标应用 <a-icon type=”close”></a-icon> 来显示

如果有组件内应用的,例如

<a-rate v-model="val">
    <a-icon #character type="star"></a-icon>
</a-rate>

五、国际化

1、引入 i18n

npm  i vue-i18n --save

2、在 plugins 下创立 i18n.js

// nuxt.config.js
export default {
    plugins: [
        '@/plugins/antd-ui',
        {src: '@/plugins/lazy-load', ssr: false},
        '@/plugins/i18n.js',
        {src: '~/plugins/lodash.js', ssr: false},
        {src: '~/plugins/moment.js', ssr: false},
        {src: '@/plugins/vue-swiper.js', mode: 'client'},
    ],
}
import Vue from 'vue'
import VueI18n from 'vue-i18n'
Vue.use(VueI18n)

export default ({app, store}) => {
    // Set i18n instance on app
    // This way we can use it in middleware and pages asyncData/fetch
    app.i18n = new VueI18n({
        locale: store.state.locale,
        fallbackLocale: store.state.locale,
        messages: {'en-US': require('@/language/en-US.json'),
            'zh-CN': require('@/language/zh-CN.json')
        },
        silentTranslationWarn: true
    })

    app.i18n.path = link => {
        // 如果是默认语言,就省略
        if (app.i18n.locale === app.i18n.fallbackLocale) {return `/${link}`
        }
        return `/${app.i18n.locale}/${link}`
    }
}

3、在 middleware 下创立 `i18n.js

// nuxt.config.js
export default {
    router: {middleware: ['i18n']
    },
}
export default function({isHMR, app, store, route, params, error, redirect}) {
    const defaultLocale = app.i18n.fallbackLocale
    // If middleware is called from hot module replacement, ignore it
    if (isHMR) return
    // Get locale from params
    const locale = params.lang || defaultLocale

    if (store.state.locales.indexOf(locale) === -1) {return error({ message: '页面未找到.', statusCode: 404})
    }
    // Set locale
    // store.commit('SET_LANG', locale)
    app.i18n.locale = store.state.locale
    // If route is /<defaultLocale>/... -> redirect to /...
    if (locale === defaultLocale && route.fullPath.indexOf('/' + defaultLocale) === 0) {const toReplace = '^/' + defaultLocale + (route.fullPath.indexOf('/' + defaultLocale + '/') === 0 ? '/' : '')
        const re = new RegExp(toReplace)
        return redirect(route.fullPath.replace(re, '/'))
    }
}

4、在 store 下创立 index.js

import {getToken} from '@/lib/token.js'
const state = () => ({
    token: '',
    locales: ['en-US', 'zh-CN'],
    locale: 'en-US'
})

const mutations = {setToken(state, token) {state.token = token},
    SET_LANG(state, locale) {if (state.locales.indexOf(locale) !== -1) {state.locale = locale}
    }
}

const actions = {async nuxtServerInit({ commit}, {app}) {let token = getToken(app) || ''commit('setToken', token)
        // 还能够获取一些通用信息,比方个人信息,通用配置什么的
    }
}
export default {
    state,
    actions,
    mutations
}

5、在 language 下创立 en-US.jsonzh-CN.json

更多语言库,请依照规定增加

配置对应的变量属性名称,在页面用

<span>{{$t('变量名') }}</span>

对应 antd-vue 组件库国际化,官网举荐应用 config-provider 组件

// default.vue 页面
<template>
    <a-config-provider :locale="lang">
        <div class="layout-container">
            <a-layout>
                <a-layout-header>header</a-layout-header>
                <a-layout-content><Nuxt /></a-layout-content>
                <a-layout-footer>footer</a-layout-footer>
                <a-back-top />
            </a-layout>
        </div>
    </a-config-provider>
</template>
<script>
import {mapState} from 'vuex'
import language from '../language/antd-lang/index'
import moment from 'moment'
import 'moment/locale/zh-cn'
moment.locale('en')

export default {data() {return {}
    },
    computed: {
        ...mapState({locale: state => state.locale}),
        lang: function() {
            let l = null
            switch (this.locale) {
                case 'zh-CN':
                    l = language.zhCN
                    moment.locale('zh-cn')
                    break
                case 'en-US':
                    l = language.enUS
                    moment.locale('en')
                    break
            }
            return l
        }
    }
}
</script>

language 下创立 antd-lang/index.js, 蕴含所有的反对语言库

// 阿拉伯
import arEG from '~/node_modules/ant-design-vue/es/locale/ar_EG'
// 保加利亚语
import bgBG from '~/node_modules/ant-design-vue/es/locale/bg_BG'
// 加泰罗尼亚语
import caES from '~/node_modules/ant-design-vue/es/locale/ca_ES'
// 捷克语
import csCZ from '~/node_modules/ant-design-vue/es/locale/cs_CZ'
// 德语
import deDE from '~/node_modules/ant-design-vue/es/locale/de_DE'
// 希腊语
import elGR from '~/node_modules/ant-design-vue/es/locale/el_GR'
// 英语
import enGB from '~/node_modules/ant-design-vue/es/locale/en_GB'
// 英语(美式)import enUS from '~/node_modules/ant-design-vue/es/locale/en_US'
// 西班牙语
import esES from '~/node_modules/ant-design-vue/es/locale/es_ES'
// 爱沙尼亚语
import etEE from '~/node_modules/ant-design-vue/es/locale/et_EE'
// 波斯语
import faIR from '~/node_modules/ant-design-vue/es/locale/fa_IR'
// 芬兰语
import fiFI from '~/node_modules/ant-design-vue/es/locale/fi_FI'
// 法语(比利时)import frBE from '~/node_modules/ant-design-vue/es/locale/fr_BE'
// 法语
import frFR from '~/node_modules/ant-design-vue/es/locale/fr_FR'
// 冰岛语
import isIS from '~/node_modules/ant-design-vue/es/locale/is_IS'
// 意大利语
import itIT from '~/node_modules/ant-design-vue/es/locale/it_IT'
// 日语
import jaJP from '~/node_modules/ant-design-vue/es/locale/ja_JP'
// 韩语 / 朝鲜语
import koKR from '~/node_modules/ant-design-vue/es/locale/ko_KR'
// 挪威
import nbNO from '~/node_modules/ant-design-vue/es/locale/nb_NO'
// 荷兰语(比利时)import nlBE from '~/node_modules/ant-design-vue/es/locale/nl_BE'
// 荷兰语
import nlNL from '~/node_modules/ant-design-vue/es/locale/nl_NL'
// 波兰语
import plPL from '~/node_modules/ant-design-vue/es/locale/pl_PL'
// 葡萄牙语 (巴西)
import ptBR from '~/node_modules/ant-design-vue/es/locale/pt_BR'
// 葡萄牙语
import ptPT from '~/node_modules/ant-design-vue/es/locale/pt_PT'
// 斯洛伐克语
import skSK from '~/node_modules/ant-design-vue/es/locale/sk_SK'
// 塞尔维亚
import srRS from '~/node_modules/ant-design-vue/es/locale/sr_RS'
// 斯洛文尼亚
import slSI from '~/node_modules/ant-design-vue/es/locale/sl_SI'
// 瑞典语
import svSE from '~/node_modules/ant-design-vue/es/locale/sv_SE'
// 泰语
import thTH from '~/node_modules/ant-design-vue/es/locale/th_TH'
// 土耳其语
import trTR from '~/node_modules/ant-design-vue/es/locale/tr_TR'
// 俄罗斯语
import ruRU from '~/node_modules/ant-design-vue/es/locale/ru_RU'
// 乌克兰语
import ukUA from '~/node_modules/ant-design-vue/es/locale/uk_UA'
// 越南语
import viVN from '~/node_modules/ant-design-vue/es/locale/vi_VN'
// 简体中文
import zhCN from '~/node_modules/ant-design-vue/es/locale/zh_CN'
// 繁体中文
import zhTW from '~/node_modules/ant-design-vue/es/locale/zh_TW'

export default {
    arEG,
    bgBG,
    caES,
    csCZ,
    deDE,
    elGR,
    enGB,
    enUS,
    esES,
    etEE,
    faIR,
    fiFI,
    frBE,
    frFR,
    isIS,
    itIT,
    jaJP,
    koKR,
    nbNO,
    nlBE,
    nlNL,
    plPL,
    ptBR,
    ptPT,
    skSK,
    srRS,
    slSI,
    svSE,
    thTH,
    trTR,
    ruRU,
    ukUA,
    viVN,
    zhCN,
    zhTW
}

六、scss、less 款式全局援用

SASS: `yarn add sass-loader node-sass`
LESS: `yarn add less-loader less`
Stylus: `yarn add stylus-loader stylus`
yarn add @nuxtjs/style-resources
npm i @nuxtjs/style-resources --save-dev
// nuxt.config.js
export default {buildModules: ['@nuxtjs/style-resources'],
    styleResources: {
        // your settings here
        sass: [],
        scss: [],
        less: [],
        stylus: []},
}
正文完
 0