最近在开发我司一项目,用的是nuxt.js开发的,nuxt版本号:2.14.8。
主要记录一下,我在这个项目中一些用到的东西吧,地址:http://www.lawlawing.com/
感觉基本包含了nuxt.js的大部分配置了。
第一种办法:
此方法可参考我的这篇文章:初识nuxt.js
我的npm 下载太慢了,所以用了第二种办法
npx create-nuxt-app
文档: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
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
nuxt.config.js
中:import { resolve } from 'path'
module.exports = {
alias: {
'img': resolve(__dirname, './assets/images'),
'css': resolve(__dirname, './assets/css'),
},
}
data(){
return{
img:{
logo: require('img/public/logo.png')
}
}
}
文档:https://nuxtjs.org/docs/2.x/configuration-glossary/configuration-alias
// nuxt.config.js
// 这里似乎不能用以上定义的别名路径
css:[
'~/assets/css/global.css'
],
npm i element-ui -S
// 用于按需加载
npm i babel-plugin-component -D
~/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)
}
nuxt.config.js
中引入element-ui.js
:// nuxt.config.js
plugins: [
'~/plugins/element-ui'
],
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
安装
npm i cookie-universal-nuxt -S
在nuxt.config.js
中引入:
modules: [ 'cookie-universal-nuxt',],
在客户端中使用:
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});
在服务端中使用:
应该是服务端中,比如在下面的axios中使用
文档:https://www.npmjs.com/package/cookie-universal-nuxt
安装
npm i @nuxtjs/axios -S
配置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) // 返回接口返回的错误信息
})
}
在nuxt.config.js
中引入
modules: [
'@nuxtjs/axios'
],
plugins: [
'~/plugins/axios'
],
使用
// 页面中:
// 组件中:
文档:https://www.npmjs.com/package/@nuxtjs/axios
文档:http://www.axios-js.com/zh-cn/docs/nuxtjs-axios.html
npm i cross-env -D
// ~/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"},
nuxt.config.js
中配置env:export default { env:{ MODE: process.env.MODE },}
创建在各个环境下的接口地址的文件:
// ~/plugins/env.jsmodule.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" }}
创建返回当前环境接口地址的文件:
// ~/plugins/host.jsconst env = require('./env')// 接口export const API = env[process.env.MODE].API;// Cookieexport const CookieDomain = env[process.env.MODE].Cookie_Domain;
使用:
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;
新标签页打开
编程式:
let routeData = this.$router.resolve({ path: "/detail/1",});window.open(routeData.href, '_blank');
event.stopPropagation();
现行有效
this.$refs.searchInput.focus()
mounted() { this.$nextTick(() => { this.$refs.searchInput.focus() });}
@keyup.enter.native=“toSearch”
手机号码:
// 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('密码不能为空')); }};// formregister:{ password:'', confirmPassword: ''},// rulespassword: [{ required: true, message: '请输入注册密码', trigger: 'blur'},{validator: checkPassword, trigger: 'change'}], confirmPassword: [{ required: true, message: '请确认注册密码', trigger: 'blur'},{validator: checkConfirmPassword, trigger: 'change'}],
// demo
// 我遇到的是:不加key,dom可以切换成功,但是表单验证呀、绑定的数据不能切换;
我的部署环境是 ubuntu+nginx+node14.x+pm2
服务器安装环境
安装Nginx
sudo apt-get install nginx
安装node
参考:ubuntu系统下安装/卸载最新版Node、NPM
安装pm2
npm i pm2 -g
编写部署配置文件:配置程序以集群方式部署
在程序根路径下新建文件: ~/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 // 是否自动重启 } ]}
打包,上传到服务器
打包
npm run build
上传服务器
将打包后的: .nuxt
,static
,ecosystem.config.js
,nuxt.config.js
,package.json
五个文件/夹 上传到服务器中的程序目录就可以了。
下载依赖, pm2运行程序
在刚才上传程序文件的文件下,安装依赖
npm i
安装完依赖后, 使用pm2启动程序
pm2 start
两步都是在程序文件的根目录下进行
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端口
Tinymce
编辑器Nuxt.js是一个服务端渲染框架。在一开始项目中使用的是quill.js编辑器,因其支持服务端渲染,但后期其功能过于少,故选择了非常强大的tinymce编辑器。
npm i @tinymce/tinymce-vue tinymce -s
在~/static/目录下创建tinymce文件夹,下载完tinymce后在node_modules 中找到 tinymce/skins目录,将其复制到static/tinymce目录。
下载中文语言包。
下载解压后,把langs文件夹放到~/static/tinymce/下。
在~/components/下创建 tinymceEditor.vue文件。
template
script
import editor from '@tinymce/tinymce-vue';
import toolbar from "./toobar"; // toolbar
import plugins from "./plugins"; // plugins
import {imageHost} from "../../../plugins/host";
let tinymce;
// 在客户端环境下引入
if (process.client) {
tinymce = require('tinymce/tinymce');
require('tinymce/themes/silver');
require('tinymce/icons/default');
require('tinymce/plugins/image');// 插入上传图片插件
require('tinymce/plugins/media');// 插入视频插件
require('tinymce/plugins/table');// 插入表格插件
require('tinymce/plugins/lists');// 列表插件
require('tinymce/plugins/link');//超链接插件
require('tinymce/plugins/wordcount');// 字数统计插件
// require('tinymce/plugins/emoticons');// 插入表情插件
require('tinymce/plugins/fullscreen');
require('tinymce/plugins/code');
require('tinymce/plugins/paste');
require('tinymce/plugins/advlist');
require('tinymce/plugins/autolink');
require('tinymce/plugins/autosave');
require('tinymce/plugins/codesample');
require('tinymce/plugins/colorpicker');
require('tinymce/plugins/contextmenu');
require('tinymce/plugins/directionality');
require('tinymce/plugins/nonbreaking');
require('tinymce/plugins/insertdatetime');
require('tinymce/plugins/preview');
require('tinymce/plugins/print');
require('tinymce/plugins/save');
require('tinymce/plugins/searchreplace');
require('tinymce/plugins/spellchecker');
require('tinymce/plugins/tabfocus');
require('tinymce/plugins/table');
require('tinymce/plugins/template');
require('tinymce/plugins/textcolor');
require('tinymce/plugins/visualblocks');
require('tinymce/plugins/textpattern');
require('tinymce/plugins/visualchars');
require('tinymce/plugins/wordcount');
require('tinymce/plugins/anchor');
require('tinymce/plugins/hr');
require('tinymce/plugins/link');
require('tinymce/plugins/noneditable');
require('tinymce/plugins/pagebreak');
}
export default {
name: "tinymce-editor",
components:{editor},
// 接收引用此组件的值
props: ['modifyContent'],
data() {
return {
// 图片地址前缀
imageHost:imageHost(),
//初始化配置
init: {
language_url: '/tinymce/langs/zh_CN.js',// 语言包的路径
language: 'zh_CN',//语言
skin_url: '/tinymce/skins/ui/oxide',// skin路径
height: 800,//编辑器高度
branding: false,//是否禁用“Powered by TinyMCE”
menubar: true,//顶部菜单栏显示
object_resizing: false,// 是否禁用表格图片大小调整
autosave_ask_before_unload:false, // 去除关闭/刷新网页时弹出对话框
plugins: plugins,
toolbar: toolbar,
body_class: "panel-body ",
end_container_on_empty_block: true,
powerpaste_word_import: "clean",
code_dialog_height: 450,
code_dialog_width: 1000,
advlist_bullet_styles: "square",
advlist_number_styles: "default",
imagetools_cors_hosts: ["www.tinymce.com", "codepen.io"],
// 自定义字体集
theme_advanced_fonts:
"宋体=宋体;微软雅黑=微软雅黑;新宋体=新宋体;Courier New=courier new,courier,monospace;AkrutiKndPadmini=Akpdmi-n",
// 自定义字号
fontsize_formats: "8pt 10pt 12pt 14pt 18pt 24pt 36pt",
content_css:'/tinymce/skins/content/default/content.css',
paste_data_images: true, // 允许粘贴图像
// 自定义字体
font_formats: `
微软雅黑=微软雅黑;
宋体=宋体;
黑体=黑体;
仿宋=仿宋;
楷体=楷体;
隶书=隶书;
幼圆=幼圆;
思源黑体CN=思源黑体CN;
Andale Mono=andale mono,times;
Arial=arial, helvetica,
sans-serif;
Arial Black=arial black, avant garde;
Book Antiqua=book antiqua,palatino;
Comic Sans MS=comic sans ms,sans-serif;
Courier New=courier new,courier;
Georgia=georgia,palatino;
Helvetica=helvetica;
Impact=impact,chicago;
Symbol=symbol;
Tahoma=tahoma,arial,helvetica,sans-serif;
Terminal=terminal,monaco;
Times New Roman=times new roman,times;
Trebuchet MS=trebuchet ms,geneva;
Verdana=verdana,geneva;
Webdings=webdings;
Wingdings=wingdings,zapf dingbats`,
content_style: `
* { padding:0; margin:0; }
html, body { height:100%; }
img { max-width:100%; display:block;height:auto; }
a { text-decoration: none; }
iframe { width: 100%; }
p { line-height:1.6; margin: 0px; font-size: 16px; font-family:微软雅黑}
table { word-wrap:break-word; word-break:break-all; max-width:100%; border:none; border-color:#999; }
.mce-object-iframe { width:100%; box-sizing:border-box; margin:0; padding:0; }
ul,ol { list-style-position:inside; }
body, td, pre {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 12px;
}
`,
style_formats: [
{
title: "首行缩进",
block: "p",
styles: { "text-indent": "2em" }
},
{
title: "行高",
items: [
{ title: "1", styles: { "line-height": "1" }, inline: "span" },
{
title: "1.5",
styles: { "line-height": "1.5" },
inline: "span"
},
{ title: "2", styles: { "line-height": "2" }, inline: "span" },
{
title: "2.5",
styles: { "line-height": "2.5" },
inline: "span"
},
{ title: "3", styles: { "line-height": "3" }, inline: "span" }
]
}
],
default_link_target: "_blank",
link_title: false,
convert_urls: false, // 图片上传路径为绝对路径
remove_script_host: false,
paste_word_valid_elements: "*[*]",
paste_convert_word_fake_lists: false,
paste_webkit_styles: "all",
paste_merge_formats: true,
nonbreaking_force_tab: false,
paste_auto_cleanup_on_paste: false,
forced_root_block: "p",
force_p_newlines: true,
importcss_append: true,
tabfocus_elements: ":prev,:next",
// 本地图片上传配置
images_upload_handler: (blobInfo, success, failure) => {
let params = new FormData();
params.append("image", blobInfo.blob());
this.$axios.post("/upload_image?random="+Math.random(), params)
.then(res=>{
if(res.data.code == 0){
success( this.imageHost + res.data.data)
} else {
failure("上传失败")
}
})
.catch(()=>{
failure("上传失败")
})
},
setup: (editor) => {
// 监听编辑器失焦事件
var _this = this;
editor.on('blur', function () {
_this.$emit('saveDraft')
})
},
},
// 绑定的内容
contents: this.modifyContent
}
},
mounted(){ // 用process.client判断一下环境再执行
this.$nextTick(()=>{
if (process.client) {
window.tinymce.init({});
}
})
},
watch: {
modifyContent(newValue) {
this.contents = newValue
},
contents(newValue) {
this.$emit('writeContent', newValue);
}
}
}
欢迎访问旗渡法律翻译来查看最早效果: https://www.qidufanyi.com
另:承接各种翻译业务,包括网站翻译。
原文地址:https://blog.zhanghaoran.ren/article/html/nuxt.jsChangJianWenTiZongJie.html