金法条前端笔记

最近在看完我司一项目,用的是nuxt.js开发的,nuxt版本号:2.14.8。

主要记录一下,我在这个项目中一些用到的东西吧。

感觉基本包含了nuxt.js的大部分配置了。

安装

第一种办法:

// 此方法可参考我的这篇文章:初识nuxt.js

// 我的npm 下载太慢了,所以用了第二种办法

npx create-nuxt-app <project-name>

文档:https://nuxtjs.org/docs/2.x/configuration-glossary/configuration-server

第二种办法:

// 1. 全局安装@vue/cli,已安装的可忽略
> npm i @vue/cli -g
// 2. 拉取nuxt模板
> vue init nuxt/starter {project-name}

// 如下显示则为安装完毕
? Project name project-name
? Project description Nuxt.js project
? Author zhanghaoran <zhanghaoran.rem@qq.com>

   vue-cli · Generated "project-name".

   To get started:

     cd project-name
     npm install # Or yarn
     npm run dev

配置启动端口

同是以本机9363端口启动

第一种办法:

// package.json
{
    ...
    "config": {
        "nuxt": {
            "host": "0.0.0.0",
            "port": "9363"
        }
    }
}

第二种办法:

// nuxt.config.js
export default {
  server: {
    port: 9363, // default: 3000
    host: '0.0.0.0', // default: localhost,
    timing: false
  }
}

文档:https://nuxtjs.org/docs/2.x/configuration-glossary/configuration-server

配置文件别名(alias)

  1. nuxt.config.js中:
import { resolve } from 'path'

module.exports = {
    alias: {
        'img': resolve(__dirname, './assets/images'),
        'css': resolve(__dirname, './assets/css'),
    },
}
  1. 在组件和页面中使用:
data(){
    return{
        img:{
            logo: require('img/public/logo.png')
        }
    }
}

<style scoped>
    @import "css/global.css";
</style>

文档:https://nuxtjs.org/docs/2.x/configuration-glossary/configuration-alias

全局css

// nuxt.config.js
// 这里似乎不能用以上定义的别名路径
css:[
    '~/assets/css/global.css'
],

element-ui按需引入

  1. 下载element-ui与babel
npm i element-ui -S
// 用于按需加载
npm i babel-plugin-component -D
  1. ~/plugins/下创建element-ui.js
// ~/plugins/element-ui.js

import Vue from 'vue'
import { Input, Select, Button, Option } from 'element-ui'

export default ()=>{
    Vue.use(Input)
    Vue.use(Select)
    Vue.use(Button)
    Vue.use(Option)
}
  1. nuxt.config.js中引入element-ui.js:
// nuxt.config.js
plugins: [
    '~/plugins/element-ui'
],
  1. nuxt.cofnig.js中配置按需加载
// nuxt.confg.js
build: {
    vendor: ['element-ui'],
    babel:{
        plugins: [
            ["component", 
                {"libraryName": "element-ui", "styleLibraryName": "theme-chalk"}
            ]
        ]
    },
}

文档:https://element.eleme.cn/#/zh-CN/component/quickstart

  1. 安装

    npm i cookie-universal-nuxt -S
    
  2. nuxt.config.js中引入:

    modules: [
        'cookie-universal-nuxt',
    ],
    
  3. 在客户端中使用:

    const path = "/";
    // 20天
    const expires = new Date(new Date() * 1 + 86400000 * 20);
    const tokenName = 'token';
    
    this.$cookies.set(tokenName, "token", {path: path, domain: CookieDomain, expires: expires});
    this.$cookies.remove(tokenName, {path:path, domain: CookieDomain});
    
  4. 在服务端中使用:

    应该是服务端中,比如在下面的axios中使用

文档:https://www.npmjs.com/package/cookie-universal-nuxt

nuxt-axios

  1. 安装

    npm i @nuxtjs/axios -S
    
  2. 配置axios

    // ~/plugins/axios.js
    
    export default function ({redirect, req, app: { $axios, $cookies }})  {
        $axios.defaults.baseURL = "http://xxx.com";
        $axios.onRequest(config => {
            config.headers.common['Authorization'] = $cookies.get('token');
        });
    
        $axios.interceptors.response.use(
            response => {
                // return response
                if(response.data.code == 401){
                    // TODO: 清楚本地用户数据, 并重定向到登录页面
                }else if(response.data.code == 404){
                    // TODO: 接口404
                }else if(response.data.code == 0){
                    return response.data.data
                }else{
                    return Promise.reject(response)
                }
            },
            error => {
                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)   // 返回接口返回的错误信息
            })
    }
    
  3. nuxt.config.js中引入

    modules: [
        '@nuxtjs/axios'
    ],
    plugins: [
        '~/plugins/axios'
    ],
    
  4. 使用

    // 页面中:
    
    // 组件中:
    

文档:https://www.npmjs.com/package/@nuxtjs/axios

文档:http://www.axios-js.com/zh-cn/docs/nuxtjs-axios.html

环境变量

  1. 下载安装
npm i cross-env -D
  1. 配置启动环境变量
// ~/package.json

"scripts": {
    "dev": "cross-env MODE=development nuxt",
    "build:test": "cross-env MODE=test nuxt build",
    "start:test": "cross-env MODE=test nuxt start",
    "build": "cross-env MODE=production nuxt build",
    "start": "cross-env MODE=production nuxt start",
    "generate": "nuxt generate"
},
  1. nuxt.config.js 中配置env:
export default {
    env:{
        MODE: process.env.MODE
    },
}
  1. 创建在各个环境下的接口地址的文件:

    // ~/plugins/env.js
    
    module.exports = {
        // 开发环境
        development: {
            MODE: 'development',
            API: 'development',
            Cookie_Domain: "development"
        },
        // 测试环境
        test:{
            MODE: 'test',
            API: 'test',
            Cookie_Domain: "test"
        },
        // 线上环境
        production: {
            MODE: 'production',
            API: 'production',
            Cookie_Domain: "production"
        }
    }
    
  2. 创建返回当前环境接口地址的文件:

    // ~/plugins/host.js
    
    const env = require('./env')
    
    // 接口
    export const API = env[process.env.MODE].API;
    // Cookie
    export const CookieDomain = env[process.env.MODE].Cookie_Domain;
    
  3. 使用:

    import {CookieDomain} from "../plugins/host";
    
    // 此时,当前系统在开发环境则返回:development;
    console.log(CookieDomain)
    this.$cookies.set(tokenName, token, {domain: CookieDomain});
    

一些优化项配置

// nuxt.config.js

module.exports = {
    render: {
        // 解决nuxt项目首屏加载全部js
        resourceHints: false,
    },
    build: {
        analyze: false,        // 可视化打包结果
        // css文件在测试与生产环境下外部引入
        extractCSS: process.env.MODE === 'development' ? false : true,
        // 在开发环境下生成sourcemap
        productionSourceMap: process.env.MODE === 'development' ? true : false,
        // gzip打开
        productionGzip: true,
        // gzip的对象
        productionGzipExtensions: ['js', 'css', 'svg', 'png'],
        // element-ui按需引入
        // ... 此处省略,上面有
    },
}

单行文本与多行文本溢出显示省略号

单行文本

width:300px;    
overflow: hidden;    
text-overflow:ellipsis;    
whitewhite-space: nowrap; 

多行文本

display: -webkit-box;    
-webkit-box-orient: vertical;    
-webkit-line-clamp: 3;    
overflow: hidden;
  1. <nuxt-link to="detail" target="_blank">新标签页打开</nuxt-link>
    
  2. 编程式:

    let routeData = this.$router.resolve({
        path: "/detail/1",
    });
    window.open(routeData.href, '_blank');
    

阻止冒泡事件

event.stopPropagation();

<template>
    <div class="contentItem" @click="toDetail()">
        <div class="sign"><span>现行有效</span></div>
        <div class="download" @click="download($event)"></div>
        </div>
    </div>
</template>

<script>
    export default {
        name: "contentItem",
        methods:{
            download(event){
                // 阻止冒泡
                event.stopPropagation();
                console.log('download')
            },
            toDetail(){
                console.log('detail')
            }
        }
    }
</script>

输入框默认聚焦

this.$refs.searchInput.focus()

mounted() {
    this.$nextTick(() => {
        this.$refs.searchInput.focus()
    });
}

el-input回车提交事件

@keyup.enter.native=”toSearch”

<el-input placeholder="请输入您要检索的关键字" v-model="query" class="input-with-select" ref="searchInput" @keyup.enter.native="toSearch">
</el-input>

自定义表单验证规则

手机号码:

// data()
var isMobile = /^1[3|4|5|6|7|8|9][0-9]\d{8}$/.test(value)
var checkPhone = (rule, value, callback) => {
    if (!value) {return callback(new Error('请输入手机号码'));}
    else {
        if (isMobile.test(value)) {callback();
        } else {return callback(new Error('请输入正确的手机号'));}
    }
};

// rules
mobile: [{validator: checkPhone, trigger: 'blur'}],

验证码:

// data()
var isVerCode = /^\d{6}$/
var checkCode = (rule, value, callback) =>{
    if(!value){return callback(new Error('请输入6位验证码'))}
    else {
        if (isVerCode.test(value)) {callback();
        } else {return callback(new Error('请输入正确的验证码'));}
    }
};
// rules
verificationCode: [{validator: checkCode, trigger: 'blur'}],

密码: 最少6位、两次输入密码一致

// data()
var checkPassword = (rule, value, callback) =>{
    if(this.register.password != ''){
        if(this.register.password.length >= 6){
            if(this.register.confirmPassword == this.register.password){
                callback();
            }else{
                return callback(new Error('两次密码不一致'));
            }
        }else{
            return callback(new Error('密码长度6位以上'));
        }
    }else {
        return callback(new Error('密码不能为空'));
    }
};
var checkConfirmPassword = (rule, value, callback) =>{
    if(this.register.confirmPassword != ''){
        if(this.register.confirmPassword.length >= 6){
            if(this.register.confirmPassword == this.register.password){
                callback();
            }else{
                return callback(new Error('两次密码不一致'));
            }
        }else{
            return callback(new Error('密码长度6位以上'));
        }
    }else {
        return callback(new Error('密码不能为空'));
    }
};

// form
register:{
    password:'',
    confirmPassword: ''
},


// rules
password: [{ required: true, message: '请输入注册密码', trigger: 'blur'},{validator: checkPassword, trigger: 'change'}],
                    confirmPassword: [{ required: true, message: '请确认注册密码', trigger: 'blur'},{validator: checkConfirmPassword, trigger: 'change'}],

v-if时记得加 :key

// demo
// 我遇到的是:不加key,dom可以切换成功,但是表单验证呀、绑定的数据不能切换;
<template>
    <div v-if="loginType === 'Password'" :key="loginType">

    </div>

    <div v-if="loginType === 'Code'" :key="loginType">

    </div>

    <button @click="changeLoginType('Password')">切换为密码登录<button>
    <button @click="changeLoginType('Code')">切换为验证码登录<button>
</template>

<script>
    export defalt {
            data(){
                return{
                    loginType: Password
                }
            }

        methods:{
            changeLoginType(loginType){
                this.loginType = loginType
            }
        }
    }
</script>

部署

我的部署环境是 ubuntu+nginx+node41.x+pm2

  1. 服务器安装环境

    安装Nginx

    sudo apt-get install nginx
    

    安装node

    参考:ubuntu系统下安装/卸载最新版Node、NPM

    安装pm2

    npm i pm2 -g
    
  2. 编写部署配置文件:配置程序以集群方式部署

    在程序根路径下新建文件: ~/ecosystem.config.js

    module.exports = {
        apps: [
            {
                name: 'lawlawing',                // 程序名称,自己修改
                exec_mode: 'cluster',            // 模式为集群模式,更多参考pm2文档
                instances: 'max', // Or a number of instances
                script: './node_modules/nuxt/bin/nuxt.js',
                args: 'start',
                env: {
                    "PORT": 9363,                // 启动端口
                    "HOST": "0.0.0.0"
                },
                max_memory_restart: "1000M",        // 最大内存重启
                autorestart: true                    // 是否自动重启
            }
        ]
    }
    
  3. 打包,上传到服务器

    打包

    npm run build
    

    上传服务器

    将打包后的: .nuxt,static,ecosystem.config.js,nuxt.config.js,package.json五个文件/夹 上传到服务器中的程序目录就可以了。

  4. 下载依赖, pm2运行程序

    在刚才上传程序文件的文件下,安装依赖

    npm i
    

    安装完依赖后, 使用pm2启动程序

    pm2 start
    

    两步都是在程序文件的根目录下进行

  5. nginx转发配置

    // 切换到ngxin目录并编辑(我这里直接在nginx.config中添加了,也可以在sites-enabled中添加)
    cd /etc/nginx 
    vim nginx.config
    

    配置

    map $sent_http_content_type $expires {
        "text/html"                 epoch;
        "text/html; charset=utf-8"  epoch;
        default                     off;
    }
    
    server {
        listen 80;
        server_name domain.com;
    
        location / {
            expires $expires;
            proxy_redirect                      off;
            proxy_set_header Host               $host;
            proxy_set_header X-Real-IP          $remote_addr;
            proxy_set_header X-Forwarded-For    $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto  $scheme;
            proxy_read_timeout          1m;
            proxy_connect_timeout       1m;
                // 因为我在第二步配置文件中写的是以9363端口启动程序,所以这里转发9363
            proxy_pass                          http://127.0.0.1:9363;
        }
    
    }
    

    服务器安全组记得开80/443端口

最后,感谢观看!