关于vue-cli:vuecli4版本如何快速优化性能

注意事项:1、vue-cli4版本测试环境无奈打包出带有hash值的文件名,解决办法: 即使设置filenameHashing:true,也是有效的,vue-cli4版本是认准NODE_ENV='production',如果想执行 npm run build:stage【指令对应环境变量文件是env.staging】,须要设置NODE_ENV='production'优化次要步骤:1、应用插件compressionPlugin进行gzip进行压缩,成果很显著 装置 npm install --save-dev compression-webpack-plugin如果装置失败,指定版本npm install --save-dev [email protected]const CompressionWebpackPlugin = require('compression-webpack-plugin');chainWebpack(config) { config.plugin('compressionPlugin').use( new CompressionWebpackPlugin({ test: /\.(js|css|json|ico|svg)$/,// 匹配文件格式 algorithm: 'gzip', threshold: 10240, // 对超过10k的数据压缩 minRatio: 0.8, // 压缩比 deleteOriginalAssets: false //是否删除源文件 }) );}nginx配置,间接粘贴在http {} 外面 gzip on; #其余属性不必,这个肯定要开,开启浏览器压缩申请 gzip_buffers 4 16k; # 压缩响应的缓冲区的数量和大小 gzip_comp_level 9; # 响应压缩的级别,1-9,数字越大压缩得越好,但越耗时间 gzip_http_version 1.1; # 默认1.1,所需的最小HTTP版本 gzip_min_length 1k; # 压缩最小大小,小于该值的文件不会被压缩 gzip_types text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php application/javascript application/json; gzip_disable "MSIE [1-6]\."; gzip_vary on; 2、应用vue-cli4自带的splitChunks来分隔代码,会对公共模块进行抽取 ...

October 28, 2022 · 1 min · jiezi

关于vue-cli:解决在elementui中使用Container-布局容器时出现白边问题

环境架构vue2 + vue-cli + element-ui 构建 问题背景在应用element-ui的Container布局容器编写基于vue-cli环境下的前端页面时发现在浏览器周围别离有白边生成如图 问题剖析受【简书】解决vue element-ui body页面默认边距- @web28的启发,应用f12关上控制台察看其初始style,发现body中具备8px的外边距款式 须要留神的是察看控制台中的8px款式是加在bady中的,故若打消白边只能将body中的margin置0px,而无奈通过设置<template>下的根元素style打消 问题解决依据控制台中的展现,只有在body中增加margin: 0px款式即可解决白边问题 代码: <template> <div id="app" > 1111111 </div></template><script>export default { name: 'App',}</script><style> body{ margin: 0px; }#app { background-color: red;}</style>效果图: 问题思考本来认为白边是element-ui生成的,然而应用npm uninstall elementui装配掉element后仍然存在该style,初步判断是vue生成的,然而生成起因不详,如果有大佬晓得其中一二,欢送评论 参考资料【简书】解决vue element-ui body页面默认边距- @web28 https://www.jianshu.com/p/877a4a24dd6c

September 28, 2022 · 1 min · jiezi

关于vue-cli:vuecliservice-command-not-found报错引发的血案

最近因为工作须要,开始学习vue,于是在github上找了一个star数比拟高的我的项目 ant-design-vue-pro 筹备练手。我的项目克隆下来后,用 vscode 关上工程,并且应用了 vscode 自带的终端装置了依赖包,然而筹备执行 yarn serve 启动工程的时候却意外的抛出了一个谬误: $ vue-cli-service serve /bin/sh: vue-cli-service: command not founderror Command failed with exit code 127.刚开始看到这个报错示意情绪还是很平静的,毕竟大风大浪见得多了,首先想到的是不是依赖包没有装置胜利? 于是把 node_modules 目录和 yarn.lock 文件删了从新装依赖包,重新启动发现仍然报错。思考了下开始狐疑是不是应用 yarn 装置依赖包的问题,于是换了 npm 和 pnpm 进行依赖包的装置,后果仍然是启动报错。 嘿嘿,到这里其实就开始感觉这个问题不简略了,狐疑这么重大的问题必定不是我一个人遇到过,通过一番Google检索,发现的确有人遇到过相似的问题,提出了如下几种解决办法: 删除 node_modules 和 lock 文件,重新安装依赖包应用npm装置依赖包,不要应用yarn既然报错 vue-cli-service 这个命令找不到,那就全局装置 npm install -g vue-cli-service办法一和办法二下面其实曾经尝试过了,是不行的,办法三尽管可能可行,然而显然全局装置 vue-cli-service 不是最优解。 于是开始尝试本人思考为什么启动报错? 首先须要弄明确执行 yarn serve 到最终脚手架工程启动都执行了哪些操作? 当咱们在工程目录下的终端执行 yarn serve 时,首先会去工程根目录下的 package.json 中的 scripts 字段查问是否有可执行的脚本,ant-design-vue-pro 是这么写的: { "scripts": { "serve": "vue-cli-service serve" }}当运行 yarn serve 就相当于执行的是 vue-cli-service serve,这个时候 nodejs 会尝试在 node_modules 下的 .bin 目录下查问 vue-cli-service 可执行性文件,如果找不到就会去全局装置的 node_modules 下查问可执行文件,如果还是找不到的话就会报错 command not found。 ...

September 7, 2022 · 2 min · jiezi

关于vue-cli:vueconfigjs常用配置

记录一下我遇到过得vue.config.js配置项,以及过后用到它们的起因。publicPathmodule.exports = { publicPath: process.env.NODE_ENV === 'production' ? '/vue/' : '/',}如果你的域名为 https://www.iicoom.top,如果生成环境 https://www.iicoom.top/ 这个门路曾经被其余我的项目占用,想要从https://www.iicoom.top/vue/ 这个门路拜访,那么进行下面的配置就能够实现。 configureWebpackremove log平时我的项目开发调试的时候免不了会有一些调试,打印一些log。当我的项目上线时去手动移除这些log可能是比拟麻烦的事件,有了上面这个配置,当咱们应用 npm run build// oryarn build之后,编译后的代码部署到线上环境,关上控制台就是清清爽爽的样子。 module.exports = { configureWebpack: config => { // 生产环境勾销 console.log if (process.env.NODE_ENV === 'production') { config.optimization.minimizer[0].options.terserOptions.compress.warnings = false config.optimization.minimizer[0].options.terserOptions.compress.drop_console = true config.optimization.minimizer[0].options.terserOptions.compress.drop_debugger = true config.optimization.minimizer[0].options.terserOptions.compress.pure_funcs = ['console.log'] } }}resolve过后我的项目中引入了一个富文本编辑器,叫 summernote。它依赖 bootstrap 和 jQuery,装置依赖后依然提醒 jquery 没有装置,于是进行了上面的配置,问题解决。 const path = require('path');module.exports = { // 选项... configureWebpack: { resolve: { alias: { 'jquery': path.resolve(__dirname, './node_modules/jquery/src/jquery'), 'jQuery': path.resolve(__dirname, './node_modules/jquery/src/jquery') } } }}

May 11, 2022 · 1 min · jiezi

关于vue-cli:关于使用vue集成Ant-Design-Vue因版本变化导致的问题

author: Nathanniedate: 2022年5月9日17:47:56 问题背景环境参数: "dependencies": { "ant-design-vue": "^2.0.0-rc.3", "vue": "^3.0.0", "vue-router": "^4.0.0-0", "vuex": "^4.0.0-0"},依照视频操作,集成 Ant Design Vue ,引入按钮款式组件,发现款式(色彩)不失效。 预期成果:实际效果: 能够看到色彩红色不失效 。 问题剖析通过一系列的查看,发现是官网代码书写有误官网给的代码(有误): <a-button danger :size="size">Danger</a-button>正确状况的代码: <a-button type="danger" ghost>Danger</a-button>剖析:没有增加type=""属性。 问题呈现在danger款式都没有增加type=""图1图2 ⭐精确的起因是学习视频中展现的官网应用的Ant Design Vue教程版本是2.0.0.rc.2。 而danger款式作为类型是在2.2.0之后,所以就视频中的版本,应用danger必须应用属性的形式,即type="danger"。而以后学习工夫,官网版本变为2.2.8,而本地版本是"ant-design-vue": "^2.0.0-rc.3",,所以间接应用类型形式是不反对的。 问题解决如果装置ant-design-vue<2.2.0,则必须应用type="danger"。如果装置ant-design-vue>2.2.0,则能够应用danger。 # <2.2.0<a-button type="danger" >Default</a-button># > 2.2.0<a-button danger >Default</a-button>相干参考https://2x.antdv.com/componen...https://www.itxst.com/ant-des...

May 9, 2022 · 1 min · jiezi

关于vue-cli:Vue-Cli引入axios

将 axios 绑定到 vue 原型上npm install axiosmain.js中导入并绑定import Vue from 'vue'import App from './App'import axios from 'axios'Vue.prototype.$axios = axiosnew Vue({ el: '#app', components: { App }, template: '<App/>'})调用<template> <div id="app"> <button @click="hello">点击</button> </div></template><script>export default { name: "App", methods: { hello() { // this.$axios({ // method: "get", // url: "http://localhost:1313/hello" // }).then(res => { // console.log(res.data); // }); this.$axios.get("http://localhost:1313/hello").then(response => { console.log(response.data); }); } }};</script><style></style>应用 vue-axiosnpm install --save axios vue-axiosmain.js 中装置import Vue from 'vue'import App from './App'import axios from 'axios'import VueAxios from 'vue-axios'// VueAxios 与 axios 的地位不能替换,否则呈现 TypeError: Cannot read property 'protocol' of undefinedVue.use( VueAxios , axios)new Vue({ el: '#app', components: { App }, template: '<App/>'})调用<template> <div id="app"> <button @click="handleClick">点击</button> </div></template><script>export default { name: "App", methods: { handleClick() { // this.axios({ // method: "get", // url: "http://localhost:8081/hello" // }).then(res => { // console.log(res.data); // }); this.axios.get("http://localhost:8081/hello").then(response => { console.log(response.data); }); } }};</script><style></style>post申请this.axios({ method: "post", url: "http://localhost:8081/hello", data: { username: "admin", password: "123" }}).then((res)=>{ console.log(res.data);})

April 26, 2022 · 1 min · jiezi

关于vue-cli:vuecli-slot的使用

<template> <div> <div class="crumbs"> <el-breadcrumb separator="/"> <el-breadcrumb-item> <i class="el-icon-lx-cascades"></i> 体系配置 </el-breadcrumb-item> </el-breadcrumb> </div> <div class="container" v-if="hasObject('options')"> <div class="handle-box"> <el-form @submit.native.prevent> <el-input v-model="query.keyword" placeholder="id" class="handle-input mr10" @keyup.enter.native="search" > </el-input> <el-select v-model="query.tab" placeholder="类别" class="handle-select mr10" > <el-option key="" label="全副" value="">全副</el-option> <el-option v-for="(item, key) in options.checkSystemTab" :key="key" :label="item" :value="key" > {{ item }} </el-option> </el-select> <el-select v-model="query.tpl" placeholder="模板" class="handle-select-tpl mr10" > <el-option v-for="(item, key) in options.webConfigKV['tpl']" :key="key" :label="item" :value="key" > {{ item }} </el-option> </el-select> <el-button type="primary" icon="el-icon-search" @click="search" >搜寻</el-button > <el-button type="primary" @click="addCheck">增加</el-button> <el-button type="primary" @click="eximportVisible = true" >导入导出</el-button > <el-button type="primary" @click="referVisible = true">查看参考</el-button> </el-form> </div> <el-table :data="tableData" :cell-style="{ background: '#fff' }" border tooltip-effect="dark" style="width: 100%" > <el-table-column prop="id" label="ID" width="100" align="center" ></el-table-column> <el-table-column prop="control" label="管制项" min-width="200" ></el-table-column> <el-table-column prop="desc" label="形容" width="250"></el-table-column> <el-table-column prop="purpose" label="查看目标" width="250" ></el-table-column> <el-table-column label="类别" width="100"> <template slot-scope="scope"> {{ options.checkSystemTab[scope.row.tab] || "" }} </template> </el-table-column> <el-table-column label="操作" width="180" align="center"> <template slot-scope="scope"> <el-button type="text" icon="el-icon-edit" @click="editCheck(scope.row.id, 'edit')" ></el-button> <el-button type="text" icon="el-icon-view" :title="'预览法律依据[' + scope.row.id + ']'" @click="editCheck(scope.row.id, 'previewLaw')" > </el-button> <el-button type="text" icon="el-icon-view" :title="'预览规范根据[' + scope.row.id + ']'" @click="editCheck(scope.row.id, 'previewStandard')" ></el-button> <el-button type="text" icon="el-icon-close" title="删除" @click="removeCheck(scope.row.id)" ></el-button> </template> </el-table-column> </el-table> <div class="pagination"> <el-pagination background layout="total, prev, pager, next" :current-page="parseInt(query.page) || 0" :page-size="parseInt(query.limit) || 0" :total="parseInt(query.total) || 0" @current-change="toPage" > </el-pagination> </div> </div> <el-dialog :title="dialogTitle" :visible.sync="popVisible" v-if="popVisible" width="80%"> <el-form :ref="pageName" :rules="rules" :model="check" label-width="100px" > <el-form-item label="ID" prop="id"> <el-input v-model="check.id"></el-input> </el-form-item> <el-form-item label="管制项" prop="control"> <el-input v-model="check.control"></el-input> </el-form-item> <el-form-item label="形容" prop="desc"> <el-input v-model="check.desc"></el-input> </el-form-item> <el-form-item label="查看目标" prop="purpose"> <el-input v-model="check.purpose"></el-input> </el-form-item> <el-form-item label="危险条件" prop="dangerConditions"> <TableDangerCondition :options="options" :instance="check"> </TableDangerCondition> </el-form-item> <el-form-item label="存在条件" prop="conditions"> <el-input :value="JSON.stringify(check.conditions)" @input="handleChange($event, 'conditions')" ></el-input> </el-form-item> <el-form-item label="相干问题" prop="source"> <el-input :value="JSON.stringify(check.source)" @input="handleChange($event, 'source')" ></el-input> </el-form-item> <el-form-item label="类别" prop="tab"> <el-select v-model="check.tab" width="100"> <el-option v-for="(item, key) in options.checkSystemTab" :key="key" :value="key" :label="item" >{{ item }}</el-option ></el-select > </el-form-item> <el-form-item label="规范根据" prop="standard"> <Editor :content="check.standard" ref="standardEditor"></Editor> </el-form-item> <el-form-item label="法律依据" prop="law"> <Editor :content="check.law" ref="lawEditor"></Editor> </el-form-item> <el-form-item label="模板" prop="tpl"> <el-select v-model="check.tpl" class="handle-select-tpl"> <el-option v-for="(item, key) in options.webConfigKV['tpl']" :key="key" :value="key" :label="item" >{{ item }}</el-option ></el-select > </el-form-item> </el-form> <span slot="footer" class="dialog-footer"> <el-button @click="popVisible = false">取 消</el-button> <el-button type="primary" @click="saveCheck">确 定</el-button> </span> </el-dialog> <el-dialog title="预览法律依据" :visible.sync="previewVisibleLaw" width="50%" > <div v-html="check.law" class="preview-html"></div> <span slot="footer" class="dialog-footer"> <el-button type="primary" @click="previewVisibleLaw = false" >确 定</el-button > </span> </el-dialog> <el-dialog title="预览规范根据" :visible.sync="previewVisibleStardard" width="50%" > <div v-html="check.standard" class="preview-html"></div> <span slot="footer" class="dialog-footer"> <el-button type="primary" @click="previewVisibleStardard = false" >确 定</el-button > </span> </el-dialog> <ExImport :options="options" :eximportVisible="eximportVisible" @closeExImport="closeExImport" :source="pageName" ></ExImport> <!-- 参考模态框 --> <Refer :referVisible="referVisible" @closeRefer="closeRefer"></Refer> </div></template><script>import { Common } from "@admin/mixin/common";import { Has } from "@admin/mixin/has";import { Rules } from "@admin/mixin/rules";import { Library } from "@admin/mixin/library";import Editor from "../common/editor";import TableDangerCondition from "./tableDangerCondition.vue";import ExImport from "./eximport.vue";import Refer from "./refer.vue";export default { mixins: [Common, Rules, Has, Library], name: "CheckSystem", components: { Editor, TableDangerCondition, ExImport, Refer, }, data() { return { pageName: "checkSystem", check: {}, rulesInfo: { id: "请输出id", control: "请输出管制项", desc: "请输出形容", purpose: "请输出查看目标", tpl: "请抉择模板", }, }; }, methods: { handleChange(e, field) { this.check[field] = JSON.parse(e); }, }, mounted() { this.getCheckDict(); },};</script>

October 28, 2021 · 3 min · jiezi

关于vue-cli:vue-环境变量封装请求

根本介绍通过 vue cli 搭建的我的项目,有三种模式 development 模式用于 vue-cli-service servetest 模式用于 vue-cli-service test:unitproduction 模式用于 vue-cli-service build 和 vue-cli-service test:e2e你能够通过传递 --mode 选项参数为命令行覆写默认的模式。如: vue-cli-service build --mode development在 执行 npm run build 的时候能够抉择不同的模式,进行打包 环境变量在我的项目根目录下搁置下列文件来指定环境变量: .env # 在所有的环境中被载入.env.local # 在所有的环境中被载入,但会被 git 疏忽.env.[mode] # 只在指定的模式中被载入.env.[mode].local # 只在指定的模式中被载入,但会被 git 疏忽.env.development 文件内容: # just a flagENV = 'development'# base apiVUE_APP_STRAPI_URL = '/dev-api'VUE_APP_STRAPI_URL = http://192.168.9.9966:1122VUE_APP_MSG_BOT_UR = http://192.168.9.8855:1122.env.production 文件内容: # just a flagENV = 'production'# base apiVUE_APP_STRAPI_URL = '/prod-api'VUE_APP_STRAPI_URL = http://192.168.9.0077:2233VUE_APP_MSG_BOT_UR = http://192.168.9.1188:2233这样就能够针对不同的环境进行打包,也不必重复批改后端地址。 ...

August 6, 2021 · 1 min · jiezi

关于vue-cli:彻底卸载Vuecli29版本

执行卸载命令: 全局卸载:npm uninstall vue-cli -g删文件: .npmrc文件删除掉:npm config ls -l能够查看文件地位:userconfig = "C:UsersAdministrator.npmrc"删vue原始文件: 窗口运行命令:where vue,找到以后装置地位,找到文件,删掉保险起见能够再执行一次npm uninstall vue-cli -g,vue -V,曾经没有版本号了装置新版:npm install -g @vue/cli OR yarn global add @vue/cli

November 12, 2020 · 1 min · jiezi

关于vue-cli:Vue环境搭建

装置vue-cli 查看版本 创立我的项目 创立我的项目的配置通过高低箭头可设置选项,按回车键确定 运行我的项目 留神 local:集体创立的Vue我的项目Network:团队创立的Vue我的项目

November 5, 2020 · 1 min · jiezi

关于vue-cli:vuecli构建的vue项目中引入snapsvg

关上snap.svg的github:https://github.com/adobe-webplatform/Snap.svg 依照snap.svg的阐明来 1、装置snap.svg npm install snapsvg 2 、vue是基于webpack的,webpack 2.x and 3.x 须要装置Imports Loader npm i -D imports-loader 3、vue.config.js增加配置 module: { rules: [ { test: require.resolve('snapsvg/dist/snap.svg.js'), use: 'imports-loader?this=>window,fix=>module.exports=0', }, ], }, resolve: { alias: { snapsvg: 'snapsvg/dist/snap.svg.js', }, },4、应用: import Snap from 'snapsvg'; 此时运行我的项目会报错。示意import-loader传了不可辨认的属性。 查阅import-loader,发现其反对的属性只有 可见官网给到的rules的use配置是谬误的。 通过查看snap.svg的issue,能够找到第三条记录 点击进入 https://github.com/adobe-webplatform/Snap.svg/issues/639 so:批改配置为: module: { rules: [ { test: require.resolve('snapsvg/dist/snap.svg.js'), use: 'imports-loader?wrapper=window&additionalCode=module.exports=0;', }, ], },即可。

November 3, 2020 · 1 min · jiezi

关于vue-cli:Vue学习记录一开发环境准备

1.开发工具 - VS Code抉择 VS Code 是因为这是一款很容易上手的工具,在 VS Code 中找到的每个性能都实现一项杰出的工作,构建了一些简略的功能集,包含语法高亮、智能补全、集成 git 和编辑器内置调试工具等,将使你开发更高效。下载地址官网: https://code.visualstudio.com/ 举荐插件Vetur —— 语法高亮、智能感知、Emmet 等Vue VSCode Snippets —— 疾速生成 Vue 模板EsLint—— 语法纠错Auto Close Tag —— 主动闭合 HTML/XML 标签Auto Rename Tag —— 主动实现另一侧标签的同步批改Path Intellisense —— 主动路劲补全Bracket Pair Colorizer —— 为代码中的括号添上一抹亮色您能够在这里找到无关扩大的文档: https://code.visualstudio.com/docs/extensions/overview 2.装置 Node.jsNode.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。 Node.js 应用了一个事件驱动、非阻塞式 I/O 的模型。下载地址官网: https://nodejs.org/en/ (一路 next 即可) 装置完可在控制台查看 node、npm 对应版本node -vnpm -v永恒应用淘宝镜像命令:npm config set registry https://registry.npm.taobao.org3.装置 vue-devtoolsvue-devtools 是一款基于 chrome 浏览器的插件,用于调试 vue 利用,这能够极大地提高咱们的调试效率。接下来咱们就介绍一下 vue-devtools 的装置。装置形式形式一:chrome 商店间接装置vue-devtools 能够从 chrome 商店间接下载安装 ...

September 11, 2020 · 3 min · jiezi

关于vue-cli:vuecli-sourcemap私有化部署配置

先抛出我的疑难:为什么 vue-cli sourcemap私有化部署 这个解决方案很少有人提,网上搜到的根本都是说sourcemap配置(开关和模式等根底配置)的货色,尽管说sourcemap私有化部署配置比拟好实现,但我在vue-cli4生成的我的项目中发现这里还是有个小坑的,故,以此记录 咱们先关上vue-cli 的文档看下相干配置 // vue.config.jsmodule.exports = { // options... productionSourceMap: true, // 默认是true,接管的是布尔值}哦?没了?没了,sourcemap publicPath?不存在!也就是咱们压根不能通过简略的批改配置做到私有化部署sourcemap的需要,那怎么办?必定是批改webpack配置了!用 SourceMapDevToolPlugin 啊!这里的具体用法我不再赘述,毕竟文档都贴出来了 OK,咱们开始吧......很快,咱们就写好了,如下 const webpack = require('webpack')module.exports = { productionSourceMap: true, // 默认是true,接管的是布尔值 chainWebpack: config => { config.plugin('SourceMapDevToolPlugin') .use(webpack.SourceMapDevToolPlugin).tap(args => { return [{ filename: '[file].map', publicPath: 'https://exmaple.com/', moduleFilenameTemplate: 'source-map' }] }) }}而后你兴奋的去运行 npm run build ......可是你发现在打包后的js开端呈现两个sourcemap指向,这是不对的,而后你开始各种猜测,各种尝试,发现就是不行,要么这不行,要么那不行的(手动坏笑) 怎么办? 排查问题大法之审查webpack配置vue-cli是开发工具,打包是基于webpack的,那咱们就去看webpack咯,看看vue-cli最终生成的webpack配置到底是什么,到底是哪里出错了不就能找到问题的起因了吗?那怎么办呢?好在cli提供了这样的命令,毕竟webpack的确配置太简单了 点击查看审查我的项目的 webpack 配置文档 运行 vue inspect --mode production > output.js 后咱们发现......咱们发现很多方才尝试的那么多为什么不胜利的起因,每个人尝试的都不同,我只说最后咱们遇到的问题吧——为什么会有两个sourcemap指向,对了,这里提一下在审查webpack配置时加上的 --mode production 如果咱们不加上这句那默认审查的配置就是 development 模式下的了,那你可能还是找不到起因,好了,咱们看下输入的配置 ...

September 9, 2020 · 1 min · jiezi

elementUiVuei18nVuecli-实现前端国际化

首先安装vue-i18n算了,这个不多讲,看官网:http://kazupon.github.io/vue-i18n/zh/main.js 中引入并注册import i18n from './lang';// 设置国际化Vue.use(ElementUI, { i18n: (key, value) => i18n.t(key, value)});new Vue({ el: '#app', i18n, render: h => h(App)});src目录中建立语言包文件夹 lang/index.js//index.js文件import Vue from 'vue';import VueI18n from 'vue-i18n';import enLocale from 'element-ui/lib/locale/lang/en';import zhLocale from 'element-ui/lib/locale/lang/zh-CN';Vue.use(VueI18n);const messages = { en: { message: { hello: '{msg} world' }, ...enLocale }, zh: { message: { hello: '{msg} 世界' }, ...zhLocale }};const i18n = new VueI18n({ locale: 'zh', // set locale messages // set locale messages});export default i18n;效果初探,随便找个页面试试,此时页面会显示 hello 世界<p>{{ $t('message.hello', { msg: 'hello' }) }}</p><p v-html="$t('message.hello')" />Look,是不是很简单,已经有了雏形,开始精加工一般来讲,要翻译的文字比较多,所以最好为每门语言建立独立文件管理. 新建文件 lang/zh.js、 lang/en.js, 写入一些测试数据//zh.jsexport default { app: { LanguageChage: '语言切换', editPassword: '修改密码', signOut: '登出' }};//en.jsexport default { app: { LanguageChage: 'Language switching', editPassword: 'Change Password', signOut: 'Sign out' }};下面去封装一个组件,用来切换语言,并将语言状态保存到cookie和Vuex中。在封装组件之前,咱们先去封装一个方法,保存语言状态值, 更新之前的 lang/index.js 文件,主要是 getLanguage 方法import Vue from 'vue';import VueI18n from 'vue-i18n';import Cookies from 'js-cookie';import enLocaleElement from 'element-ui/lib/locale/lang/en';import zhLocaleElement from 'element-ui/lib/locale/lang/zh-CN';import zhLocale from './zh';import enLocale from './en';Vue.use(VueI18n);// 语言环境信息const messages = { en: { ...enLocale, ...enLocaleElement }, zh: { ...zhLocale, ...zhLocaleElement }};// 获取语言环境并保留状态export function getLanguage() { const cookieLanguage = Cookies.get('language'); if (cookieLanguage) return cookieLanguage; const browerLanguage = (navigator.language || navigator.browserLanguage).toLowerCase(); const locales = Object.keys(messages); for (const locale of locales) { if (browerLanguage.indexOf(locale) > -1) { return locale; } }}const i18n = new VueI18n({ locale: getLanguage(), messages, fallbackLocale: 'zh'});// 热更新if (module.hot) { module.hot.accept(['./en', './zh'], function() { i18n.setLocaleMessage('en', require('./en').default); i18n.setLocaleMessage('zh', require('./zh').default); });}export default i18n;vuex仓库中增加language字段, 一般大家应该都是用vuex的吧,这里我用vuex的module模式来写, 其实随意,都可以。// app.js 这是我的store文件import { getLanguage } from '@/lang/'; // 引入之前写好的方法// state里增加language字段const state = { language: getLanguage()};const mutations = { SETLANGE: (state, language) => { state.language = language; Cookies.set('language', language); }};const actions = { setLanguage({ commit }, language) { commit('SETLANGE', language); }};export default { namespaced: true, state, mutations, actions};OK, 准备工作已完成,下面封装切换语言的组件, 新建一个 launageSelect.vue 文件<template> <el-dropdown trigger="click" class="international" @command="handleSetLanguage"> <div> 语言切换 </div> <el-dropdown-menu slot="dropdown"> <el-dropdown-item :disabled="language==='zh'" command="zh"> 中文 </el-dropdown-item> <el-dropdown-item :disabled="language==='en'" command="en"> English </el-dropdown-item> </el-dropdown-menu> </el-dropdown></template><script>export default { computed: { language() { return this.$store.getters.language; //这里我用getters处理,代码不贴了,你么你随意 } }, methods: { handleSetLanguage(lang) { // 通过VueI18n的根实例设置当前的语言环境 不懂请看文档 http://kazupon.github.io/vue-i18n/zh/api/#%E9%9D%99%E6%80%81%E5%B1%9E%E6%80%A7 this.$i18n.locale = lang; this.$store.dispatch('app/setLanguage', lang); this.$message({ message: 'Switch Language Success', type: 'success' }); } }};</script>到此为止,基本的国际化框架就已经完成,可以直接去使用了。等等,还没完,接下来才是最重要的。一般vue项目的菜单都是在route中去写的,此时无法直接使用模板语法进行国际化,所有咱们还要封装一个方法,用来处理菜单标题/** *生成字符- 国际化使用 * @param {*} lanuageKey 语言对象键值 * @param {*} title 要转换的值 */export function generateText(lanuageKey, title) { const key = this.$te(`${lanuageKey}.${title}`); if (key) { return this.$t(`${lanuageKey}.${title}`); } return title;}找到渲染菜单的文件,引入刚刚的方法,进行菜单标题格式化 <app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path)"> <el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}" > <item :icon="onlyOneChild.meta.icon||(item.meta&&item.meta.icon)" :title="generateText('route', onlyOneChild.meta.title)" /> </el-menu-item> </app-link> //引入方法 import { generateText } from '@/utils/'; //methods里调用下 methods: { generateText }此时你的配置应该是这样的// zh.jsexport default { route: { home: '首页', }}//router.js (title中的home要和你的zh.js里的key值对应) { path: '/', component: Layout, redirect: '/home', children: [{ path: 'home', name: 'Home', component: () => import('@/views/home/index'), meta: { title: 'home', icon: 'home' } }] }此时你得菜单项便可以正常渲染了到此便正式结束,其实还蛮简单的,当然i18n有很多个语法,大家自行查阅文档,谢谢!

October 17, 2019 · 2 min · jiezi

listen-EADDRNOTAVAIL-address-not-available-1921682919528

1.进入项目 cd xxxx2.npm install3.npm run dev 准备就绪启动项目 ><!!! 报错了 listen EADDRNOTAVAIL: address not available 192.168.2.91:9528之前为了能在手机上访问vue的项目,找到config文件夹下的index.js文件,打开后,将host的值改为我本地的ip。 在config下的index.js修改 解决办法:因为机器重启,DHCP重新分配了IP。重新配置工程绑定当前分配的IP就可以了,或者修改本机的IP为静态IP,问题就解决了。

October 15, 2019 · 1 min · jiezi

vuecli-为项目设置别名

1.使用场景:在项目开发过程中经常需要引入各种文件,例img,css,js等,我们可以在vue-cli中给不同目录设置别名,方便我们使用 2.vue-cli 2x 配置 // 在 webpack.base.config.js中的 resolve 配置项,在其 alias 中增加别名resolve: { extensions: ['.js', '.vue', '.json'], alias: { 'vue$': 'vue/dist/vue.esm.js', '@': resolve('src'), } }3.vue-cli 3x 配置 // 在根目录下创建vue.config.jsvar path = require('path')function resolve (dir) { console.log(__dirname) return path.join(__dirname, dir)}module.exports = { chainWebpack: config => { config.resolve.alias .set(key, value) // key,value自行定义,比如.set('@@', resolve('src/components')) }}4.保存,重启项目

October 15, 2019 · 1 min · jiezi

根据vuecli手摸手实现一个自己的脚手架

故事背景身为一个入门前端七个月的小菜鸡,在我入门前端的第一天就接触到了vue,并且死皮赖脸的跟他打了这么久的交到,还记得第一次用vue init webpack 这句命令一下生成一个模板的时候那种心情,当时我就想,要是自己也能写一个的话,那会是灰常吃鸡的吧 o( ̄▽ ̄)ブ,所以说今天我们也要简单实现一个自己的脚手架认识binbin的作用首先我们先来了解一下这个bin ,这个bin和我们最开始用的vue init webpack 这个命令是息息相关的 还记得我们在最开始安装vue-cli的时候嘛 npm install vue-cli -g 这条命令的意思是把vue-cli 安装到全局 ,以至于你再任何一个地方打开cmd 的时候都能够使用 vue init webpackvue init webpack 这条命令实际上是执行的vue-cli 里边 package.json 里边的bin属性下的命令 这个文件大概位置如下 这个路径里边有隐藏的路径,在查找的时候记得打开隐藏目录可见 这个bin里边大概长成这个样子 由图中可见,这里边有三个命令 vue vue-init vue-list这个三个命令的意思是执行对应的文件,Npm会在node_modules/.bin/目录下建立符号链接。又因为node_modules/.bin/目录会在运行时加入系统的PATH变量,因此在运行npm时,就可以不带路径,直接通过命令来调用这些文件。bin所执行的文件和参数那么说到这里你肯定会好奇这个文件是怎么做到生成模板的对吧,那么我们就来看一下被执行的这个文件到底是何方神圣 #!/usr/bin/env node const program = require('commander') program .version(require('../package').version) .usage('<command> [options]') .command('init', 'generate a new project from a template') .command('list', 'list available official templates') .command('build', 'prototype a new project') .command('create', '(for v3 warning only)') program.parse(process.argv)上边这一坨代码就是 执行vue init webpack 的文件所有内容 ...

October 4, 2019 · 2 min · jiezi

Elementui中ref和scope的使用

ref一般写在el-form中,以作为验证表单时使用<el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="250px" class="demo-ruleForm" ></el-form-item>在调接口前作验证 this.$refs[formName].validate(valid => { if (valid) { console.log("11"); upDataPc(updateAddinfo).then(res => { this.resetForm(formName); this.$message.success("修改批次成功"); this.addBatchDialog = false; this.getBatchList(); });在el-table-column中可以添加template插槽通过scped.row加属性拿到data中的对应数据 <el-table-column prop="bzftype" label="保障房类型" align="center"> <template slot-scope="scope"> <span v-if="scope.row.bzftype == 0">公共租赁住房</span> <span v-if="scope.row.bzftype == 1">廉租住房</span> </template> </el-table-column> <el-table-column prop="stime" label="开始日期" align="center"></el-table-column> <el-table-column prop="etime" label="结束日期" align="center"></el-table-column> <el-table-column label="操作" align="center"> <template slot-scope="scope"> <el-button @click="updateBatch(scope.row.id)" type="text" size="small">编辑</el-button> <span v-if="scope.row.sfysy==0">|</span> <el-button v-if="scope.row.sfysy==0" @click="deleteBatch( scope.row.id)" type="text" size="small">删除</el-button> </template> </el-table-column>

September 20, 2019 · 1 min · jiezi

手摸手-Webpack-多入口配置实践

最近在做项目的时候遇到了一个场景:一个项目有多个入口,不同的入口,路由、组件、资源等有重叠部分,也有各自不同的部分。由于不同入口下的路由页面有一些是重复的,因此我考虑使用 Webpack 多入口配置来解决这个需求。 再一次,在网上找的不少文章都不合我的需求,很多文章都是只简单介绍了生产环境下配置,没有介绍开发环境下的配置,有的也没有将多入口结合 vue-router、vuex、ElementUI 等进行配置,因此在下通过不断探坑,然后将思路和配置过程记录下来,留给自己作为笔记,同时也分享给大家,希望可以帮助到有同样需求的同学们~ 1. 目标分析一个项目中保存了多个 HTML 模版,不同的模版有不同的入口,并且有各自的 router、store 等;不仅可以打包出不同 HTML,而且开发的时候也可以顺利进行调试;不同入口的文件可以引用同一份组件、图片等资源,也可以引用不同的资源;代码仓库:multi-entry-vue 示意图如下: 2. 准备工作首先我们 vue init webpack multi-entry-vue 使用 vue-cli 创建一个 webpack 模版的项。文件结构如下: .├── build├── config├── src│   ├── assets│   │   └── logo.png│   ├── components│   │   └── HelloWorld.vue│   ├── router│   │   └── index.js│   ├── App.vue│   └── main.js ├── static├── README.md├── index.html├── package-lock.json└── package.json这里顺便介绍在不同系统下生成目录树的方法: mac 系统命令行生成目录树的方法 tree -I node_modules --dirsfirst ,这个命令的意思是,不显示 node_modules 路径的文件,并且以文件夹在前的排序方式生成目录树。如果报没有找到 tree 命令的错,安装 tree 命令行 brew install tree 即可。windows 系统在目标目录下使用 tree /f 1.txt 即可把当前目录树生成到一个新文件 1.txt 中。首先我们简单介绍一下 Webpack 的相关配置项,这些配置项根据使用的 Webpack 模版不同,一般存放在 webpack.config.js 或 webpack.base.conf.js 中: ...

September 10, 2019 · 5 min · jiezi

小爱ADMIN系列文章二用Vuecli3mockjs-实现后台管理权限和三级菜单功能

最近完成了我的小爱ADMIN后台管理系统基本功能,同时进行了页面整体布局和样式的全新改版。新增了系统权限功能的实现,同时觉得后台系统所有的菜单都左置,会限制菜单的扩展,因此我改进了三级菜单的显示。 效果演示地址github地址权限功能的实现权限路由思路:根据用户登录的roles信息与路由中配置的roles信息进行比较过滤,生成可以访问的路由表,并通过router.addRoutes(store.getters.addRouters)动态添加可访问权限路由表,从而实现左侧和顶栏菜单的展示。 权限功能的实现步骤:1.给相应的菜单设置默认的roles信息在router/index.js中,给相应的菜单设置默认的roles信息;如下: 给"权限设置"菜单设置的权限为: { path: '/permission', name: 'permission', meta: { title: '权限设置', roles: ['admin', 'editor'] //不同的角色都可以看到 }}给其子菜单"页面权限",设置权限为: { path: 'page', name: 'pagePer', meta: { title: '页面权限', roles: ['admin'] //只有"admin"可以看到该菜单 }, component: () => import('@/page/permission/page'),}给其子菜单"按钮权限"设置权限为: { path: 'directive', name: 'directivePer', meta: { title: '按钮权限', roles:['editor'] //只有"editor"可以看到该菜单 }, component: () => import('@/page/permission/directive'),}2.通过router.beforeEach()进行路由过滤和权限拦截;代码如下: function hasPermission(roles, permissionRoles) { if (roles.indexOf('admin') >= 0) return true if (!permissionRoles) return true return roles.some(role => permissionRoles.indexOf(role) >= 0)}const whiteList = ['/login'] // 不重定向白名单router.beforeEach((to, from, next) => { NProgress.start() // 设置浏览器头部标题 const browserHeaderTitle = to.meta.title store.commit('SET_BROWSERHEADERTITLE', { browserHeaderTitle: browserHeaderTitle }) // 点击登录时,拿到了token并存入了cookie,保证页面刷新时,始终可以拿到token if (getToken('Token')) { if(to.path === '/login') { next({ path: '/' }) NProgress.done() } else { // 用户登录成功之后,每次点击路由都进行了角色的判断; if (store.getters.roles.length === 0) { let token = getToken('Token'); getUserInfo({"token":token}).then().then(res => { // 根据token拉取用户信息 let userList = res.data.userList; store.commit("SET_ROLES",userList.roles); store.commit("SET_NAME",userList.name); store.commit("SET_AVATAR",userList.avatar); store.dispatch('GenerateRoutes', { "roles":userList.roles }).then(() => { // 根据roles权限生成可访问的路由表 router.addRoutes(store.getters.addRouters) // 动态添加可访问权限路由表 next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 }) }).catch((err) => { store.dispatch('LogOut').then(() => { Message.error(err || 'Verification failed, please login again') next({ path: '/' }) }) }) } else { // 没有动态改变权限的需求可直接next() 删除下方权限判断 ↓ if (hasPermission(store.getters.roles, to.meta.roles)) { next()// } else { next({ path: '/401', replace: true, query: { noGoBack: true }}) } } } } else { if (whiteList.indexOf(to.path) !== -1) { // 点击退出时,会定位到这里 next() } else { next('/login') NProgress.done() } }})router.afterEach(() => { NProgress.done() // 结束Progress setTimeout(() => { const browserHeaderTitle = store.getters.browserHeaderTitle setTitle(browserHeaderTitle) }, 0)})本系统权限逻辑分析1、路由对象区分权限路由对象和非权限路由对象;初始化时,将非权限路由对象赋值给Router;同时设置权限路由中的meta对象,如:meta:{roles:['admin','editor']},表示该roles所拥有的路由权限; ...

August 28, 2019 · 4 min · jiezi

vuecli安装使用less

vue-cli构建的项目默认是不支持less的,需要自己添加依赖1.安装less和less-loader ,在项目目录下运行如下命令npm install less less-loader --save-dev 2.安装成功后,打开build/webpack.base.conf.js ,在 module.exports = 的对象的module.rules 后面添加一段:module.exports = { // 此处省略无数行,已有的的其他的内容module: { rules: [ // 此处省略无数行,已有的的其他的规则 { test: /\.less$/, loader: "style-loader!css-loader!less-loader", } ] }} 3.最后,在代码中的style标签中加上lang="less"属性即可 <style lang="less" scoped> .index-wrap { display: flex; align-items: center; justify-content: center; span { font-size: 0.373rem; } }</style>

July 12, 2019 · 1 min · jiezi

vuecli脚手架工具搭建vuewebpack项目

vue-cli构建工具大大降低webpack的使用难度,支持热更新,有webpack-dev-server的支持,相当于启动了一个请求服务器,给你搭建了一个测试环境,只关注开发。 1.使用vue-cli之前,需要安装node环境,详细教材参考https://www.cnblogs.com/xinai... 2.使用npm全局安装webpack打开命令行工具输入:npm install webpack -g或者(npm install -g webpack),安装完成之后输入 webpack -v,如下图,如果出现相应的版本号,则说明安装成功。 3.全局安装vue-cli在cmd中输入命令:npm install --global vue-cli,安装完成之后输入 vue -V(注意这里是大写的“V”),如下图,如果出现相应的版本号,则说明安装成功。 4.vue-cli来构建项目在D盘新建一个文件夹(vue_project)作为项目存放地,然后使用命令行cd进入到项目目录输入:vue init webpack vue-test 输入命令后,会跳出几个选项让你回答:Project name (vue-test):项目名称,直接回车,按照括号中默认名字(注意这里的名字不能有大写字母,如果有会报错Sorry, name can no longer contain capital letters)Project description (A Vue.js project):项目描述,也可直接点击回车,使用默认名字Author ():作者Runtime + Compiler: recommended for most users 运行加编译,既然已经说了推荐,就选它了Runtime-only: about 6KB lighter min+gzip, but templates (or any Vue-specificHTML) are ONLY allowed in .vue files - render functions are required elsewhere 仅运行时,已经有推荐了就选择第一个了Install vue-router? (Y/n) 是否安装vue-router,这是官方的路由,大多数情况下都使用,这里就输入“y”后回车即可。Use ESLint to lint your code? (Y/n) 是否使用ESLint管理代码,ESLint是个代码风格管理工具,是用来统一代码风格的,一般项目中都会使用。接下来也是选择题Pick an ESLint preset (Use arrow keys) 选择一个ESLint预设,编写vue项目时的代码风格,直接y回车Setup unit tests with Karma + Mocha? (Y/n) 是否安装单元测试,我选择安装y回车Setup e2e tests with Nightwatch(Y/n)? 是否安装e2e测试 ,我选择安装y回车回答完毕后就开始构建项目 ...

July 8, 2019 · 1 min · jiezi

一次项目中的验签加密的一些坑主要是数据格式问题

最近接手了一个项目是一个比较完整的项目了 我需要进行改造 是基于vuecli3.0+webpack开发的u其中有一个功能就是我们每个请求都要进行一次验签 就是取一些字符串进行加密 并将验签加入请求头中 后台也用相同的算法进行加密 然后比对这个功能本身是写好的 但是有些问题我们其中的加密字段是穿的参数按照字母排序 然后取第一个参数的前三位和最后一个参数的后三位这都很简单用sort()方法排序一下就行第一个问题就是axios直接传值的话服务端会认为是字符串所以截取的时候会将符号也截取一般就成了{"+排序第一的参数的第一个字母和排序最后一个参数的最后一个字母 + "} 这样明显是有问题的 不过这个解决也简单 直接用qs这个插件处理一下就ok 这里我做了一个处理 如果requestData是类型是字符串 用 requestData.split('&').sort().join('').replace(/([^=><])=([^=><])/g,'$1$2');进行排序如果是对象 用 for (var i in requestData) { dataString += `${i}${requestData[i]}&` } dataString = dataString.split('&').sort().join('')进行排序这样就解决了大部分的问题 但是昨天突然有一个模块说验签又不过了 我就很奇怪 就让后端小哥把没加密的串返回给我对比了一下首先还是我上面说的截取到了符号 这个简单 qs处理一下然后这里的问题是用qs处理过后 参数中如果带有中文 后端接收到的其实是中文 但是qs自己会对中文进行encodeURIComponent转码 这个处理也很简单 使用decodeURIComponent() 函数进行解码就可以

July 6, 2019 · 1 min · jiezi

关于Vue2一些值得推荐的文章-七月初

七月初 vue2 推荐集合查看github最新的Vue weekly;请::点击::集web前端最近很火的vue2框架资源;定时更新,欢迎 Star 一下。 七月: 不在山,不在岸,采我之时七月半。!七月-银潢七月秋浪高,黄昏欲渡未成桥。(07.01~至今): 王子乔 [唐] 宋之问 王子乔,爱神仙,七月七日上宾天。白虎摇瑟凤吹笙, 乘骑云气吸日精。吸日精,长不归,遗庙今在而人非。 空望山头草,草露湿人衣。 学习vue源码我们一起写一个Vue的Loading插件吧大白话理解和初步使用vue-routervue使用总结Vue nextTick 变迁史vuex中的四大金刚提前使用Vue 3.0新特性,vue-function-api尝鲜使用vue中的混入mixin优化表单验证插件一张图教你快速玩转vue-cli3学习vue源码—mvvmvue-router 源代码全流程分析「长文」探索Angular,React,Vue的趋势比较深入理解vue响应式原理你不知道的Vue.nextTick源码系列Vue手把手带你撸项目系列之动态面包屑为vue3学点typescript(1), 体验typescript使用 Typescript 加强 Vuex 使用体验前端规范之vue 项目规范大白话理解和初步使用vuexVue 面试知识点总结Vue 项目功能实现:刷新当前页面精读《Vue3.0 Function API》Vue入门学习之技术分享-2(深入理解Vue组件)为vue3学点typescript, 基础类型和入门高级类型vuex了解一下?Vue 面试知识点总结(二)【持续更新中~】【一文学会】vue.js入门到放弃从源码解读Vue生命周期,让面试官对你刮目相看Vue入门学习之技术分享-3(Vue中的动画特效)Vue中jsx不完全应用指南vue打包后vendor.js文件过大解决方案带你了解vue计算属性的实现原理以及vuex的实现原理记录一次vue练习的填坑记录Vue2 weekly 上Why You Should Start Front-End by Learning Vue.js Integrating content management into your Vue.js projects with PrismicVue.js Amsterdam RecordingsiView UI framework 2.4Promoted - Get all products by Creative Tim including Vue premium dashboards 90% offBest resources to learn Vue.js in 2018The Vue.js Conference in Amsterdam will have everything you hope forLaravel Nova Administration Panel with Vue.jsVuePress: What is it and Why it is a great tool to useVue.js Frameworks & Libraries to use in your next projectVueCamp: Vue.js Barcamp BerlinAmendment proposal to Function-based Component API · Issue #63 · vuejs/rfcs Why every Vue developer should be excited by Quasar 1.0 – Razvan StoenescuVue's Darkest Day – Daniel ElkingtonVue2 weekly 中What does the Vue function API feel like - Abdelrahman Awad3 Key Insights from Vue’s new functional API RFC – Kevin BallVue without View - An Introduction to Renderless Components – Jason Yu How to use cookies in VuePress - Dan VegaIn Vue, When Do I Actually Need the :key Attribute and Why? — Marina MostiWhat is VueFront? - VueFrontVue.js functional components: what, why, and when? – Austin GMigrating from Vuetify to Quasar - Stanislav Valasek10 Things You Should Know Before Writing Your Next Vuejs Component - Edithson Abelard GitHub - jamesdruhan/vue-jd-tableHow To Upgrade Your VuePress Site To v1.0 - Florimond MancaUse Fragments to Avoid Obsolete GraphQL Fields in Vue.js Applications – Markus OberlehnerReading Image Sizes and Dimensions with Vue.js – Raymond CamdenFrom JSX to Vue: my favorite templating tips – briwa A beginner-friendly guide to unit testing the Vue.js application – Vladislav BulyukhinVue2 weekly 下tiptap – a renderless rich-text editor for Vue.js VueFrontVuePress 1.x Released! – ULIVZNuxtJS: From Terminal to Browser - Sébastien ChopinTriggering events from Vue Router views - Dan VegaBuild An Intersection Observer Directive In Vue - Alex ReganBuild Decoupled Vue.js Applications with Hooks - Markus OberlehnerHow to Build a Group Chat App with Vue.js - Oscar CastroGitHub - kai-oswald/vue-svg-transitionGitHub - wokes/Laravel-Vue-SPA-template更多推荐查看github最新的Vue weekly;请::点击::集web前端最近很火的vue2框架资源;定时更新,欢迎 Star 一下。 ...

July 6, 2019 · 2 min · jiezi

vuecli3-取消eslint-校验代码

vue create hello-world创建项目的时候选择了Linter / Formatter,所以写代码的时候会有代码规范检查,怎么才能关闭这个校验呢 1.项目创建好后会生成 .eslintrc.js文件 module.exports = { root: true, env: { node: true }, 'extends': [ 'plugin:vue/essential', // '@vue/standard',//这行注释就可以 '@vue/typescript' ], rules: { 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off' }, parserOptions: { parser: '@typescript-eslint/parser' }}@vue/standard 这个注释掉就可以了

July 5, 2019 · 1 min · jiezi

vuecli脚手架初体验

按照网上教程初始化了一个新的目录,开发环境没问题,打包也没问题,打包完之后访问就出现了网上经常出现的路径访问错误问题,当然是用网上的解决方案也解决了,还遇到一个iview字体文件找不到的问题,写在这做个记录 1、build之后路径错误config/index.js build部分 assetsPublicPath: '/',//改为 './'2、iview字体图标不显示/找不到字体路径问题/build/webpack.prod.conf.js extract: true,//改为false3、Eslint语法检查问题有时候多个分号,少个空格,没有空格都会报错,可以去根目录下的.eslintrc.js文件修改配置 rules: { // allow async-await 'generator-star-spacing': 'off', // allow debugger during development 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', "indent": ["off", 2], 'semi': 0,//取消分号 'eol-last':0,//取消换行 "no-irregular-whitespace":0,//取消空格 "space-before-function-paren": 0//取消方法前空格 }即使这样还有一些限制去不掉,解决方案就是不用语法检查build/webpack.base.conf.js,将eslint相关语法注释或删除 // ...(config.dev.useEslint ? [createLintingRule()] : []),重新运行 npm run dev有效

July 2, 2019 · 1 min · jiezi

dockerdaocloud实现前端项目Vuejs自动部署

项目的自动化部署在大公司或独角兽中用得比较多,相比来进行手动部署项目来说会更加高效。那么本文结合之前学习的docker知识点以及nginx来简单实现VueJs项目的自动部署,当然针对其他项目也类似。运行环境首先需要在服务器上进行docker、nginx、node等的安装。便于进行后续的操作。通过docker拉取nginx镜像,命令docker pull nginx通过vue-cli初始化一个项目可以通过vue init webpack 项目名称初始化一个项目,这里假设项目名称是docker-vue,然后在该项目的根目录新建一个Dockerfile文件,大致内容如下: FROM nginx:latest#把当前打包工程的html复制到虚拟地址COPY dist/ /usr/share/nginx/html/#使用自定义nginx.conf配置端口和监听RUN rm /etc/nginx/conf.d/default.confADD default.conf /etc/nginx/conf.d/RUN /bin/bash -c 'echo init ok!!!'并新建一个default.conf文件,内容如下: server {项目中定义的端口号listen 8080;server_name localhost;#charset koi8-r;#access_log /var/log/nginx/log/host.access.log main;location / { root /usr/share/nginx/html; index index.html index.htm;}#error_page 404 /404.html;# redirect server error pages to the static page /50x.html#error_page 500 502 503 504 /50x.html;location = /50x.html { root html;}}自此,基本工作已完成,接下来就是对于daocloud.io的基本配置操作了 daocloud.io基本配置操作若无账号,可以先进行注册daocloud.io。接下来的操作分为: 创建项目集群管理创建镜像仓库创建项目这里需要添加项目名称,设置代码源(可以是github、gitlab)等,然后选择你所需要构建的项目,我这里选择了我自己的github仓库docker-vue,然后点击开始创建就行。 集群管理集群管理的主要目的是为了链接远程服务器,并通过命令进行daocloud.io镜像的创建。选择新建主机 由于我自己是购买了阿里云服务器了,系统是ubuntu的,所以就选择了这样的配置,然后在服务器上运行: curl -sSL https://get.daocloud.io/daomonit/install.sh | sh -s e2fa03ebead51076411388c26dff2257dae89768 来构建一个docker镜像,如: ...

July 2, 2019 · 1 min · jiezi

vuecli的npm包

为了方便在项目的中使用的vue框架,自己搭建了一套vue-cli,欢迎大家使用,并提出问题,谢谢 1.安装npm包cnpm(npm) install create-frame-vue -g 2.使用create-frame-vue指令就可以创建项目 使用指令后你可以看到这么的 指令完成之后创建的项目 npm install && npm run serve 即可启动项目。 欢迎大家使用,希望大家提供好的建议或意见,谢谢大家

June 27, 2019 · 1 min · jiezi

前端请求graphql的数据格式之我见

前端请求后端数据,vue-cli用graphql的方法去请求:刚开始我们用ajax,axios去请求后端数据,无往不利。可是,在某一天,突然,要用graphql来请求数据! 心里一慌,没事,来者不拒。 第一步:我们定义一个新的js,xxx.js:import gql from "graphql-tag";export const getApoVal = { xxxName: gql` query { xxxBackName{ name age } } `,}上面就是类似get请求了。xxxName:随便起一个名字;xxxBackName:这是后端的字符串名字;name,age:后端传过来的属性名字。后端的字符串一定要一一对应,不对应就会报红色的error,哈哈哈! 有参数怎么办?export const getApoVal = { xxxName: gql` query APIQuery($page: Int, $pageSize: Int){ xxxBackName(page: $page, pageSize: $pageSize){ name age } } `,}完美解决你的get方法参数问题。 第二步,教你post方法获取:export const submitApoVal= { xxxName: gql` mutation APIMutation($page: Int, $pageSize: Int){ xxxBackName(page: $page, pageSize: $pageSize){ name age } } `,}是不是很简单?query改成mutation,这就是要点,还是要和后端字符串一一对应! 到这里,你已经可以完美获取后端数据。感谢大家的支持!!

June 26, 2019 · 1 min · jiezi

vue-videojs-处理-m3u8-的坑

vue + videojs 处理 m3u8 的坑:坑后面再说,先让m3u8运行起来, 第一步:首先vue的index.html 引入<link href="http://cdn.bootcss.com/video....; rel="stylesheet" /> <script src="http://cdn.bootcss.com/video....;></script> <script src="http://cdn.bootcss.com/videoj...;></script> 这3个东西,我觉得这几个很重要! 第二步:然后在xxx.vue使用:<video id="hls-video" width="1024" height="576" class="video-js vjs-default-skin" playsinline webkit-playsinline controls preload="auto" x-webkit-airplay="true" x5-video-player-fullscreen="true" x5-video-player-typ="h5" > <source src="your addr" type="application/x-mpegURL" > </video>第三步:js中的mouted()实例化:var player; player = videojs('hls-video'); 补充:在methods中可以用:player.play()播放;player.pause()暂停。 坑来了!:如果你第一次渲染,完全没问题,如果从这个页面跳spa到别的页面,再跳回来,bug出现了! 为什么会有红字error?我做错了什么?因为你没有销毁这个东西! 在本页面xxx.vue 中加上: beforeDestroy: function () { player.dispose();}, 完美解决!这个东西真的太坑了! 感谢大家的支持!!谢谢

June 25, 2019 · 1 min · jiezi

玩转Vue

1小时VueVue Tutorial in 2018 - Learn Vue.js by Example的笔记,深入浅出,通俗易懂。效果如下,在线演示地址:http://www.caishuxiang.cn/demo/190619vueproj/#/ 安装Vue 安装vue有三种方式,本次使用Vue CLI Vue 提供了一个官方的 CLI,为单页面应用 (SPA) 快速搭建繁杂的脚手架。它为现代前端工作流提供了 batteries-included 的构建设置。只需要几分钟的时间就可以运行起来并带有热重载、保存时 lint 校验,以及生产环境可用的构建版本 步骤: 安装vue cli > npm install -g @vue/cli开始一个新的Vue项目 > vue create vue-proj进入项目,开启服务,访问localhost:8080 yarn serve Vue组件 组件是组成Vue应用的基本单元,可以看下vue-pro的工程目录 这里的App.vue、Skill.vue就是组件,每个vue文件都是组件。 组件的结构template 中放置的是htmlscript中是页面的逻辑style中即样式信息<template> ...</template><script> ...</script><style> ...</style>引入其他的组件 如下所示: <template> <!-- Other HTML removed for brevity --> <HelloWorld msg="Welcome to Your Vue.js App"/> <!-- Other HTML removed for brevity --></template><script>import HelloWorld from './components/HelloWorld.vue'export default { name: 'app', components: { HelloWorld }}</script>Vue class和style绑定scoped style元素上使用了scoped,那么该style下面的写的css或者引用的外部css,只对所在component中的元素起作用.如下: ...

June 19, 2019 · 3 min · jiezi

vuecli3下配置IE浏览器兼容性

最近,在重构公司官网,需要兼容ie9/10/11,使用vue-cli构建项目。 在查询如何兼容ie时,首先是查看vue cli官网,浏览器兼容性,感觉官网说的不是太明晰(小白一枚,实在不太懂),然后就直接百度了,网上方法基本类似,都是用 browserslist,babel-polyfill等,只是具体步骤有差异,不过 都没有解决本人问题。经过层层查询,逐步对vue-cli 原理了解后,网上查询方法结合本人理解,将问题解决,在此记录下。 先说步骤,然后说一些自己浅显理解。 一.解决步骤1.配置browserslist配置这一项,有两个途径,一是 在 package.json文件中,添加browserslist字段;二是 在项目根目录,创建一个.browserslistrc文件,两种途径。这两种方法不能同时配置,不然运行serve命令会报错。 先说package.json中配置,网上很多如下方法: "browserslist": [ "> 1%", "last 4 versions" ]本人依此配置,报错!然后按照另外一种配置,如下: "browserslist": [ "ie 11" ]成功! 额外贴出.browserslistrc方法配置方式(只是列出书写方式,代码有效性,按上面来): > 1%last 4 versions2.安装babel-polyfill依赖这个简单,直接 npm i babel-polyfill --save-dev即可 3.引入babel-polyfill依赖 这一步是关键,网上查询很多,在main.js中,import babel-polyfill引入,本人测试后无效。 具体引入是在vue.config.js中configureWebpack字段中,具体: configureWebpack: config => { config.entry.app = ["babel-polyfill", "./src/main.js"]; }即在webpack入口配置中,加入babel-polyfill。至此,在ie下,兼容es6就解决了! 二.自己的理解上面把问题解决了,再将自己解决过程中的理解梳理下。 1.首先上面的解决步骤,仅仅适用于源码(/src),对依赖包无效。当需要对依赖包做兼容转译时,就需要用到官网中Polyfill部分内容了 2.vue-cli中webpack配置文件是在node_modules中的,没有直接在根目录,要想配置webpack,需要在vue.config.js中configureWebpack字段或者chainWebpack配置。具体如下: module.exports = { configureWebpack: { resolve: { alias: { querystring: 'querystring-browser' } } }}module.exports = { chainWebpack: config => { config.resolve.alias.set('querystring', 'querystring-browser') }}解决过程中,查询的相关资料1.Vue 兼容 ie9 的全面解决方案2.Vue CLI 3 浏览器兼容性配置3.Editing webpack.config.js when using vue-cli 3 ...

June 19, 2019 · 1 min · jiezi

Mac-升级-vue-3x-之前卸载-vue-296-失败的原因和解决方法

之前安装了 vue 2.9.6 的版本,现在 vue 官方升级到了 3.x 版本,所以想卸载掉 2.9.6 的版本,安装 3.x 版本,结果输入官方给出的命令 npm uninstall vue-cli -g 却无法成功卸载,一直提示 up to time in 0.03s,然后百度和 Google 了好久,也没见到有效的解决方法,最终沉下心慢慢的研究,终于知道了原因,记录下来,方便遇到相同问题的人。先介绍原因吧,可能大家都知道,npm 是 node 包管理器的简称(node package manager),在我们安装 node 的时候会一并安装。正常情况下,我们安装的 node 在 /usr/local/bin 目录下,而 npm 在 /usr/local/lib/node_modules 目录下,然后我们通过 npm 的全局命令安装的模块也在 /usr/local/bin 目录下(例如 npm install vue-cli -g),平时我们在终端里使用的 node --vesion 或者 vue --version 这种命令其实调用的就是 /usr/local/bin 中的命令。而我们使用 npm uninstall vue-cli -g 命令卸载 vue-cli 模块的时候,也是在这个目录去找,去卸载。但是如果我们在已经安装 vue 的情况下再安装 nvm(node 版本管理器,node version manager),就会出问题,nvm 会改变 npm 全局安装模块的路径,我这边的路径变成了 ~/.nvm/versions/node/v10.15.1/bin,在安装 nvm 之后我再使用 npm 的全局安装命令安装的模块全都在这个目录下。那么我们使用 npm uninstall vue-cli -g 命令去卸载 vue 当然是不会成功的,因为它是在 ~/.nvm/versions/node/v10.15.1/bin 目录去卸载,而我们的 vue 安装在 /usr/local/bin 目录下。那么知道了原因之后,就得解决问题了,下面的方法可能不是最好的,大家可以探索更好的方法。 ...

June 19, 2019 · 1 min · jiezi

vuecli-安装

打开终端cd ~/Desktopnpm install -g vue-clivue init webpack blog-client 红色框选出的区域 注意 yes 和 no 的选择 之后终端会创建 blog-client 文件夹 以及相关文件 执行cd blog-clientnpm run dev 一般情况下会报错【注意!报错提示缺少什么就安装什么就好】没有其他技巧!!!每个人遇到的情况不一样 以下只是学习方法 例如: 输入命令:npm run dev发现报错 缺少 webpack-dev-server(都告诉你 缺少了 不安装等什么???等它自己长出来吗) 安装 webpack-dev-server输入命令:npm install webpack-dev-server --save-de 再输入运行命令:npm run dev又发现报错:缺少 webpack (安呗。。。)安装 webpack输入命令:npm install webpack(安装完成的 不截图了 懒) 再输入运行命令:npm run dev又又发现报错:缺少 extract-text-webpack-plugin (继续安呗。。。)安装 extract-text-webpack-plugin 输入命令:npm install extract-text-webpack-plugin(安装完成的 不截图了 懒) 安装后 继续输入运行命令:npm run dev继续安装缺少文件 循环 循环 循环 直到 ...

June 18, 2019 · 1 min · jiezi

vue-cli3-项目打包

详细信息到vue-cli3官网新建 vue.config.js 文件// 在这里配置module.exports = { // 基本路径 publicPath:"./", // 输出文件目录 outputDir: 'dist', // webpack-dev-server 相关配置 devServer: { // port: 8888, // ... },}在 router.js 里//把mode写成hash模式mode: 'hash'运行npm run build

June 17, 2019 · 1 min · jiezi

vuecliwebpack初始项目

@vue/cli+webpack初始项目 (1)安装Vue-cli npm install -g @vue/cli(2)创建webpack管理的项目 vue init webpack vue_demo创建完成后,运行: npm run dev或者 npm start

June 9, 2019 · 1 min · jiezi

vuecli3多页应用构建优化

接续前篇多页应用改造,优化改造后的项目打包效果。 效果对比阶段磁盘占用空间打包时间备注原始9.9M-5.20版架构改造(SPA->MPA)7.1M-5.27版样式整合7.0M-5.30版公共组件&工具类整合6.9M-6.4版图片压缩6.0M20.767s-UglifyJs5.9M23.391s-合并小文件5.3M55.469s-代码分割splitChunks5.1M73.730s-gzip6.3M89.204s-优化前 优化后 优化过程压缩图片chainWebpack: config => { config.module .rule("image-webpack-loader") .test(/\.(gif|png|jpe?g|svg)$/i) .use("file-loader") .loader("image-webpack-loader") .tap(() => ({ disable: process.env.NODE_ENV !== "production" })) .end()};添加UglifyJs,移除consoleconst UglifyJsPlugin = require('uglifyjs-webpack-plugin')configureWebpack: config => { if (process.env.NODE_ENV === 'production') { const plugins = [] plugins.push( new UglifyJsPlugin({ uglifyOptions: { compress: { drop_console: true, drop_debugger: true } }, cache: true, // 启用文件缓存 parallel: true // 使用多进程并行运行来提高构建速度 // sourceMap: false // 映射错误信息到模块 }) ) config.plugins = [ ...config.plugins, ...plugins ] } }动态导入合并小文件webpackChunkName原来打包出来的文件,快上百个了,还有好些0.29KB的,需要合并下。此处使用webpackChunkName ...

June 7, 2019 · 2 min · jiezi

vuecli配置全局sassless变量

一、全局配置less 1.下载插件**vue add style-resources-loader**vue add pluginName 是vue-cli3提供的。vue add 是用yarn安装插件的, yarn源的问题有可能导致失败。如果上面安装失败的话,就分别安装 style-resources-loader 和 vue-cli-plugin-style-resources-loader(前提是已经安装过 less less-loader) // 没有出错的话,可以无视这里 npm i style-resources-loader vue-cli-plugin-style-resources-loader -D 或 yarn add style-resources-loader vue-cli-plugin-style-resources-loader -D** 第二步配置vue.config.js const path = require("path"); module.exports = { ... pluginOptions: { "style-resources-loader": { preProcessor: "less", patterns: [ //这个是加上自己的路径, //注意:试过不能使用别名路径 path.resolve(__dirname, "./src/assets/variable.less") ] } } ... }或者使用官网的自动导入在chainWebpack中引入https://cli.vuejs.org/zh/guid... 二、全局配置sass(直接配置vue.config.js) 注意:官网独爱sass,这种loader的形式只有sass才合适用,其他的(less、stylus)都会报错。 module.exports = { ... css: { loaderOptions: { sass: { // @是src的别名 data: ` @import "@/assets/variable.scss"; ` } } } ... }

June 5, 2019 · 1 min · jiezi

vuecli3添加模式配置多环境变量

vue-cli3配置多环境变量先挂官网描述:环境变量和模式 需求根据运行环境判断执行代码: 预发环境操作完成跳转地址与线上环境跳转地址不同线上环境添加埋点脚本实现Step1:在项目根目录中新建.env.uat.env.uat配置如下: VUE_APP_BUILD_TYPE=uatvue-cli中规定,只有以 VUE_APP_ 开头的变量会被 webpack.DefinePlugin 静态嵌入到客户端侧的包中。代码中可以通过process.env.VUE_APP_SECRET这样访问。 NODE_ENV 和 BASE_URL 是两个特殊变量,在代码中始终可用Step2:修改 package.json传递 --mode 选项参数为命令行覆写默认的模式。 "scripts": { "build": "vue-cli-service build", "build:uat": "vue-cli-service build --mode uat" }Step3:使用// 是否预发部署const IS_UAT = process.env.VUE_APP_BUILD_TYPE === 'uat'const _url = IS_UAT ? 'http://a.123.com' : 'http://b.123.com'// 是否添加埋点const IS_ADD_JAQ = process.env.NODE_ENV === 'production' && !IS_UATif (IS_ADD_JAQ && loginUser) addJaq(loginUser) ...优化到这,功能已经实现了。 美滋滋地打个包,妈呀,体积也太大了: 此处解决办法为强写NODE_ENV,最终.env.uat配置如下: NODE_ENV=productionVUE_APP_BUILD_TYPE=uat 这样子顺眼些了,但整个项目打包这部分还是有很大的优化空间,下期再干咯~

June 4, 2019 · 1 min · jiezi

vuecli3多页应用改造

需求一个平台P,包含产品a、b、c、d、e。各产品UI样式风格统一,且会用到公共配置(HOST、是否添加埋点js)、组件(头部导航、表格、搜索框)、方法(请求拦截、生成UUID)。 现状:由于历史遗留原因,各产品为独立SPA、各自维护,配置、组件也都自成一体,只是大概样式上保持了一致,但细节(比如同一面包屑样式,左边距5px、8px都有)都不一致。这种情况下,改组件、改配置都得一改改多个地方,且有些项目是vue-cli2、有些是vue-cli3,项目间依赖包的版本也不一致,维护起来非常不友好。 目标:整合各产品单页应用为MPA,提取公共文件(主题、配置、组件、方法),减少规范性东西的维护成本。 目录结构对比整合前 bds-bank-fe│ README.md││// 静态资源输出目录│└───dist│ └───index.html + static // 平台首页│ └───label // 产品a│ │ └───index.html + static│ └───metrics // 产品b│ └───service // 产品c│ └───help // 产品d││// 项目路径│└───help-center // 产品d└───portal-page // 平台首页└───service-doc // 产品c└───unify-label // 产品a└───unify-metrics // 产品b│ └───build│ └───config│ └───src整合后 │// 静态资源输出目录│└───dist│ └───index.html│ └───label.html│ └───metric.html│ └───service.html│ └───stocktake.html│ └───css│ └───js│ └───img├── public│ └───favicon.ico│ └───index.html││// 项目路径│├── src│   └── assets│   └── components│   ├── pages│   ├── index│   ├── label│   ├── metric│   ├── service│   ├── stocktake实现vue-cli 3.0官方支持多页,重点在于vue.config.js文件中pages这个配置项,每个页面单独配置entry、template、filename等。pages配置说明 ...

June 4, 2019 · 2 min · jiezi

vuelic-3-静态资源路径public

新上手的一个vue-lic项目,有几个纯文本的静态页面想直接丢进去,不知道要放哪里。 网上看了下别人的说法是放到static或者assets文件夹里,但那是以前版本的做法,饶了一天弯路之后终于搞清楚publice的作用! 在最新的vue-lic文档中有对public的说明:https://cli.vuejs.org/zh/guid... 看不明白的话听我以小白的方式讲一下: 以下是一个vue-lic项目结构图:可以看到public和src是同级的,之前我错误的把public放到src里面结果public下面的文件都引用不到了,这里需要注意。 然后把我的静态html文件丢进这里(其他静态资源文件也行)再通过绝对路径( '/xxx.html' )引用打包后就能在dist文件夹里看见啦!说明大功告成!

June 3, 2019 · 1 min · jiezi

快速搭建的webpackvue项目

快速搭建的webpack+vue项目!第一步: npm install -g @vue/cli第二步: npm install -g @vue/cli-init第三步: vue init webpack my-project会有一系列选项,询问项目名称等,可以默认(按Enter键),也可以自定义。 等待几分钟,安装成功:# Project initialization finished! 此时一个快速搭建的webpack+vue项目就构建成功啦! 下面来查看一下项目结构: tree .│ .babelrc│ .editorconfig│ .eslintignore│ .eslintrc.js│ .gitignore│ .postcssrc.js│ ii.txt│ index.html│ info.txt│ package.json│ README.md│├─build # webpack config files│ webpack.base.conf.js│ webpack.dev.conf.js│ webpack.prod.conf.js│ ...├─config│ index.js # main project config│ ...├─node_modules├─src│ │ App.vue # main app component│ │ main.js # app entry file│ ├─ assets # module assets (processed by webpack)│ │ ...│ ├─ components # ui components│ │ ...│ └─ router│ index.js│├─static # pure static assets (directly copied)└─test └─e2e │ nightwatch.conf.js │ runner.js │ ├─custom-assertions │ elementCount.js │ └─specs test.js第四步:进入项目文件: ...

June 3, 2019 · 1 min · jiezi

vue2脚手架组合iview精简版模板可用做PC后台系统模板

github项目地址:《vue2-cli-iview》 iview官方demo是自己配置的webpack,如果想拿iview2的来做后台模板,需要自己拆分本文已拆分好精简版iview使用vue2的后台精简模板,可用作PC后台管理系统模板,快速开发。 精简版图登录页 首页 错误页 更换颜色 锁屏页 如果对大家有帮助,麻烦在github给个star支持一下github项目地址:《vue2-cli-iview》

May 29, 2019 · 1 min · jiezi

初体验vuecli3x

以下是使用vue-cli3.x的一些总结,后续后持续更新1.查看官方文档https://cli.vuejs.org/zh/guide/ 2.安装注:若要使用 Vue CLI 3,需将 Node 版本升级至 8.9 及以上。 npm install -g @vue/cli//初始化项目vue create xx //你的项目名称注:之后的操作都在package.json(同目录)新建vue.config.js进行项目的配置 3.静态资源文件引入解决build静态文件引入错误的问题 module.exports = { publicPath:'./'}4.添加全局less文件在前端项目中,经常会用到相同的主题色。此时,我们需要存储这些变量,且将其全局引入。 安装less npm install less-loader less --save-dev安装style-resources-loader npm install style-resources-loader --save-dev//使用sass把less替换成less即可function addStyleResource(rule) { rule.use('style-resource') .loader('style-resources-loader') .options({ patterns: [ path.resolve(__dirname, 'src/assets/css/base.less')//你的文件目录 ] })}module.exports = { chainWebpack: config => { const types = ['vue-modules', 'vue', 'normal-modules', 'normal'] types.forEach(type => addStyleResource(config.module.rule('less').oneOf(type))) }5.rem和lib-flexible安装postcss-px2rem npm install postcss-px2rem --save-dev使用lib-flexible后配置px转换成rem module.exports = { css: { loaderOptions: { less: { javascriptEnabled: true }, postcss: { plugins: [require('postcss-px2rem')({ remUnit: 75 })] } } }}6.使用雪碧图安装webpack-spritesmith ...

May 27, 2019 · 1 min · jiezi

IPress-让你更流畅的书写-Spring-Boot-Vue-VueCli3-markdown

导语很久没有更新文章了, 最近参考showdoc.cc 写了一个 笔记(知识管理/博客)工具 IPress. 技术栈Spring Boot 2.x Mysql 8.x Vue 2.x Vue Router 2.x iview ui 3.x 前后端分离 通过 jwtToken 跨域认证演示地址:Ipress 部署在了码云的Pages上 项目源码获取:已上传 github 项目模块划分:IPress│├─ipress-core 用户权限登录模块 (80%)│├─ipress-pocket 业务功能模块(已完成)│├─ipress-run run 入口│└─ipress-ui 用户界面 (已完成)界面首页: pocket: pocket: 文件夹管理: 编辑器:

May 23, 2019 · 1 min · jiezi

vue项目添加多页面配置

公司使用vue-cli创建的vue项目在初始化时并没有做多页面配置,随着需求的不断增加,发现有必要使用多页面配置。看了很多vue多页面配置的文章,基本都是在初始化时就配置了多页面。而且如果使用这些实现,需要调整当前项目的目录结构,这点也是不能接受的。 最后,参考这些文章,在不调整当前项目目录结构实现了多页面的配置的添加。这里做下记录、总结,方便以后复用。如果还能有幸帮助到有同样需求的童鞋的话,那就更好了。 实现步骤添加新增入口相关文件;使用变量维护多入口;开发环境读取多入口配置;生产环境读取多入口配置;新增入口相关文件在src目录下新增一个page1文件夹,新建新页面的所需的相关文件(入口文件、HTML模板文件等)。我这边直接vue-cli初始化创建相关文件复制了一份到page1文件夹下。如下: ├─App.vue├─main.js├─page1.html // 这里模板文件名称需要与文件夹名称相同,方便输出模板读取├─router| └index.js├─components| └HelloWorld.vue├─assets| └logo.pngpage1/router/index.js需要对该页面的所有路由添加同文件夹名的公共路径,用于解析: import Vue from 'vue'import Router from 'vue-router'import HelloWorld from '@/page1/components/HelloWorld' // 这里也需要留意Vue.use(Router)export default new Router({ mode: 'history', base: '/', routes: [ { path: '/page1/', redirect: '/page1/index' }, { path: '/page1/index', name: 'HelloWorld', component: HelloWorld } ]})使用变量维护多入口我们在项目目录下的build/utils.js的最后exports一个指定多入口的对象。如下: // 这里,每个属性就是一个页面配置,指定该页面的入口文件// 如果需要添加,只需多增加一个属性// 属性名必和html模板文件名、目录名称相同exports.multipleEntrys = { page1: './src/page1/main.js'}之所以使用build/utils.js,是因为该文件在webpack.base.conf.js、webpack.prod.conf.js、webpack.dev.conf.js都用导入。 开发环境读取多入口配置首先,在build/webpack.base.conf.js中,我们把上面定义的入口添加进entry配置: entry: { app: './src/main.js', ...utils.multipleEntrys // entry添加该行 }然后,在build/webpack.dev.conf.js添加路径解析和多页面输出: // 添加解析,将historyApiFallback的属性修改如下: historyApiFallback: { rewrites: [ // 将所有多入口遍历成路径解析项 ...((()=>{ let writes = [] for(let prop in utils.multipleEntrys){ // 使用属性名匹配为正则 // 这就是上面“需要对该页面的所有路由添加同文件夹名的公共路径”的原因 let reg = new RegExp(`^/${prop}/`) writes.push({ from: reg, // 使用属性名读取模板文件 // 这就是上面“模板文件名称需要与文件夹名称相同”的原因 to: path.posix.join(config.dev.assetsPublicPath, `${prop}.html`) }) } return writes })()), // 匹配所有路径一定要在最后,否则该匹配之后的项,不会被执行 { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') } ], }// 在已经的HtmlWebpackPlugin中添加chunks配置,否则默认页面会注入所有页面的js文件...plugins: [ ... new HtmlWebpackPlugin({ filename: 'index.html', template: 'index.html', inject: true, // 增加此行, // 'app'为默认入口名称,如果你的默认入口不是'app' // 则这里需要替换 chunks: ['manifest', 'vendor', 'app'] }) ...]...// 在`devWebpackConfig`定义之后,紧接着添加多页面输出:for(let prop in utils.multipleEntrys){ devWebpackConfig.plugins.push(new HtmlWebpackPlugin({ filename: `${prop}.html`, // html模板路径,使用属性名作为文件夹名称 // 这是新页面文件夹名称需要和多入口配置变量属性名相同的原因 template: `./src/${prop}/${prop}.html`, inject: true, chunks: ['manifest', 'vendor', prop], }))}最后,添加多页面相互跳转链接: ...

May 22, 2019 · 2 min · jiezi

vuecli-源码阅读

vue-cli 源码阅读前一阵写了一个平时自己用的 React 模板项目 boone-react,想着以后每次写新项目的时候就可以直接拉取现成的模板就不用自己配置了。但完成后,就发现每次都需要 git clone 下来还是比较麻烦的,而且如果之后有不同的模板需求,不方便扩展,于是自己写了一个 CLI 工具 boone-cli,这样在本地安装执行相关命令就可以完成基本需求了。但感觉还是有很多不足,想着去看看之前用过多次的 vue-cli 是怎么实现的。 Tip:阅读的是 vue-cli 的 v2.9.6 版本。因为 CRA 和 vue-cli@3.0 都是整合了一个插件系统来完成的项目新建工作,重点就不在命令行工具了而是插件系统如何实现了,增加阅读负担,自己菜还找借口从项目结构开始把测试文件、构建配置文件、文档文件去除后,项目的源码结构如下。其中: package.json 不多说,注意里面的 bin 字段,这里定义了安装后执行的命令以及命令所对应的执行脚本bin 目录下是命令文件,在敲入 vue init 等命令后会执行对应的文件lib 目录下是一些自定义函数,会在各个执行脚本中用到分析完结构就知道了,主要需要看的就是 bin 和 lib 两个目录下的文件了。 ├── bin│   ├── vue│   ├── vue-build│   ├── vue-create│   ├── vue-init│   └── vue-list├── lib│   ├── ask.js│   ├── check-version.js│   ├── eval.js│   ├── filter.js│   ├── generate.js│   ├── git-user.js│   ├── local-path.js│   ├── logger.js│   ├── options.js│   └── warnings.js├── package.jsonbin 目录vue 脚本这里使用了 commander,主要用来处理命令行工具的开发。vue 这个脚本文件主要功能就是给用户提示,提示 vue-cli 工具的用法和所有命令。PASS! ...

May 15, 2019 · 11 min · jiezi

解决调用百度地图web服务api出现跨域问题vuestatus-240问题

跨域问题可参考这篇文章《vue-cli使用webpack代理,解决跨域问题》;如果需要查看多种跨域方法的,可参考这篇文章《九种跨域方式实现原理》 百度地图web服务api调用,出现status: 240问题(注意:如果没做跨域处理,是请求不到数据的,会报错) 调用web服务api,需要创建服务端的应用,再使用该key值;百度授权白名单可以设置0.0.0.0/0,不限制授权域名。

May 15, 2019 · 1 min · jiezi

vuecli使用webpack代理解决跨域问题

可以在vue-cli创建的项目目录config/index.js,找到dev.proxyTable属性,在上面写代理域名即可

May 15, 2019 · 1 min · jiezi

vuecli构建的小说阅读器

项目介绍主要页面1、首页home.vue分类展示书籍,幻灯片展示热门推荐2、搜索search.vue,上拉加载更多3、书籍详情book.vue加入书架、立即阅读,展示评论,同类书籍推荐4、书籍内容read.vue,获取目录,存储翻阅的章节位置,5、书架bookrack.vue,获取加入书架的书单 技术栈vue、vue-cli、axios、vue-router、vuex、localStorege 入口页面app.vue分成底部导航 跟 主视图容器 router-view首页tabbar/Home包含: components/sub/item 和 components/sub/search 、components/sub/header结构: banner切换 与 搜索 和 小说分类楼层 小说楼层单独定义了组件 components/sub/item , home循环楼层分类名称,并将楼层分类id传给item组件 :booklistId='{id:item._id}' , item组件用props: ["booklistId"] 接收分类id, 并根据分类id获取对应的数据item.vue mouted: this.getlist(this.booklistId.id);methods: getlist(id) { //每个分类id下对应的数据 子组件接收父组件传过来的id 获取对应的数据 bootd(id).then(res => { var arrdata = res.data.data; arrdata.map(item => { this.booklist.push(item.book); }); }); }小说详情页components/book/Book.vue包含: components/sub/yuedu 、mulu、pinglun、结构: 小说概况与简介,是否加入书架或者继续阅读 ,目录、评论、同类书籍推荐加入书架/立即阅读(yuedu.vue)组件 加入书架,获取书籍信息,并把相关书籍信息存放在书架中、存localbook.vue computed: { ...mapState(['calbook','shuajiabook']) //书籍信息 书架数据[] }, methods:{ addbook(){ this.flag=!this.flag var book= this.calbook; // calbook 是store里存储的书籍信息【 SHEFLBOOK 】 var carbook = JSON.parse(window.localStorage.getItem('book') || '{}') if(!this.flag){ //加入书架 carbook[book._id] = { cover: book.cover, flag:!this.flag, title: book.title, lastChapter:book.lastChapter, id: book._id, author:book.author, chapterIndexCache: 0, bookSource: 0, pageIndexCache: 0, } this.setbook(false) window.localStorage.setItem('book', JSON.stringify(carbook)) }else{ delete carbook[book._id] this.setbook(true) //设置的布尔值 window.localStorage.setItem('book', JSON.stringify(carbook)) } } }立即阅读时进入小说章节 `this.$router.push({name:'read',params:{id:this.booklinks}})`目录组件components/sub/mulu.vue ...

May 13, 2019 · 2 min · jiezi

打包优化从0到1搭建element后台框架优化篇

前言hello,咱又见了~~嘻嘻。本次主要来说说这个打包优化的问题。一个vue项目从开发到上线必须得经历打包过程,一个项目的打包优化与否都决定了你这个项目的运行速度以及用户体验。本次主要是针对vue.config,js的配置进行优化。项目地址 开发环境与生产环境开发环境与生产环境的配置也是开发中的必不可少的一环。本项目是由vue-cli3开发,vue-cli3深度集成了webpack,如果不熟悉vue-cli3可以先去官网看看相关配置。 开发环境在项目根目录下新建.env.development文件表明是开发环境。 VUE_APP_CURRENTMODE ="development" //当前的环境 VUE_APP_LOGOUT_URL="http://localhost:3000/" //开发环境的地址生产环境在项目根目录下新建.env.production文件表明是生产环境。 VUE_APP_CURRENTMODE ="development" //当前的环境 VUE_APP_LOGOUT_URL="xxx" //生产环境的地址当然你也可以自己创建一个测试环境.env.test,同样可以像上边一样配置。 环境运用那么接下来我们怎么用它呢?这里不得不说一下的是package.json里面的两个命令serve,build,其实对应的是全命令是vue-cli-service serve --mode development,vue-cli-service build --mode production,如果你想要在构建命令中使用开发环境变量,那么可以加入 "dev-build": "vue-cli-service build --mode development"接下来在vue.config.js运用它。 config.plugin('define').tap(args => { args[0]['process.env'].VUE_APP_LOGOUT_URL = JSON.stringify(process.env.VUE_APP_LOGOUT_URL) console.log(args[0]) return args; });这里有必要说下,这段代码是写在chainWebpack配置项下面。这段代码其实运用了两个webpack插件webpack-chain允许配置链式操作,以及webpack.DefinePlugin。 webpack-chain:尝试通过提供可链式或顺流式的 API 创建和修改webpack 配置。了解更多webpack.DefinePlugin:它的作用是定义全局常量,是常量。即在模块用它定义的全局常量,那么你就不能改变它。也就是说我定义了一个process.env.VUE_APP_LOGOUT_URL常量,在src文件夹下面都可以使用。了解更多分包(code splitting)首先思考,我们引入的第三方包与我们的业务代码一起打包会产生什么问题?顾名思义,我们的业务代码变动比较频繁,而我们引入的第三方包基本上不会变动。浏览器会有缓存,没有变动的文件会直接从缓存中读取,这也间接的优化了网站的访问速速。接下来配置vue.config.js, 分割第三方库 //代码分割 config.optimization.minimize(true); config.optimization.splitChunks({ chunks: 'all', cacheGroup:{ //vue2-editor单独打一个包 vueEdior: { name: 'vueEdior', test: /[\\/]node_modules[\\/]vue2-editor[\\/]/, priority: 10 // 优先级要大于 vendors 不然会被打包进 vendors }, //其余的第三方包打进vendor vendors: { test: /[\\/]node_modules[\\/]/, priority: -10 } } })分割共用文件组件是vue项目的重要组成部分。相当一部分组件都可以公用,在不同的文件中引入,因此我们可以将这部分公用的组件直接分割出来。 ...

May 11, 2019 · 2 min · jiezi

vue-实现搜索的结果页面支持全选与取消全选

演示地址,打开、搜索、随便点demo : http://msisliao.github.io/dem... 仓库代码 : https://github.com/msisliao/v... 安装vue-cli安装elementUI npm i element-ui -S在main.js 引入elementUI// main.jsimport ElementUI from 'element-ui'import 'element-ui/lib/theme-chalk/index.css'Vue.use(ElementUI)demo功能概览默认没有全选,搜索时支持全选与取消全选,将选择的数据添加到已选中,已选删除时改变当前搜索列表的状态与全选按钮的状态全选时全部追加到已选,取消全选时从已选中删除当前搜索的列表功能列表1、搜索时展示相应的数据列表,支持全选与取消全选,(默认展示所有数据时不支持全选) datas() { // 每次搜索的数据 根据下拉菜单的值的变化 if (this.value !== "") { return this.listItem.list.filter(item => { return item.BrandNames.includes(this.value); }); } else { return this.listItem.list; // 没有搜索的关键词时展示全部数据 } },2、搜索的下拉菜单去重 filDatas() { // 利用reduce 下拉菜单去重 var obj = {}; return this.listItem.list.reduce(function(item, next) { obj[next.BrandNames] ? "" : (obj[next.BrandNames] = true && item.push(next)); return item; }, []); }3、当前界面全选时添加到已选中,当前界面取消全选时,从已选的数据删除当前搜索出来的列表数据, ...

May 9, 2019 · 4 min · jiezi

VueCLI2x全家桶架构支持打包后自动部署到服务器构建案例

今天有时间分享一些平时自己开发上的一些构建配置,我们以Vue-CLI-2.x来构建开发环境。好,我们先来看一下我们要做哪些工作。现附上源码地址,https://github.com/749264345/... 1.Vue,Vuex,vue-router,axios通过CDN引入;优化打包后文件过大的问题2.开发环境区分开发,测试,生产;提高开发效率3.打包区分测试与生产4.实现项目打包后自动部署到远程服务器5.模块化构建vuex状态管理6.打包后自动清除console.log()7.项目默认基于Element-ui,对相关组件二次封装8.模块化构建axios请求响应拦截器一寸光阴一寸金,寸金难买寸光阴~废话不多说,直接撸起袖子就是干~~ 1.Vue,Vuex,vue-router,axios通过CDN引入在过去我们都习惯使用npm或者cnpm安装依赖,因为这种操作非常方便,但是有利必有弊,有些小伙伴在将项目打包后会发现打包后的js文件非常庞大,有些甚至达到了几兆,所以最终导致应用打开时首屏加载非常慢,因此我们可以使用传统的引入方式,也就是CDN引入。Vue,Vuex,vue-router,axios,这些均为静态资源,我们从它们官网下载适合的版本后放入项目根目录【static】文件夹,然后修改几个地方:首先,index.html <!--兼容ie--> <script src="./static/libs/polyfill.min.js"></script> <script src="./static/libs/eventsource.js"></script> <!--vue--> <script src="./static/libs/vue.js"></script> <script src="./static/libs/vue-router.min.js"></script> <script src="./static/libs/element-ui/element-ui.js"></script> <script src="./static/libs/axios.js"></script> <script src="./static/libs/vuex.js"></script>然后修改,build/webpack.base.conf.js module.exports = { externals: { 'vue': 'Vue', 'vuex': 'Vuex', 'vue-router': 'VueRouter', 'axios': 'axios' }, ...}到这里基本配置已经完成,最后一步需要在main.js中删除原先对这些模块的import操作即可。这样后再打包项目,你会发现页面非常丝滑,几乎秒开。 2.开发环境区分开发,测试,生产;提高开发效率在调试接口,或者debug的时候我们经常会切换环境,而且在打包的时候又要改成生产的接口,这样没有效率,所以我们可以做如下配置。在config/dev.env.js文件中, const TARGET = process.env.npm_lifecycle_event;//开发环境if (TARGET === 'dev') { var data = { NODE_ENV: '"dev"', API: '"http://www.dev.com"' }}//测试环境if (TARGET === 'test') { var data = { NODE_ENV: '"test"', API: '"http://www.test.com"' }}//生产环境if (TARGET === 'prod') { var data = { NODE_ENV: '"prod"', API: '"http://www.prod.com"' }}我们从process.env.npm_lifecycle_event中获得当前node执行的环境来区分项目运行的环境,这样我们可以用来区分接口环境,因此我们添加相关指令。在根目录package.json文件中, ...

May 5, 2019 · 3 min · jiezi

Vue-引入-AMap-高德地图

本文代码仅针对 Vue CLI 3.x 生成的项目有效,但是在第二步配置的时候,可以直接配置 webpack.externals,所以本引入思路是通用的,并不局限于该项目 资源AMap 准备-入门教程Vue CLI webpack 相关配置引入 AMap在 public/index.html 文件 </body> 前引入 <script type="text/javascript" src="https://webapi.amap.com/maps?v=1.4.14&key=您申请的key值"></script> 配置 Webpack项目根目录新建配置文件 vue.config.js,填入内容: module.exports = { configureWebpack: { externals: { AMap: "window.AMap" } }};在项目中使用新建 Index.vue 文件,填入内容: <template> <div> <div style="width: 100vw;height: 100vh" id="container"></div> </div></template><script>// eslint-disable-next-lineimport AMap from "AMap";export default { name: "Index", data() { return {}; }, mounted() { new AMap.Map("container", { resizeEnable: true, zoom: 11 }); }};</script>

April 28, 2019 · 1 min · jiezi

从0到1搭建element后台框架之权限篇

前言首先还是谢谢各位童鞋的大大的赞赞,你们的支持是我前进的动力!上周写了一篇从0到1搭建element后台框架,很多童鞋留言提到权限问题,这一周就给大家补上。GitHub 一、jwt授权认证现在大多数项目都是采用jwt授权认证,也就是我们所熟悉的token登录身份校验机制,jwt的好处多多,由于jwt是由服务端生成,中间人修改密串后,服务端会校验不过,安全有效。一般呆在请求头上的Authorization里面。前端童鞋一般获取token后通过vuex存储起来,随后数据持久化存到session中。 路由跳转验证token首先在路由跳转的时候需要验证vuex是否存储了token,如果没有token的话直接跳到登陆页面获取token。 if (to.path !== '/login' && !store.state.token) { next('/login') NProgress.done() // 结束Progress } else { next(); }请求拦截带上token详细请看项目中的router.js本地存在token之后,我们在每次请求接口的时候都需要带上token来验证token的合法性。 //在请求前拦截 if (store.state.token) { config.headers["Authorization"] = "Bearer " + store.state.token; }如果token不合法,全局错误处理,直接跳到登陆页面 case 401: messages("warning", "用户登陆过期,请重新登陆"); store.commit('COMMIT_TOKEN','') setTimeout(() => { router.replace({ path: "/login", query: { redirect: router.currentRoute.fullPath } }); }, 1000); break;详细代码看项目中的request.js 二、菜单权限本项目中,我主要是通过后端传过来的角色类型来判断导航菜单的显示与隐藏。也就是说首先前端请求接口,后端返回token,以及对应的角色,比如项目中用admin登陆的话,roles=['admin'],用user登陆的话roles=['user']。接下来我这边设计了一份菜单表和一份路由表,路由表主要是为了注册路由,不需要考虑层级关系。而菜单表需要考虑层级关系,里面可以配置主菜单,子菜单,图标等等一系列的东西,当然菜单表最好是通过接口数据从后端传过来。值得注意的是无论是菜单表,还是路由表,里面都有一个meta配置项。里面可以配置我们的角色权限。路由表对应的菜单表角色权限需要一致。没有配置角色权限的菜单默认都开放。 menu.js { icon: "el-icon-question", index: "premission", title: "权限测试", subs: [{ index: "permission", title: "菜单测试", meta: { roles: ['admin'] } }, { index: "permissionBtn", title: "按钮权限", }, ] }router.js { path: '/permission', component: getComponent('permission', 'permission'), meta: { title: '菜单权限', roles: ['admin'] } },根据角色过滤菜单现在我们开始编写菜单逻辑,进入Aside.vue,首先根据角色过滤菜单表menu.js ...

April 26, 2019 · 2 min · jiezi

Vuecli简单使用

Vue-cli3.X创建项目1.环境要求安装Vue-cli3.x的前置条件:Node.js以Windows为例安装Node.js,百度 “Node.js官网” 或”Node.js中文网”均可 ,如无特殊要求 下载安装 LTS版(长期支持版,该版本已满足Vue CLI官网所需要求版本要求)一路Next即可,一般无需更改默认安装设置安装完毕在开始菜单内即可找到一个名为 Node.js 的文件夹如下图注:Node.js内可直接运行js基础代码(非DOM等相关代码)**而我们需要使用的是 Node.js command prompt 2.Vue-CLI安装:官方命令 npm install -g @vue/cli 注:@不能少,少了@安装的不是3.x版本而是1.x、2.x版本,若已经安装了旧版本则需卸载旧版本然后再安装新版本 旧版本卸载命令 npm uninstall vue-cli -g 补充:vue-cli 3.x 卸载命令 npm uninstall @vue/cli -g (如果需要可使用)国内下载速度比较慢查看npm当前下载镜像,命令为:npm get registry结果> https://registry.npmjs.org/如果嫌弃下载慢可以切换为淘宝镜像或者直接安装cnpm并更换淘宝镜像,命令如下: npm config set registry http://registry.npm.taobao.org/npm install -g cnpm --registry=https://registry.npm.taobao.org等待安装完毕 2.1使用脚手架创建项目建议先考虑项目文件夹储存的位置并进入相关位置,以桌面为例cd desktop如果无需更改位置,请跳过;如果需返回上级目录 cd.. 即可,其他cmd命令可自行百度创建项目的两种方式: 一、直接命令行创建创建项目命令: vue create 项目名 自己起个名字即可,但请注意不能有大写字母,否则报错:Warning: name can no longer contain capital lettersvue create learn √接下来会问你选择那种配置(会显示所有保存过的配置,首次使用只会显示 default(babel,eslint) 以及 Manually select features)可选自己之前创建过的或选择官方默认配置或者手动选择)选择Manually select features 将出现以下内容方向键 控制上下 空格选择 A 全选 I反转选择选择好大体的功能/插件之后 回车 接着会让你选择细分的特性比如 Linter/Formatter 下:在保存时进行代码检测Babel、PostCSS、ESLint等配置文件存放位置,选择单独保存在各自的配置文件中Pick a CSS pre-processor(css预处理语言)下 有SCSS/SASS、LASS、Stylus还有TS、PWA、Roter(vue 路由管理;SPA必带)、Vuex(vue状态管理)、测试(Unit Testing、E2E Testing)等等,均可按需选择最后会询问你 是否保存为未来项目的预设配置 如果保存需要输入名称等待项目创建...项目创建好后按提示进入项目,并启动项目cd learn 进入后 npm run serve这两个地址均可访问,第二个地址也并不能对外访问,应该是没做好端口映射,那这个地址用来干嘛的? ...

April 24, 2019 · 1 min · jiezi

基于vuecli30构建功能完善的移动端架子

基于vue-cli3.0构建功能完善的移动端架子,主要功能包括webpack 打包扩展css:sass支持、normalize.css、_mixin.scss、_variables.scssvw、rem布局跨域设置eslint设置cdn引入路由设计、登录拦截axios、api 设计vuex状态管理项目地址: vue-cli3-H5demo地址: https://zhouyupeng.github.io/vuecli3H5/#/ webpack 打包扩展vue-cli3.*后目录结构大改,去除了以往的build,config文件夹,要实现配置的改动在根目录下增加vue.config.js进行配置 css:sass支持、normalize.css、_mixin.scss、_variables.scss使用的css预处理器是sass,对于css mixin,变量这里做了全局引入,并且引入normalize.css 使HTML元素样式在跨浏览器上表现得的高度一致性vue.config.js配置 css: { // 是否使用css分离插件 ExtractTextPlugin extract: true, // 开启 CSS source maps? sourceMap: false, // css预设器配置项 // 启用 CSS modules for all css / pre-processor files. modules: false, sass: { data: '@import "style/_mixin.scss";@import "style/_variables.scss";' // 全局引入 } } }vw、rem布局对于移动端适配方案使用的是网易新闻的方法,使用vw + rem布局 /**750px设计稿 取1rem=100px为参照,那么html元素的宽度就可以设置为width: 7.5rem,于是html的font-size=deviceWidth / 7.5**/html { font-size: 13.33333vw}@media screen and (max-width: 320px) { html { font-size: 42.667PX; font-size: 13.33333vw }}@media screen and (min-width: 321px) and (max-width:360px) { html { font-size: 48PX; font-size: 13.33333vw }}@media screen and (min-width: 361px) and (max-width:375px) { html { font-size: 50PX; font-size: 13.33333vw }}@media screen and (min-width: 376px) and (max-width:393px) { html { font-size: 52.4PX; font-size: 13.33333vw }}@media screen and (min-width: 394px) and (max-width:412px) { html { font-size: 54.93PX; font-size: 13.33333vw }}@media screen and (min-width: 413px) and (max-width:414px) { html { font-size: 55.2PX; font-size: 13.33333vw }}@media screen and (min-width: 415px) and (max-width:480px) { html { font-size: 64PX; font-size: 13.33333vw }}@media screen and (min-width: 481px) and (max-width:540px) { html { font-size: 72PX; font-size: 13.33333vw }}@media screen and (min-width: 541px) and (max-width:640px) { html { font-size: 85.33PX; font-size: 13.33333vw }}@media screen and (min-width: 641px) and (max-width:720px) { html { font-size: 96PX; font-size: 13.33333vw }}@media screen and (min-width: 721px) and (max-width:768px) { html { font-size: 102.4PX; font-size: 13.33333vw }}@media screen and (min-width: 769px) { html { font-size: 102.4PX; font-size: 13.33333vw }}@media screen and (min-width: 769px) { html { font-size: 102.4PX; #app { margin: 0 auto } }}vue.config.js配置 ...

April 24, 2019 · 6 min · jiezi

vue-cli的简单实现

这个demo我是模仿Vue-CLI 2.0写的一个简单的构建工具,3.0的源码还没去看,所以会有不同的地方。 已经上传到github上了 先安装开发依赖的工具npm i commander handlebars inquirer metalsmith -Dcommander:用来处理命令行参数 handlerbars:一个简单高效的语义化模板构建引擎,比如我们用vue-cli构建项目后命令行会有一些交互行为,让你选择要安装的包什么的等等,而Handlerbars.js会根据你的这些选择回答去渲染模版。 inquirer:会根据模版里面的meta.js或者meta.json文件中的设置,与用户进行一些简单的交互以确定项目的一些细节。 metalsmith:一个非常简单的可插拔的静态网站生成器,通过添加一些插件对要构建的模版文件进行处理。 安装完后就能在package.json中看到如下的依赖 项目目录结构 其中template-demo里面包含了本次要构建的项目模版templae,和meta.js文件 代码编写1.bin/dg.js之后在命令行下面运行 node bin/dg.js xxx xxx就可以构建项目了。两个 xxx的地方 第一个是项目的模版,第二个是要输入到哪个目录下也就是要构建的项目名称 // dg.jsconst program = require('commander')const path = require('path')const chalk = require('chalk') // 终端字体颜色const inquirer = require('inquirer')const exists = require('fs').existsSync // 判断 路径是否存在const generate = require('./lib/generate')/** * 注册一个help的命令 * 当在终端输入 dg --help 或者没有跟参数的话 * 会输出提示 */program.on('--help', () => {{ console.log(' Examples:') console.log() console.log(chalk.gray(' # create a new project with an template')) // 会以灰色字体显示 console.log(' $ dg dgtemplate my-project')}})/** * 判断参数是否为空 * 如果为空调用上面注册的 help命令 * 输出提示 */function help () { program.parse(process.argv) //commander 用来处理 命令行里面的参数, 这边的process是node的一个全局变量不明白的可以查一下资料 if (program.args.length < 1) return program.help()}help()/** * 获取命令行参数 */let template = program.args[0] // 命令行第一个参数 模版的名字const rawName = program.args[1] // 第二个参数 项目目录/** * 获取项目和模版的完整路径 */const to = path.resolve(rawName) // 构建的项目的 绝对路径const tem = path.join(process.cwd(), template) //模版的路径 cwd是当前运行的脚本是在哪个路径下运行/** * 判断这个项目路径是否存在也就是是否存在相同的项目名 * 如果存在提示 是否继续然后运行 run * 如果不存在 则直接运行 run 最后会创建一个项目目录 */if (exists(to)) { inquirer.prompt([ // 这边就用到了与终端交互的inquirer了 { type: 'confirm', message: 'Continue?', name: 'ok' } ]).then(answers => { if (answers.ok) { run () } })} else { run ()}/** * run函数则是用来调用generate来构建项目 */function run () { if (exists(tem)) { generate(rawName, tem, to, (err) => { if (err) console.log(err) // 如果构建失败就调用的回调函数 }) }}注释说明 都在代码里面了。 ...

April 22, 2019 · 4 min · jiezi

Vue项目构建持续集成阿里云CDN

CDN加速是Web应用性能优化和用户体验提升的至关重要的一环,当一个项目构建部署时,就需要考虑到如何高效的去完成相关资源的CDN部署。本文以一个基于 vue-cli3 构建的项目实例,来简单讲解如何配合Teamcity,自动进行阿里云CDN资源部署和持续集成。项目构建vue-cli3 默认支持将项目以 test、development、production 三种模式构建,其中 production 模式将在 build 后生成 dist目录。我们在项目路径下插入 .env.[mode] 格式的文件就可以实现自定义模式。通常,默认的构建模式无法满足项目研发需求。一个项目至少需要包含本地调试 - 即开发过程中的 development 模式,不生成 dist 静态目录,使用 vue-dev-server运行项目;测试环境 - 即基本的集成测试,需要文件静态化,部署到测试环境;线上环境 - 即用户环境,也需要文件静态化,并做CDN加速等性能优化措施;按照这个模型,我们需要自定义一个 deploy 模式,来实现和普通 production打包后,资源引入路径的区别。首先,环境创建在项目根目录下创建 .env.deploy 文件,添加内容如下:NODE_ENV=productionDEPLOY=onlineNODE_ENV的设置代表webpack构建时使用production模式,即会生成 dist静态目录。DEPLOY的设置,是一个我们定义的变量,用于在配置中区分deploy和production模式。其次,配置文件在 vue.config.js 中,配置 BASE_URL// 根据自定义的变量来进行内容设置let BASE_URL = ‘/‘switch(process.env.DEPLOY) { case ‘online’: BASE_URL = ‘http://web-cdn.xxx.com/' break default: BASE_URL = ‘/’}module.exports = { publicPath: BASE_URL, ….}该配置会使得当程序使用 deploy 模式运行时,打包的资源根路径为我们的CDN地址。最后,构建命令在 package.json 中,配置使用 deploy 模式的打包命令"scripts": { “build”: “vue-cli-service build”, “deploy”: “vue-cli-service build –mode deploy”, …}当用户执行 npm run build 时,会生成以 / 为资源路径的文件;当用户执行 npm run deploy 时,生成 index.html 中的资源路径就变成了我们配置的CDN路径。<!DOCTYPE html><html> <head> <meta charset=utf-8> <meta http-equiv=X-UA-Compatible content=“IE=edge”> <meta name=viewport content=“width=device-width,initial-scale=1”> <link rel=icon href=http://web-cdn.xxx.com/favicon.ico> <title>Demo</title> <link href=http://web-cdn.xxx.com/css/chunk-0fabbc4c.08fa0fd2.css rel=prefetch> <link href=http://web-cdn.xxx.com/css/chunk-1025f268.0dc416de.css rel=prefetch> <link href=http://web-cdn.xxx.com/js/app.84dcc9e6.js rel=preload as=script> </head> <body> <div id=app></div> <script src=http://web-cdn.xxx.com/js/chunk-vendors.614ecc0c.js></script> <script src=http://web-cdn.xxx.com/js/app.84dcc9e6.js></script> </body></html>阿里云CDN配置和上传接下来,我们要做的就是配置一个CDN,并能够把这些资源传上去。首先,在阿里云上配置CDN,做好域名CNAME解析,并获取到阿里云的 accessKeyId、accessKeySecret、Region、BucketName等信息,然后选择一种语言,写好上传脚本。这里我们以Node脚本为例:// oss-deploy.jslet OSS = require(‘ali-oss’)let fs = require(‘fs’)let client = new OSS({ region: ‘oss-cn-hangzhou’, accessKeyId: ‘xxx’, accessKeySecret: ‘xxx’, bucket: ‘xxx’})// 使用async+await方法,实现同步化,方便在失败后重试处理async function put(fileName) { try { let result = await client.put(fileName, ‘../dist/’ + fileName) console.log(‘File Upload Success: ‘, fileName) } catch (e) { console.log(‘File Upload Failed: ‘, fileName) // 这里省略异常/失败的重试 }}// 读取打包后的 dist 路径,按照原文件夹结构,进行上传let readFileList = (path, filesList) => { let files = fs.readdirSync(path) files.forEach(itm => { if (itm) { let stat = fs.statSync(path + itm) if (stat.isDirectory()) { readFileList(path + itm + ‘/’, filesList) } else { filesList.push(path + itm) } } }) return filesList}let dist = readFileList(’../dist/’, [])// 递归执行文件上传操作let i = 0, l = dist.lengthlet uploadAsset = () => { if (i < l) { let name = dist[i].split(’../dist/’)[1] put(name) i++ uploadAsset() }}uploadAsset()执行npm install –save-dev ali-ossnode oss-deploy.js即可看到文件已经被上传到了CDN路径下。持续集成上面的两个模块,已经实现了基本的CDN部署。但我们在项目开发的时候,肯定不希望每次 build完,都去自己执行上传CDN,再去服务器上部署。这里我们再把 TeamCity上实现自动build、一键上线的流程简单阐述。TeamCity上的执行脚本如下:cd /apps/kaleido-cms/git pull -f origin masternpm installnpm run deploygit add dist/*git commit -m “Deploy"git push origin mastercd /apps/kaleido-cms/deploynode oss-deploy.jsssh root@10.0.0.1 “./deploy_cms.sh"ssh root@10.0.0.2 “./deploy_cms.sh"因为线上服务通常是集群模式,而 webpack在不同服务器执行build,会产生不同的哈希值版本号,会导致远程资源无法获取到。所以我们需要在持续集成部署的服务器上做build操作,生成dist路径,上传到git和cdn。最后再到集群的每个服务器上拉取静态文件即可。补充:在同一台服务器上,只要文件完全不变,我们使用vue-cli3构建生成的最终文件的哈希值版本号就不会产生改变。因此,对于用户来说当我们更新版本时,并不会对用户造成所有缓存文件失效的性能和体验影响。在阿里云的CDN上,是使用协商缓存的ETag来进行文件资源缓存,因此重名新文件覆盖旧文件时,如文件内容完全一致,Etag也会保持一致,对用户来讲也不必担心缓存问题;如文件发生变更,用户协商缓存也将无法命中,就会取新的资源文件。有些方法是把静态资源的请求发到Nginx,然后再转发到CDN地址。笔者认为,这样会造成所有资源需要重定向、并且在Nginx上无法设置缓存信息,性能上不如本文介绍的直接构建生成CDN地址的HTML文件的方法。通过这套操作,最终我们实现了在TeamCity上,一键执行打包、上传CDN、部署的整个流程。 ...

April 18, 2019 · 2 min · jiezi

为VUE 脚手架中自定义title标签页小图标

效果如图所示:一、 在项目index.html同级目录下添加favicon.ico文件二、 在项目index.html中引入<link rel=“shortcut icon” type=“image/x-icon” href="./favicon.ico" />三、 配置webpack配置文件(build文件夹下面)在下面两个配置文件中加入:favicon: path.resolve(’./favicon.ico’)具体位置:1.webpack.prod.conf.js new HtmlWebpackPlugin({ filename: config.build.index, template: ‘index.html’, favicon: path.resolve(’./favicon.ico’), inject: true, }), 2. webpack.prod.dev.jsnew HtmlWebpackPlugin({ filename: process.env.NODE_ENV === ’testing’ ? ‘index.html’ : config.build.index, template: ‘index.html’, favicon: path.resolve(’./favicon.ico’), inject: true, minify: { removeComments: true, collapseWhitespace: true, removeAttributeQuotes: true // more options: // https://github.com/kangax/html-minifier#options-quick-reference }

April 17, 2019 · 1 min · jiezi

Vue-CLI(3.X)项目中实现分环境请求API

Vue脚手架升级到3后,生成的项目结构有了一些改变,最近做的一个项目用了新版的脚手架,借此,记录一下如何配置实现分环境配置请求不同的后端service地址。一、项目结构如果你的vue-cli版本还是老版本,请先卸载原来的版本(npm uninstall vue-cli -g 或 yarn global remove vue-cli),再安装新版本(npm install -g @vue/cli 或 yarn global add @vue/cli)。新版本生成的项目结构如下图相比之下,少了build和config文件夹,因此配置的方式也不一样二、目的为什么要把项目进行分环境配置呢?这在实际的项目开发中是很有必要的,项目上线(production)前需要有一个经过反复测试的稳定版(verification)本,而开发者需要有另一个环境(dev)进行开发和自测,这样才不会影响到稳定的环境……(这些是我结合自己实际的项目经验总结出来的,或许大家有不同的经历)所以,在前后端分离的项目里,前端和后端都要配置不同的环境。因此,就有这一篇文章,记录一下个人的实践。三、配置进入正题,让我们参考官方文档愉快地配置吧~package.json文件 模式是 Vue CLI 项目中一个重要的概念。比如我们在package.json文件内写一个这样的脚本 如果我们用命令行’npm run serve’启动项目,就表示当前项目的模式是’qa’。.env.XX 定义好了模式之后,怎么把它和项目环境联系在一起呢?我们需要在项目的根目录下创建名为.env.[mode]的文本文件,在这里我们创建.env.qa文件,那么当项目启动时,在这个文件里声明过的变量就会在qa模式下被载入。因此,我们可以声明当前模式下的NODE_ENV。注意:只有以 VUE_APP_ 开头的变量会被 webpack.DefinePlugin 静态嵌入到客户端侧的包中。除了 VUE_APP_* 变量之外,在你的应用代码中始终可用的还有两个特殊的变量:NODE_ENV & BASE_URL。NODE_ENV 我们可以通过process.env.NODE_ENV获得到在相应模式下的.env.[mode] 内配置的值; 在html文件中,参考生成的模板代码,可以这样写↓四、验证接下来,要验证我们用命令“npm run serve”启动项目,是否能获取到对应模式下的环境配置,直接上图好了。我们已经配置成功了,接下来调用api就要用到axios或者其他的工具,按照相应的配置方式进行配置就搞定啦(^-^)V

April 16, 2019 · 1 min · jiezi

入手vue-cli 3.x

笔者环境 macOS node v8.11.3准备工作首先查看本地版本注:vue-cli需要要8.9+版本,我使用的n模块,进行node版本管理。因为之前曾经安装2.x版本 所以先执行卸载npmnpm uninstall vue-cli -g使用yarnyarn global remove vue-cli卸载完成后 重新使用 npm或者yarn进行安装npm install -g @vue/cli#或者使用yarn global add @vue/cli现在 我用yarn成功安装3.5.5版本项目创建vue create yourProject第一个选择是选择默认设置还是去手动选择功能在这里我选择了默认的包含了基本的Babel+ESLint的预制和yarn当然也可以选自己定制babel:使用babel将最新版的js语法进行转换typescript:使用TypeScript写源码PWA:渐进式WEB应用Router:使用vue-routerVuex:使用vuexCSS Pre-processors:css预处理器选择Linter / Formatter:代码规范选择Unit Testing:单元测试E2E Testing:e2e测试以上就是项目的根目录,可以看到跟以前相比变得更加简洁执行build启动项目在vue-cli的项目中,@vue/cli-service 安装了一个名为 vue-cli-service 的命令。可以在 npm scripts 中以 vue-cli-service、或者从终端中以 ./node_modules/.bin/vue-cli-service 访问这个命令。npm run serve# 或者yarn serve# 进行调用以下说明参考官方文档1.vue-cli-service serve [options] 【entry】(启动开发服务器)选项:–open 在服务器启动时打开浏览器–copy 在服务器启动时将 URL 复制到剪切版–mode 指定环境模式 (默认值:development)–host 指定 host (默认值:0.0.0.0)–port 指定 port (默认值:8080)–https 使用 https (默认值:false)2.vue-cli-service build [options] 【entry|pattern 】(dist 目录产生一个可用于生产环境的包)选项:–mode 指定环境模式 (默认值:production)–dest 指定输出目录 (默认值:dist)–modern 面向现代浏览器带自动回退地构建应用–target app | lib | wc | wc-async (默认值:app)–name 库或 Web Components 模式下的名字 (默认值:package.json 中的 “name” 字段或入口文件名)–no-clean 在构建项目之前不清除目标目录–report 生成 report.html 以帮助分析包内容–report-json 生成 report.json 以帮助分析包内容–watch 监听文件变化3.vue-cli-service inspect [options] […paths](审查项目的vue-cli webpack config)选项:–mode 指定环境模式 (默认值:development)4.npx vue-cli-service help 查看所有命令。下面我们来简单使用下这样通过命令行工具 我们使用的vue-cli3 构建的项目成功在本地8888端口 运行起来了后续文章内容都很简单基础,后续会跟随这个演示项目进行更新。 ...

April 11, 2019 · 1 min · jiezi

vue-cli3 开启HTTPS

项目里边准备试试html5的录音。然后调研一波,发现大坑:必须使用HTTPS才能录音。然后就想着本地模拟HTTPS录音。项目用的vue-cli3,折腾一波,发现开启非常简单:创建配置文件 项目根目录新建 vue.config.js 文件。粘贴代码module.exports = { devServer: { https: true }}不过,好像模拟的假的HTTPS,调用api还是会报错。然后太过麻烦,放弃这个录音feature。

April 10, 2019 · 1 min · jiezi

Vue组件之间通信,父到子,子到父,非父子组件之间数据传递梳理

一、父组件=》子组件传递数据1、子组件在props中创建一个属性,用以接收父组件传过来的值2、父组件中注册子组件3、在子组件标签中添加子组件props中创建的属性4、把需要传给子组件的值赋给该属性二、子组件=》父组件传递数据当子组件需要向父组件传递数据时,就要用到自定义事件。1、子组件中需要以某种方式例如点击事件的方法来触发一个自定义事件2、将需要传的值作为$emit的第二个参数,该值将作为实参传给响应自定义事件的方法3、在父组件中注册子组件并在子组件标签上绑定对自定义事件的监听三、非父子组件传递数据1、新建一个eventBus.js文件,在里面新建一个vue实例,这个实例就承担起了组件之间通信的桥梁了,也就是中央事件总线2、然后给每个子组件绑定一个方法(触发时候发布eventBus),在每个子组件做一个订阅的监控,触发绑在created里的方法执行在通信中,组件之间传值,他们都有一个共同点就是有中间介质,子向父的介质是自定义事件父向子的介质是props中的属性非父子组件的介质是中央事件总线 抓准这三点对于组件之间通信就好理解了vue-cli创建的项目,附上精简的代码与图片:HelloWorld.vue<template> <div class=“hello”> <h1>hello标题</h1> <!– // 在子组件标签child-aa上绑定myEvent对自定义事件的监听 –> <child-aa :myProp=“toChildA” @myEvent=“touchMe”></child-aa> <div>孩子,你贵姓:{{getByChildA}}</div> <child-bcd :myProp=“toChildA” @myEvent=“touchMe”></child-bcd> </div></template><script>import childAa from ‘./childA’import childBcd from ‘./childBcd’export default { name: ‘HelloWorld’, data () { return { toChildA: ‘给子组件childA传字符串内容’, // 把需要传给子组件的值赋给该属性 getByChildA: ’’ } }, components: { childAa, // 父组件中注册子组件 childBcd }, methods: { touchMe(obj) { this.getByChildA = obj.age } }}</script>childA.vue<template> <div class=“childA”> <h3>这里是childA</h3> <div> {{myProp}} </div> <button @click=“doSomething”> 给父组件传个信息 </button> <h3>兄弟组件传什么过来了:{{brotherInfo}}</h3> </div></template><script>import $bus from ‘../untils/eventBus’export default { name: ‘childA’, data () { return { brotherInfo: ’’ } }, props: { myProp: { type: String // 子组件在props中创建一个属性,用以接收父组件传过来的值 } }, methods: { doSomething() { // 子组件中需要以某种方式例如点击事件的方法来触发一个自定义事件 this.$emit(‘myEvent’, {age: ’lihongwei’}) // 将需要传的值作为$emit的第二个参数,该值将作为实参传给响应自定义事件的方法 } }, created() { $bus.$on(‘myEvent’,(brotherInfo) => { this.brotherInfo = brotherInfo }) }}</script><style scoped>.childA{ padding: 30px; border: 5px solid #ddd;}</style>childBcd.vue<template> <div class=“childBcd”> <h3>这里是childBcd</h3> <button @click=“toBrother”> 给chidA传个信息 </button> </div></template><script>import $bus from ‘../untils/eventBus’export default { name: ‘childBcd’, data () { return { } }, methods: { toBrother() { $bus.$emit(‘myEvent’, ‘兄弟,你好’) } }}</script><style scoped>.childBcd{ padding: 30px; border: 5px solid #ddd;}</style>eventBus.jsimport Vue from ‘vue’export default new Vue() ...

April 9, 2019 · 1 min · jiezi

vue-cli 最强指南

今天在这篇文章里,会对 vue-cli 的功能做个详细的整理,把 vue-cli 所有的功能都列出来。注:这个是官网连接:https://cli.vuejs.org/zh/guide/ ,建议多看细看不但要看还要多想,这里的介绍才是最全最准确的。①.vue-cli 是什么?vue-cli 又称为vue 脚手架,(我发现在起名这件事上前端从来就没输过)这个名字很通俗易懂。百度百科对脚手架的解释是:脚手架是为了保证各施工过程顺利进行而搭设的工作平台。其实基建工程和软件工程有很多东西都是相通的,软件工程中的很多开发思想和管理方法也是从基建那边引入的。在前端vue框架中引入脚手架这个名词我就觉得非常好。另外从百度百科的解释上看,也能大致猜出 vue-cli 在项目中是做什么用的。vue-cli是一个工作平台,在这个平台里面可以对项目开发进行高效的管控,使项目开发更符合标准,即使多人同时开发也能保证代码规范要求一样。在vue-cli这个工作平台里,多人协作开发效率更高,产品经理再也不用担心我写的代码与小伙伴的不兼容了。因为有了这些优秀的框架前端也有机会能体验到工程化编程了。其实我感觉最牛之处还是在项目迁移与备份方面。现在有了vue-cli只需要一个配置文件(package.json)和vue-cli中的几个命令就能搭建出来一个同样的脚手架(工作平台)出来。前提是得在你的电脑中先安装好 vue-cli。②.vue-cli 安装运行命令:cnpm install -g vue-cli vue-cli 安装之前先确定你的电脑中已经安装好了nodejs,至于nodejs和怎么安装可以参考我的上一篇文章:走进vue2.0大观园。如果已经安装好了nodejs,进入你的工作目录‘E:WorkSpacevue2.0-tutorial’,打开命令窗口运行命令:cnpm install –g vue-clicnpm 安装命令:npm install -g cnpm –registry=https://registry.npm.taobao.org注:cnpm 是淘宝的安装镜像,在速度上会快很多 -g 是全局安装vue-cli 安装完成后,就可以使用vue 命令进行项目构建搭建一个项目平台了。③.vue-cli 构建项目运行命令:vue init webpack your-project在这个命令里有个混入了一个奇怪的东西:webpack,webpack是什么?为什么在vue的命令里会出现webpack这个指令?先看一下官网:https://www.webpackjs.com/从图上可以看出来,左侧的脚本、样式、图片、表、资源等文件经过webpack 后变成了简单的三类四个文件:样式、脚本、图片。so,webpack的作用就是对项目中的静态资源文件进行打包操作,按照类别进行归纳集结。经过webpack打包之后的文件结构更清晰明了,最重要的是可以直接在浏览器中运行。因为webpack 已经集成到vue-cli中了,不需要单独安装,但是webpack4.X之后的版本需要安装webpack依赖,运行命令:cnpm install webpack webpack-cli -g输入命令:vue init -h可以看到有两种构建项目的方法可供选择,第一中就是我们用的这种,这种构建的项目是使用官方的模板进行构建的,第二种 vue init username/repo my-porject 是使用github上的模板进行构建的。这里我们我们选择的就是第一种。项目构建时配置的信息详情如下:Project name :项目名称,可以自定义,直接回车默认是指令中指定的项目名Project description :项目描述,也可直接点击回车,使用默认名字Author:作者,可以自己指定,也可直接回车Runtime + Compiler: recommended for most users 运行加编译,既然已经说了推荐,就选它了Runtime-only: about 6KB lighter min+gzip, but templates (or any Vue-specificHTML) are ONLY allowed in .vue files - render functions are required elsewhere仅运行时,已经有推荐了就选择第一个了Install vue-router? (Y/n) 是否安装vue-router,这是官方的路由,大多数情况下都使用,这里就输入“y”后回车即可。Use ESLint to lint your code? (Y/n) 是否使用ESLint管理代码,ESLint是个代码风格管理工具,是用来统一代码风格的和标准的,这里我选择了“n”不安装。Setup unit tests with Karma + Mocha? (Y/n)是否安装单元测试。我选择了“n”不安装。Setup e2e tests with Nightwatch(Y/n)? 是否安装e2e测试。我选择了“n”不安装。命令运行完成后,进入项目目录会看到多了很多的文件,接下来就需要在这个基础上进行项目开发。比直接进行文件夹创建和新建文件简单多了吧。④.vue-cli 配置讲解项目构建完成后一般是不需要再做额外的配置的,在命令行中输入命令:cnpm run dev 进行项目启动,然后可以在浏览器中打开就可以。但是我还想把一些基本的配置在这里做个介绍,这样对这个构建完的项目如可配置和运行的能有个初步的了解。用IDE导入刚才构建好的项目,我在这里用的是visual studio code,功能能满足日常开发需要,最重要的是免费,不用担心软件过期全网扒拉着找注册码了,这种痛用过破解版的都会懂。项目目录结构如下图所示:我在截图中用红框标出了几个重点,看看都是什么?config:这里就是整个项目的配置中心,全局配置都是在这里做的。dev.env.js:开发环境使用的变量index.js:项目运行的配置信息,比如端口、文件的生成路径、资源的存放目录prod.env.js:生产环境使用的变量// index.js 文件 ‘use strict’ // 启用严格模式// Template version: 1.3.1// see http://vuejs-templates.github.io/webpack for documentation.const path = require(‘path’)module.exports = { dev: { // 资源路径 assetsSubDirectory: ‘static’, // 静态资源文件子目录 assetsPublicPath: ‘/’, // 公共静态资源文件 proxyTable: {}, // 代理列表,在做跨域请求时会使用到 // 开发环境配置项 host: ’localhost’, // 主机地址可以设置成:localhost/127.0.0.1/...(本机IP) port: 8080, // 可以自定义,如果改端口被占用会启用一个新的端口 autoOpenBrowser: false, // 是否允许自动打开浏览器 errorOverlay: true, notifyOnErrors: true, poll: false, // /** * Source Maps / // https://webpack.js.org/configuration/devtool/#development devtool: ‘cheap-module-eval-source-map’, // If you have problems debugging vue-files in devtools, // set this to false - it may help // https://vue-loader.vuejs.org/en/options.html#cachebusting cacheBusting: true, cssSourceMap: true }, build: { // 生产环境的首页地址 index: path.resolve(__dirname, ‘../dist/index.html’), // 生产环境路径 assetsRoot: path.resolve(__dirname, ‘../dist’), assetsSubDirectory: ‘static’, assetsPublicPath: ‘/’, /* * Source Maps */ productionSourceMap: true, // 是否生成map文件 // https://webpack.js.org/configuration/devtool/#production devtool: ‘#source-map’, // Gzip off by default as many popular static hosts such as // Surge or Netlify already gzip all static assets for you. // Before setting to true, make sure to: // npm install –save-dev compression-webpack-plugin productionGzip: false, // 是否开启文件压缩 productionGzipExtensions: [‘js’, ‘css’], // 压缩文件过滤 // Run the build command with an extra argument to // View the bundle analyzer report after build finishes: // npm run build --report // Set to true or false to always turn it on or off bundleAnalyzerReport: process.env.npm_config_report }}⑤.项目编译打包项目安装完成,并且正常运行,接下来怎么把项目上传到服务器上去呢?能在服务器上访问我们的项目文件,难道是把我们整个项目上传上去?话说我就添加了一个文件,就把整个工程全都搞到服务器上是不是有点崩溃。如果这样的话,vue框架就没有存在的理由了。那要怎么做?接下来就要介绍另一个功能了,项目打包,这就是安装webpack的原因。运行命令:cnpm run build运行结束后会生成一个新文件夹:dist ,这里面的文件就是我们需要上传到服务上去的静态文件。打开dist目录,看里面的文件和目录结构是不是清爽多了,这里的文件就是经过webpack打包后生成的,和上面介绍的webpack是不是对应在一起了。⑥.vue-cli 使用总结下面对使用过的脚手架功能做个总结:问:在使用 vue-cli 的时候我们共使用了几个命令?答:三个。1.cnpm install -g vue-cli (vue-cli 安装)2.vue init webpack your-project (项目构建)3.cnpm run build (项目编译打包) ...

April 3, 2019 · 2 min · jiezi

两行代码让你创建vue项目

和大家分享一下自己写的cli由于用vue自己的脚手架没那么舒服,所以自己写了个cli(主要是为了新建项目的时候偷懒,不想复制粘贴了);1.vue-cli这个我是基于yeoman开发的npm install -g yonpm install generator-frame -g yo frame大家可以直接去使用,如有什么需要改动,优化的地方,大家可以提出来,共同进步,谢谢

April 2, 2019 · 1 min · jiezi

Vue-Cli 使用IcoMoon 显示乱码问题

问题描述在vue-cli项目的main.js通过require导入IcoMoon的css文件后,页面svg图标显示乱码解决措施调出控制台,发现加载了信息,但是加载的内容为空推测可能是文件加载路径问题查看IcoMoon配置文件,发现所配置文件中的url路径和真实的文件路径不相同修改所有的url结果问题解决,图标正确显示

March 29, 2019 · 1 min · jiezi

Vue技术分类

vue-cli1、vue-cli 工程常用的 npm 命令有哪些?$ npm install vue-cli //1$ vue init webpack vue-project //2$ cd vue-project //3$ npm install //4$ npm run dev 2、请说出vue-cli工程中每个文件夹和文件的用处3、config文件夹 下 index.js 的对于工程 开发环境 和 生产环境 的配置module.exports => dev => proxyTable 开发时请求代理module.exports => port 开发时使用端口module.exports => build => 规定打包后文件的结构以及名称4、详细介绍一些 package.json 里面的配置name: 项目名称,version: 版本号,description: 项目说明,author: 作者信息,dependencies: 开发环境和生产环境都需要的依赖包devDependencies: 生产环境的依赖包vue知识点1、对于Vue是一套渐进式框架的理解 Vue核心功能是一个视图模板引擎,但不是说Vue就不能成为一个框架。可以通过添加组件系统、客户端路由、大规模状态管理来构建一个完整的框架。这些功能相互独立,可以在核心功能的基础上任意选用其他的部件,不一定要全部整合在一起。这就是“渐进式”,就是Vue的使用方式。2、vue.js的两个核心是什么?数据驱动、组件系统。3、请问 v-if 和 v-show 有什么区别? v-if判断条件是否渲染,是惰性的,初始渲染时条件为假时什么也不做;v-show是 display: block/none;元素始终都会渲染;在项目中如果需要频繁的切换则使用v-show较好,运行条件很少改变,则使用v-if。4、vue常用的修饰符.prevent 提交事件不再重载页面;.stop 阻止单击事件冒泡;.self 当事件发生在该元素本身而不是子元素时触发;.capture 添加事件监听器时使用事件捕获模式;.once 只会触发一次 按键修饰符 :keyup.enter :keyup.tab5、v-on可以监听多个方法吗? 可以。6、vue中 key 值的作用v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue 将不会移动DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,主要是为了高效的更新虚拟DOM。7、vue-cli工程升级vue版本手动修改 package.json 里面vue的版本,同时修改 vue-template-compiler 为相同的版本;后者在devDependencies里面,然后npm install。8、vue事件中如何使用event对象? @click=“EventName($event)“9、$nextTick的使用在修改数据之后立即使用这个方法,获取更新后的 DOM。10、Vue 组件中 data 为什么必须是函数每用一次组件,就会有一个新实例被创建。每个实例可以维护一份被返回对象的独立的拷贝,每个对象都是独立互不影响的。11、v-for 与 v-if 的优先级v-for 具有比 v-if 更高的优先级。v-if 将分别重复运行于每个 v-for 循环中。vue风格指南提示永远不要把 v-if 和 v-for 同时用在同一个元素上。12、vue中子组件调用父组件的方法第一种:this.$parent.xxx;第二种:通过props传递父组件函数名,子组件接受,接受类型为Function;第三种:创建eventBus。13、vue中 keep-alive 组件的作用keep-alive是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。include(包含的组件缓存) 与 exclude(排除的组件不缓存,优先级大于include) 。include - 字符串或正则表达式,只有名称匹配的组件会被缓存;exclude反之亦然。 include=“a,b” :include="/a|b/” :include=”[‘a’, ‘b’]“14、vue中如何编写可复用的组件?1.规范化命名:组件的命名应该跟业务无关,而是依据组件的功能命名。2.数据扁平化:定义组件接口时,尽量不要将整个对象作为一个 prop 传进来。每个 prop 应该是一个简单类型的数据。这样做有下列几点好处: (1) 组件接口清晰。加粗文字 (2) props 校验方便。 (3) 当服务端返回的对象中的 key 名称与组件接口不一样时,不需要重新构造一个对象。 扁平化的 props 能让我们更直观地理解组件的接口。3.可复用组件只实现 UI 相关的功能,即展示、交互、动画,如何获取数据跟它无关,因此不要在组件内部去获取数据。4.可复用组件应尽量减少对外部条件的依赖。5.组件在功能独立的前提下应该尽量简单,越简单的组件可复用性越强。6.组件应具有一定的容错性。15、什么是vue生命周期和生命周期钩子函数?Vue 实例从创建到销毁的过程,就是生命周期。从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、销毁等一系列过程,称之为 Vue 的生命周期。总共分为8个阶段:创建前/后, 载入前/后,更新前/后,销毁前/销毁后。让我们在控制整个Vue实例的过程时更容易形成好的逻辑。16、vue生命周期钩子函数有哪些?beforeCreate(创建前) 在数据观测和初始化事件还未开始created(创建后) 完成数据观测,属性和方法的运算,初始化事件,$el属性还没有显示出来; beforeMount(载入前) 在挂载开始之前被调用,相关的render函数首次被调用。实例已完成以下的配置:编译模板,把data里面的数据和模板生成html。注意此时还没有挂载html到页面上;mounted(载入后) 在el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用。实例已完成以下的配置:用上面编译好的html内容替换el属性指向的DOM对象。完成模板中的html渲染到html页面中。此过程中进行ajax交互;beforeUpdate(更新前) 在数据更新之前调用,发生在虚拟DOM重新渲染和打补丁之前。可以在该钩子中进一步地更改状态,不会触发附加的重渲染过程;updated(更新后) 在由于数据更改导致的虚拟DOM重新渲染和打补丁之后调用。调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作。然而在大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。该钩子在服务器端渲染期间不被调用;beforeDestroy(销毁前) 在实例销毁之前调用。实例仍然完全可用;destroyed(销毁后) 在实例销毁之后调用。调用后,所有的事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务器端渲染期间不被调用。17、vue如何监听键盘事件中的按键?监听keyup事件并添加按键修饰符,对一些常用按键vue提供了别名,或者使用keyCode,vue也支持复合按键。18、vue更新数组时触发视图更新的方法Vue.set(arr, key, value) Vue.set(object, key, value)19、vue中对象更改检测的注意事项Vue 不能检测对象属性的添加或删除;不能动态添加根级别的响应式属性。使用 Vue.set(object, key, value) 方法向嵌套对象添加响应式属性。20、解决非工程化项目初始化页面闪动问题vue页面在加载的时候闪烁花括号{}},v-cloak指令和css规则如[v-cloak]{display:none}一起用时,这个指令可以隐藏未编译的Mustache标签直到实例准备完毕。/css样式/[v-clock] { display: none;}21、v-for产生的列表,实现active的切换<ul class=“ul” > <li v-on:click=“currentIndex = index” class=“item” v-bind:class="{clicked: index === currentIndex}” v-for="(items, index) in arr"> <a>{{items}}</a> </li></ul>data() { return{ currentIndex: 0 }}22、v-model语法糖的组件中的使用1:用于表单上数据的双向绑定;2:修饰符: .lazy- 取代input监听change事件 .number- 输入字符串转为数字 .trim- 输入首尾空格过滤 23、十个常用的自定义过滤器// 全局方法 Vue.filter() 注册一个自定义过滤器Vue.filter(“sum”, function(value) { return value + 4;});// 局部new Vue({ el: “.test”, data: { message:12 }, filters: { sum: function (value) { return value + 4; } }})24、vue等单页面应用及其优缺点优点——数据驱动、组件化、轻量简洁高效,通过尽可能简单的API实现响应的数据绑定和组合的视图组件;缺点:不支持低版本的浏览器,不利于SEO优化,可以使用服务器端渲染,首次加载耗时长。25、什么是vue的计算属性?在模板中放入太多的逻辑会让模板过重且难以维护,在需要对数据进行复杂处理,且可能多次使用的情况下,尽量采取计算属性的方式。计算属性基于它们的依赖进行缓存的;只在相关依赖发生改变时它们才会重新求值。31、计算属性的缓存和方法调用的区别两种方式的最终结果确实是完全相同的。不同的是计算属性是基于它们的依赖进行缓存的,只在相关依赖发生改变时它们才会重新求值。只要相关依赖还没有发生改变,多次访问计算属性会立即返回之前的计算结果,而不必再次执行函数如果不希望有缓存,请用方法来替代。 26、vue-cli提供的几种脚手架模板vue-cli的脚手架项目模板有webpack-simple 和 webpack;区别在于webpack-simple 没有包括Eslint 检查等功能。27、vue父组件如何向子组件中传递数据? 通过父组件v-bind传递数据子组件props接收数据28、vue-cli开发环境使用全局常量①少量Vue.prototype.baseUrl = function () { return ‘https://segmentfault.com/';};Vue.prototype.getTitle = { title:’’, isBack: true, isAdd: false,};②配置文件形式在项目的src 目录里面 新建一个 lib目录,lib目录里创建一个 config.js文件。export default { install(Vue,options) { Vue.prototype.baseUrl = function () { return ‘111’; }; Vue.prototype.getTitle = { title:’’, isBack: true, isAdd: false, }; Vue.prototype.showFootTab = { isShow:false, active:0, }}最后导入 import config from ‘./lib/config.js’; Vue.use(config);使用 <template> <div> {{getTitle.title}} </div> </template> this.getTitle29、vue-cli生产环境使用全局常量30、vue弹窗后如何禁止滚动条滚动? /滑动限制/ stop(){ var mo=function(e){e.preventDefault();}; document.body.style.overflow=‘hidden’; document.addEventListener(“touchmove”,mo,false);//禁止页面滑动 }, /取消滑动限制/ move(){ var mo=function(e){e.preventDefault();}; document.body.style.overflow=’’;//出现滚动条 document.removeEventListener(“touchmove”,mo,false); } // 如果不是Vue,可以直接给html设置overflow:hidden32、vue-cli中自定义指令的使用directives: { focus: { // 指令的定义 inserted: function (el) { el.focus() }![图片描述][1] }}Vue.directive(‘color-swatch’, function (el, binding) { el.style.backgroundColor = binding.value}) vue-router1、vue-router如何响应 路由参数 的变化?当使用路由参数时,例如从 /user/foo 导航到 /user/bar,原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。同时意味着组件的生命周期钩子不会再被调用。复用组件时,想对路由参数的变化作出响应的话,你可以简单地 watch (监测变化) $route 对象:watch: { ‘$route’ (to, from) { // 对路由变化作出响应… }}2、完整的 vue-router 导航解析流程导航被触发。在失活的组件里调用离开守卫。调用全局的 beforeEach 守卫。在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。在路由配置里调用 beforeEnter。解析异步路由组件。在被激活的组件里调用 beforeRouteEnter。调用全局的 beforeResolve 守卫 (2.5+)。导航被确认。调用全局的 afterEach 钩子。触发 DOM 更新。用创建好的实例调用 beforeRouteEnter 守卫中传给 next 的回调函数。3、vue-router有哪几种导航钩子( 导航守卫 )?全局的, 单个路由独享的, 组件级的。全局守卫:router.beforeEach router.beforeResolve(2.5+) router.afterEachconst router = new VueRouter({ … })router.beforeEach((to, from, next) => { // …})router.afterEach((to, from) => { // 这些钩子不会接受 next 函数也不会改变导航本身: …})路由独享的守卫: beforeEnter 这些守卫与全局前置守卫的方法参数是一样的。const router = new VueRouter({ routes: [ { path: ‘/foo’, component: Foo, beforeEnter: (to, from, next) => { // … } } ]})组件内的守卫beforeRouteEnterbeforeRouteUpdate (2.2 新增)beforeRouteLeaveconst Foo = { template: ..., beforeRouteEnter (to, from, next) { // 在渲染该组件的对应路由被 confirm 前调用 // 不!能!获取组件实例 this // 因为当守卫执行前,组件实例还没被创建 next(vm => { // 通过 vm 访问组件实例 }) }, beforeRouteUpdate (to, from, next) { // 在当前路由改变,但是该组件被复用时调用 // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候, // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。 // 可以访问组件实例 this }, beforeRouteLeave (to, from, next) { // 导航离开该组件的对应路由时调用 // 可以访问组件实例 this }}每个守卫方法接收三个参数:to: Route: 即将要进入的目标 路由对象from: Route: 当前导航正要离开的路由next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。4、vue-router的几种实例方法以及参数传递编程式导航 this.$router.push({ name: ’news’, params: { userId: 123 }}); // this.$route.params.userId this.$router.push({ path: ‘/news’, query: { userId: 123 }}); // this.$route.query.userId this.$router.replace();声明式导航 <router-link :to="{ name: ’news’, params: { userId: 1111}}">click to news page</router-link> <router-link :to="{ path: ‘/news’, query: { userId: 1111}}">click to news page</router-link>5、vue-router的动态路由匹配以及使用需要把某种模式匹配到的所有路由,全都映射到同个组件const User = { template: ‘<div>User{{ $route.params.id }}</div>’}const router = new VueRouter({ routes: [ // 动态路径参数 以冒号开头 { path: ‘/user/:id’, component: User } ]})复用组件时,想对路由参数的变化作出响应的话,使用watch (监测变化) $route 对象 watch: { ‘$route’ (to, from) { // 对路由变化作出响应… } }想匹配任意路径,我们可以使用通配符 (){ // 会匹配所有路径 path: ‘’}, { // 会匹配以 /user- 开头的任意路径 path: ‘/user-*’}6、vue-router如何定义嵌套路由?在router.js使用children数组来定义子路由,并在模板中使用<router-view>定义嵌套路由。如果没有匹配到合适的子路由,可以提供一个 空的 子路由 routes: [ { path: ‘/user/:id’, component: User, children: [ // 当 /user/:id 匹配成功, // UserHome 会被渲染在 User 的 <router-view> 中 { path: ‘’, component: UserHome }, // …其他子路由 ] } ]7、<router-link></router-link>组件及其属性<router-link> 组件支持用户在具有路由功能的应用中 (点击) 导航。 通过 to 属性指定目标地址,默认渲染成带有正确链接的 <a> 标签,可以通过配置 tag 属性生成别的标签。to: <!– 字符串 –> <router-link to=“home”>Home</router-link> <!– 渲染结果 –> <a href=“home”>Home</a> <!– 使用 v-bind 的 JS 表达式 –> <router-link v-bind:to="‘home’">Home</router-link> <!– 不写 v-bind 也可以,就像绑定别的属性一样 –> <router-link :to="‘home’">Home</router-link> <!– 同上 –> <router-link :to="{ path: ‘home’ }">Home</router-link> <!– 命名的路由 –> <router-link :to="{ name: ‘user’, params: { userId: 123 }}">User</router-link> <!– 带查询参数,下面的结果为 /register?plan=private –> <router-link :to="{ path: ‘register’, query: { plan: ‘private’ }}">Register</router-link>replace: 会调用 router.replace() 而不是 router.push(),于是导航后不会留下 history 记录。<router-link :to="{ path: ‘/abc’}" replace></router-link>append: 在当前 (相对) 路径前添加基路径tag: 渲染成某种标签active-class: 设置 链接激活时使用的 CSS 类名。默认值可以通过路由的构造选项 linkActiveClass 来全局配置。8、vue-router实现路由懒加载( 动态加载路由 )component: () => import(‘comp/AlbumlibMore’)9、vue-router路由的两种模式vue-router 默认 hash 模式 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。HTML5 History 模式 充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面。 要玩好,还需要后台配置支持; 因为我们的应用是个单页客户端应用,如果后台没有正确的配置,当用户在浏览器直接访问 http://oursite.com/user/id 就会返回 40410、history路由模式与后台的配合在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面;然后在给出一个 404 页面。vuex1、什么是vuex?专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。读取的状态集中放在store中; 改变状态的方式是提交mutations,这是个同步的事物; 异步逻辑应该封装在action中。在main.js引入store,注入。新建了一个目录store,export 。场景有:单页应用中,组件之间的状态、音乐播放、登录状态、加入购物车2、使用vuex的核心概念state => 基本数据 getters => 从基本数据派生的数据 mutations => 提交更改数据的方法,同步! actions => 像一个装饰器,包裹mutations,使之可以异步。 modules => 模块化Vuex(2019.03.26)3、vuex在vue-cli中的应用4、组件中使用 vuex 的值和修改值的地方?5、在vuex中使用异步修改6、pc端页面刷新时实现vuex缓存http请求1、Promise对象是什么?2、axios、fetch与ajax有什么区别?3、什么是JS的同源策略和跨域问题?4、如何解决跨域问题?5、vue-cli中如何使用JSON数据模拟?6、vue-cli中http请求的统一管理。7、axios有什么特点?UI样式1、.vue组件的scoped属性的作用2、如何让CSS只在当前组件中起作用?3、vue-cli中常用的UI组件库4、如何适配移动端?【 经典 】5、移动端常用媒体查询的使用6、垂直居中对齐7、vue-cli中如何使用背景图片?8、使用表单禁用时移动端样式问题9、多种类型文本超出隐藏问题常用功能1、vue中如何实现tab切换功能?2、vue中如何利用 keep-alive 标签实现某个组件缓存功能?3、vue中实现切换页面时为左滑出效果4、vue中父子组件如何相互调用方法?5、vue中央事件总线的使用混合开发1、vue如何调用 原生app 提供的方法?2、原生app 调用 vue 提供的方法,并将值传递到 .vue 组件中生产环境1、vue打包命令是什么?2、vue打包后会生成哪些文件?3、如何配置 vue 打包生成文件的路径?4、vue如何优化首屏加载速度?MVVM设计模式1、MVC、MVP与MVVM模式2、MVC、MVP与MVVM的区别3、常见的实现MVVM几种方式4、Object.defineProperty()方法5、实现一个自己的MVVM(原理剖析)6、 ES6中类和定义7、JS中的文档碎片8、解构赋值9、Array.from与Array.reduce10、递归的使用11、Obj.keys()与Obj.defineProperty12、发布-订阅模式13、实现MVVM的思路分析源码剖析1、vue内部与运行机制:Vue.js 全局运行机制响应式系统的基本原理什么是 Virtual DOM?如何编译template 模板?diff算法批量异步更新策略及 nextTick 原理?proxy代理?2、vuex工作原理详解Vue.mixinVue.use深入拓展1、vue开发命令 npm run dev 输入后的执行过程2、vue的服务器端渲染3、从零写一个npm安装包4、vue-cli中常用到的加载器5、webpack的特点 ...

March 26, 2019 · 4 min · jiezi

Vue技术点②

1:Vue实现数据双向绑定的原理?答:Object.defineProperty(),采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应监听回调。当把一个普通 Javascript 对象传给 Vue 实例来作为它的 data 选项时,Vue 将遍历它的属性,用 Object.defineProperty 将它们转为 getter/setter。用户看不到 getter/setter,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。<body> <div id=“app”> <input type=“text” id=“txt”> <p id=“show”></p></div></body><script type=“text/javascript”> var obj = {} Object.defineProperty(obj, ’txt’, { get: function () { return obj }, set: function (newValue) { document.getElementById(’txt’).value = newValue document.getElementById(‘show’).innerHTML = newValue } }) document.addEventListener(‘keyup’, function (e) { obj.txt = e.target.value })</script>2:Vue的路由实现:hash模式 和 history模式答:hash模式:在浏览器中符号“#”,#以及#后面的字符称之为hash,用window.location.hash读取;特点:hash虽然在URL中,但不被包括在HTTP请求中;用来指导浏览器动作,对服务端安全无用,hash不会重加载页面。hash 模式下,仅 hash 符号之前的内容会被包含在请求中,如 http://www.xxx.com,因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回 404 错误。history模式:history采用HTML5的新特性;且提供了两个新方法:pushState(),replaceState()可以对浏览器历史记录栈进行修改,以及popState事件的监听到状态变更。history 模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致,如 http://www.xxx.com/items/id。后端如果缺少对 /items/id 的路由处理,将返回 404 错误。Vue-Router 官网里如此描述:“不过这种模式要玩好,还需要后台配置支持……所以呢,你要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。”3:vuex是什么?怎么使用?哪种功能场景使用它?答:专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。读取的状态集中放在store中; 改变状态的方式是提交mutations,这是个同步的事物; 异步逻辑应该封装在action中。在main.js引入store,注入。新建了一个目录store,….. export 。场景有:单页应用中,组件之间的状态、音乐播放、登录状态、加入购物车4:vue-router如何响应 路由参数 的变化?答:当使用路由参数时,例如从 /user/foo 导航到 /user/bar,原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。同时意味着组件的生命周期钩子不会再被调用。复用组件时,想对路由参数的变化作出响应的话,你可以简单地 watch (监测变化) $route 对象: watch: { ‘$route’ (to, from) { // 对路由变化作出响应… } }5:vue-router有哪几种导航钩子答:全局的, 单个路由独享的, 或者组件级的。全局守卫:router.beforeEach router.beforeResolve(2.5+) router.afterEachconst router = new VueRouter({ … })router.beforeEach((to, from, next) => { // …})router.afterEach((to, from) => { // 这些钩子不会接受 next 函数也不会改变导航本身: …})路由独享的守卫: beforeEnter 这些守卫与全局前置守卫的方法参数是一样的。const router = new VueRouter({ routes: [ { path: ‘/foo’, component: Foo, beforeEnter: (to, from, next) => { // … } } ]})组件内的守卫beforeRouteEnterbeforeRouteUpdate (2.2 新增)beforeRouteLeaveconst Foo = { template: ..., beforeRouteEnter (to, from, next) { // 在渲染该组件的对应路由被 confirm 前调用 // 不!能!获取组件实例 this // 因为当守卫执行前,组件实例还没被创建 next(vm => { // 通过 vm 访问组件实例 }) }, beforeRouteUpdate (to, from, next) { // 在当前路由改变,但是该组件被复用时调用 // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候, // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。 // 可以访问组件实例 this }, beforeRouteLeave (to, from, next) { // 导航离开该组件的对应路由时调用 // 可以访问组件实例 this }}每个守卫方法接收三个参数:to: Route: 即将要进入的目标 路由对象from: Route: 当前导航正要离开的路由next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。6:完整的 vue-router 导航解析流程答:导航被触发。在失活的组件里调用离开守卫。调用全局的 beforeEach 守卫。在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。在路由配置里调用 beforeEnter。解析异步路由组件。在被激活的组件里调用 beforeRouteEnter。调用全局的 beforeResolve 守卫 (2.5+)。导航被确认。调用全局的 afterEach 钩子。触发 DOM 更新。用创建好的实例调用 beforeRouteEnter 守卫中传给 next 的回调函数。 ...

March 25, 2019 · 2 min · jiezi

Vue-cli 3.5.1 + Webstorm 使用手机访问演示页面

Vue-cli 3.5.1 + Webstorm 使用手机访问演示页面如果使用Webstorm和Vue-cli 3.5.1创建项目。npm run server 后手机不能通过网络访问演示页面,原因是webstorm默认使用计算机本地连接的IP地址作为网络访问地址,修改IP地址为要使用的无线网络地址就可以解决问题.在之前的版本中可以修改config目录内index.js文件解决.cli3移除了config文件后:可尝试如下解决办法。根目录下创建vue.config.jsvue.config.js是vue cli 3移除config目录后可选的配置文件,如果创建在根目录下会自动加载.vue.config.js 参考文档 : https://cli.vuejs.org/zh/conf…模板设置// vue.config.js 配置说明// 这里只列一部分,具体配置参考文档module.exports = { //publicPath:用于替代原先baseUrl; publicPath: process.env.NODE_ENV === ‘production’ ? ‘/production-sub-path/’ : ‘/’, // outputDir: 在npm run build 或 yarn build 时 ,生成文件的目录名称(要和baseUrl的生产环境路径一致) outputDir: “mycli3”, //用于放置生成的静态资源 (js、css、img、fonts) 的;(项目打包之后,静态资源会放在这个文件夹下) assetsDir: “assets”, //指定生成的 index.html 的输出路径 (打包之后,改变系统默认的index.html的文件名) // indexPath: “myIndex.html”, //默认情况下,生成的静态资源在它们的文件名中包含了 hash 以便更好的控制缓存。你可以通过将这个选项设为 false 来关闭文件名哈希。(false的时候就是让原来的文件名不改变) filenameHashing: false, // lintOnSave:{ type:Boolean default:true } 问你是否使用eslint lintOnSave: true, //如果你想要在生产构建时禁用 eslint-loader,你可以用如下配置 // lintOnSave: process.env.NODE_ENV !== ‘production’, //是否使用包含运行时编译器的 Vue 构建版本。设置为 true 后你就可以在 Vue 组件中使用 template 选项了,但是这会让你的应用额外增加 10kb 左右。(默认false) // runtimeCompiler: false, /** * 如果你不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建。 * 打包之后发现map文件过大,项目文件体积很大,设置为false就可以不输出map文件 * map文件的作用在于:项目打包后,代码都是经过压缩加密的,如果运行时报错,输出的错误信息无法准确得知是哪里的代码报错。 * 有了map就可以像未加密的代码一样,准确的输出是哪一行哪一列有错。 * */ productionSourceMap: false, // 它支持webPack-dev-server的所有选项 devServer: { host: “192.168.31.23”, port: 8080, // 端口号 https: false, // https:{type:Boolean} open: false, //配置自动启动浏览器 // proxy: ‘http://localhost:4000’ // 配置跨域处理,只有一个代理 // 配置多个代理 proxy: { “/api”: { target: “<url>”, ws: true, changeOrigin: true }, “/foo”: { target: “<other_url>” } } }};修改设置将模板设置内的devserver部分内的host修改为你要使用的网络IP地址.将port修改为要使用的端口号,重新npm run server即可.获取IP地址不建议使用ipconfig命令获取,建议直接点击网络图标查看属性内的IP地址. ...

March 16, 2019 · 1 min · jiezi

iview-admin多环境配置打包

前言由于目前我在公司已经搭建了Jenkins来进行一键系统发布,同时存在测试和生产两套环境。但是目前iview-admin是不支持的,只好自己进行改造了。PS:iview-admin版本为2.1.0改造方案iview-admin 2.1.0比起iview-admin 2.0.0,移除了config目录且将vue-cli升级到3.0。所以可以使用vue-cli 3.0的环境变量和模式特性来支持多环境配置打包。在项目根目录添加环境变量文件新增开发环境文件.env.dev,内容如下:NODE_ENV = ‘dev’MOCK = trueBASE_URL= ‘/‘新增测试环境文件.env.test,内容如下:NODE_ENV = ’test’MOCK = falseBASE_URL= ‘/test’新增生产环境文件.env.prod,内容如下:NODE_ENV = ‘prod’MOCK = falseBASE_URL= ‘/prod’环境变量文件中各个属性的用途如下:NODE_ENV为对应的环境MOCK为是否引入mock.js文件的标识BASE_URL为前端项目访问时的相对地址修改package.json修改scripts的dev和build,修改后内容如下: “scripts”: { “dev”: “vue-cli-service serve –open –mode dev”, “build:test”: “vue-cli-service build –mode test”, “build:prod”: “vue-cli-service build –mode prod”, “lint”: “vue-cli-service lint”, “test:unit”: “vue-cli-service test:unit”, “test:e2e”: “vue-cli-service test:e2e” },修改后的指令npm run dev为开发调试npm run build:test为测试环境打包npm run build:prod为开发环境打包修改vue.config.js文件修改BASE_URL(此参数控制的是前端项目访问时的相对地址),改为从环境变量中获取,内容如下: const BASE_URL = process.env.BASE_URL修改src/config/index.js文件修改baseUrl,改为多个后端API接口的配置,内容如下: baseUrl: { dev: ‘http://localhost:8081’, test: ‘http://www.test.com’, prod: ‘http://www.prod.com’ },修改src/libs/api.request.js文件修改baseUrl(对应后端API接口的地址),改为根据环境变量获取对应的URL,内容如下: const baseUrl = config.baseUrl[process.env.NODE_ENV]修改src/main.js文件修改mock包引入判断,改为从环境变量中获取,内容如下: if (process.env.MOCK) require(’@/mock’)参考资料https://cli.vuejs.org/zh/guid…https://github.com/vuejs/vue-… ...

March 6, 2019 · 1 min · jiezi

vue-cli3+typescript初体验——router篇

前言vue基于类的写法,和基于对象的写法并不一致。使用vue-cli3创建的项目,src目录下的文件结构并没有多大区别,store、router、app、view、components、aeests该有的还是有的。但是,多了一个东西:vue-property-decorator,vue-property-decorator是vue-class-component的超集。import { Component, Prop, Vue, Watch, Emit } from ‘vue-property-decorator’;最主要的区别就是这里,组件的定义,参数的接受,方法的定义,等等。但是本文主要讲的是router的监听。路由监听用vue2的vue-cli创建项目,在src下有App.vue,main.js,其中如果要做路由权限控制,可以通过在mian.js添加以下代码来控制:import router from ‘./router’router.beforeEach((to, from, next) => { /如果需要登录,当前没有登录,直接跳转到登录页/ if (to.meta.Auth && !store.state.loginStatus) { return next({ name: ‘Login’, query: {path: to.name}}) } next() })这个功能,在新版本的vue3中依然可以使用,因为使用了typescript,所以应该是main.ts文件。但是如果要在组件内部使用路由监听,就遇到问题了,路由钩子beforeRouteEnter,beforeRouteLeave,beforeRouteUpdate不生效。官网推荐在mian.ts中注册解决:import Component from ‘vue-class-component’Component.registerHooks([ ‘beforeRouteEnter’,//进入路由之前 ‘beforeRouteLeave’,//离开路由之前 ‘beforeRouteUpdate’])但是在vue-cli3中试过,不生效。可能是vue-property-decorator和vue-class-component有区别的原因,或者项目配置问题。组件中实现路由监听,只能通过@Watch(’$route’)来实现。但是@Watch不是路由守卫,如果离开当前组件,就不能继续监听路由变化,所以需要在当前的router-virew容器组件中监听。<template> <div id=“app”> <div id=“nav”> <router-link to="/">Home</router-link> | <router-link to="/about">About</router-link> </div> <router-view/> </div></template><script lang=“ts”>import { Component, Vue, Watch } from ‘vue-property-decorator’;@Componentexport default class App extends Vue { @Watch(’$route’,{ immediate: true }) private changeRouter(route: Route){ console.log(route) }}</script>其中{ immediate: true }是关键,必须加这个参数才嫩实现对$route的监听。结语vue-cli3+typescript的规范还不成熟,各种文档还不够齐全,尤其是中文文档。很多demo都是基于vue2改造的,导致使用vue-cli3的时候出bug。尤其是vue-router和vuex的使用。但也正是这些问题,让我们有更大的兴趣学习使用这个新的技术规范。 ...

March 1, 2019 · 1 min · jiezi

vue-cli3+typescript初体验

前言气势汹涌,ts似乎已经在来的路上,随时可能敲门。2015年,三大前端框架开始火爆的时候,我还在抱着Backbone不放,一直觉得可以轻易转到其他框架去。后来换工作,现实把脸都打肿了,没做过vue、react、angular?不要!今天,不能犯这个错了,毕竟时不我与,都快奔三了。vue-cli3vue-cli3的详细功能推荐官方文档,不在本文介绍范围内。安装:npm install -g @vue/cli检查安装成功与否:vue –version创建项目:vue create myapp可以选择Manually select feature来自由选择功能,常用的有vuex、vue-router、CSS Pre-processors等,我们再把typescript勾上,就可以回车进入下一步了。PS:勾选的操作是按空格键。创建成功之后,执行启动命令:npm run serve就可以通过http://localhost:8080/访问本地项目啦。typescript如果没有typescript基础,可以先补补课,大概花三十分钟就可以了解typescript的一些特性,比如:TypeScript 入门教程。ts最主要的一点就是类型定义,有个概念才好看得懂demo。vue-property-decorator这是一个涵盖了vue的一些对象的集合,我们可以从这里取一些东西出来:import { Component, Prop, Vue, Watch } from ‘vue-property-decorator’;取出来的这几个属性,分别是 组件定义Component,父组件传递过来的参数Prop,原始vue对象Vue,数据监听对象Watch。还包括这里没有列举出来的Model,Emit,Inject,Provide,可以自己尝试下。demo<template> <div class=“hello”> <h1>{{ msg }}–{{ names }}</h1> <input type=“text” v-model=“txt”> <p>{{ getTxt }}</p> <button @click=“add”>add</button> <p>{{ sum }}</p> </div></template><script lang=“ts”>import { Component, Prop, Vue, Watch } from ‘vue-property-decorator’;@Componentexport default class HelloWorld extends Vue { //props @Prop() private msg!: string @Prop() private names!: string //data private txt: string = ‘1’ private sum: number = 0 //computed get getTxt(){ return this.txt } //methods private add(){ this.sum++ console.log(sum : ${this.sum}) } //生命周期 created(){ console.log(‘created’) } //watch @Watch(’txt’) changeTxt(newTxt: string, oldTxt: string){ console.log(change txt: ${oldTxt} to ${newTxt}) } }</script><!– Add “scoped” attribute to limit CSS to this component only –><style scoped lang=“less”>h3 { margin: 40px 0 0;}input { width: 240px; height: 32px; line-height: 32px;}</style>以上就是demo,代码组织有点散,没有原来js书写的整齐。这个demo没有引入组件,如果需要引入组件,应该这样书写:<template> <div class=“home”> <img alt=“Vue logo” src="../assets/logo.png"> <HelloWorld msg=“Welcome to Your Vue.js + TypeScript App” names=“aaa” /> <HelloWorld2 msg=“Welcome to Your Vue.js + TypeScript App” names=“bbb” /> </div></template><script lang=“ts”>import { Component, Vue } from ‘vue-property-decorator’;import HelloWorld from ‘@/components/HelloWorld.vue’; // @ is an alias to /srcimport HelloWorld2 from ‘@/components/HelloWorld2.vue’; // @ is an alias to /src@Component({ components: { HelloWorld, HelloWorld2, },})export default class Home extends Vue {}</script>结语如果VSCode编辑器有警告提示,比如:Experimental support for decorators is a feature that is subject to change in a future release. Set the ’experimentalDecorators’ option to remove this warning.可以把工作区其他的项目移除,或者把本项目拖动到工作区的首位,或者在把本项目的tsconfig.json复制到工作区首位的项目的根目录下,重启编辑器,有比较大的概率可以解决警告提示。 ...

February 27, 2019 · 2 min · jiezi

Vue CLI3.0 中使用jQuery 和 Bootstrap

Vue 中使用 jQuery 和 Bootstrap 不是特别符合 Vue 原生的写法,但是有时候又要用,所以放上我的引入设置,供大家参考。在 Vue CLI2.0 中引入 jQuery 和 Bootstrap 需要设置很多配置项,网上有很多方法法,这里不重复写了。直接上 Vue CLI3.0 配置步骤。第一步:安装 jQuery、 Bootstrap、popper.js依赖。其中popper.js 用于在 Bootstrap 中显示弹窗、提示、下拉菜单,所以需要引入。npm install jquery bootstrap@3 popper.js –save注意:上面的 bootstrap@3 指的是安装 Bootstrap 第三版,如果不加 @3 符号,默认安装第四版。第二步:配置 main.js引入 Boostrap 请看配置文件。//main.jsimport Vue from “vue”;import App from “./App.vue”;import router from “./router”;import store from “./store”;//在这里引入 bootstrap。默认只引入 bootstrap 中的 js,css 需要另外引入,我的 bootstrap.ss 在APP.vue中引入的import “bootstrap”;//也可以在这里引入 bootstrap.css ;//import “bootstrap/dist/css/bootstrap.css”;Vue.config.productionTip = false;new Vue({ router: router, store: store, render: h => h(App)}).$mount("#app");我的 APP.vue 的配置,只是引入 bootstrap.css,代码仅供参考。<style>// 因为我的 bootstrap 文件经过了我自己的调整,所以单独放在 assets 文件夹中做单独引入。//如果你只是想使用原生的 bootstrap,直接在 main.js 中引入 css 文件即可。@import “./assets/css/bootstrap.css”;</style>第三步:配置 vue.config.js 文件Vue CLI3.0 中的所有配置都在 vue.config.js 文件,你在这里配置好,脚手架自动使用你的配置覆盖掉默认的配置。如果你的项目中没有 vue.config.js 文件,请你在 package.json 文件的同级目录新建一个 vue.config.js 文件。文件内具体的配置如下:const webpack = require(“webpack”);module.exports = {//configureWebpack 是Vue CLI3.0 中用于配置 webpack 插件参数的地方,你在这里设置,会新建或者覆盖 webpack 默认配置。//webpack ProvidePlugin 的含义是创建一个全局的变量,使这个变量在 webpack 各个模块内都可以使用。这里的配置含义是创建 ‘$’、‘jQuery’、‘window.jQuery’ 三个变量指向 jquery 依赖,创建 ‘Popper’ 变量指向 popper.js 依赖。 configureWebpack: { plugins: [ new webpack.ProvidePlugin({ $: ‘jquery’, jQuery: ‘jquery’, ‘window.jQuery’: ‘jquery’, Popper: [‘popper.js’, ‘default’] }) ] }}第四步:具体使用范例我做了一个 tooltip 的示例,鼠标放上去会出现 tooltip 提示//template<template> <div class=“content-wrap”> <button type=“button” class=“btn btn-default” data-toggle=“tooltip” data-placement=“left” title=“Tooltip on left”>Tooltip on left</button> <button type=“button” class=“btn btn-primary” data-toggle=“tooltip” data-placement=“top” title=“Tooltip on top”>Tooltip on top</button> <button type=“button” class=“btn btn-warning” data-toggle=“tooltip” data-placement=“bottom” title=“Tooltip on bottom”>Tooltip on bottom</button> <button type=“button” class=“btn btn-danger” data-toggle=“tooltip” data-placement=“right” title=“Tooltip on right”>Tooltip on right</button> </div></template><script>export default { name: “componentsTooltips”, mounted: function() { //在页面加载完毕后初始化 tooltip, 相当于$(function(){ $(’[data-toggle=“tooltip”]’).tooltip(); } $(’[data-toggle=“tooltip”]’).tooltip(); }};</script>如果 eslint 报误,请设置 .eslintrc.js 文件。module.exports = { env: { node: true, jquery: true }};本人测试结果如下:欢迎大家批评指正。参考文档:Vue CLI3.0: https://cli.vuejs.org/zh/guid...Bootstrap tooltip :https://v3.bootcss.com/javasc…Stackoverflow: https://stackoverflow.com/que… ...

February 27, 2019 · 2 min · jiezi

Vue-cli 搭建移动端项目

1、注意点:babel-polyfill的引用和使用:https://www.cnblogs.com/princ…

February 27, 2019 · 1 min · jiezi

说说vue-cli中使用flexible和px2rem-loader

1.下载lib-flexiblenpm i lib-flexible –save或yarn add lib-flexible2.在项目中引入lib-flexible 一般情况在(main.js中引入lib-flexible)import ’lib-flexible/flexible'3.设置meta标签(视情况而定)<meta name=“viewport” content=“width=device-width, initial-scale=1.0”>4.安装px2rem-loadernpm install px2rem-loader –save或yarn add px2rem-loader5.在webpack中配置px2rem-loader1,在项目build文件中找到util.js,将px2rem-loader添加到cssLoaders中,2,px2rem-loader 下的 remUnit 根据设计稿而定具体如下:exports.cssLoaders = function (options) { options = options || {} const cssLoader = { loader: ‘css-loader’, options: { minimize: process.env.NODE_ENV === ‘production’, sourceMap: options.sourceMap } } //rem编译(新加px2) const px2remLoader = { loader: ‘px2rem-loader’, options: { remUnit: 75 // 由于设计稿是750 } } function generateLoaders (loader, loaderOptions) { var loaders = [cssLoader,px2remLoader]//添加到loader里面 省略….. }}6.项目中使用假设设计稿width和font-size分别是200px,50px 具体代码:(按照设计稿写即可).demo{ width: 200px; font-size: 50px;}7.单独使用flexible可直接添加一个rem.js文件,具体如下:1,配合less,sass和stylus来做px转换rem2,具体可参看css编译/*** 移动端自适应方案 FROM 手淘*/export const setViewport = (()=>{//此处是单独使用 const win = window const lib = window.lib || (window.lib = {})//;(function(win, lib) {//此处是直接使用 let doc = win.document; let docEl = doc.documentElement; let metaEl = doc.querySelector(‘meta[name=“viewport”]’); let flexibleEl = doc.querySelector(‘meta[name=“flexible”]’); let dpr = 0; let scale = 0; let tid; let flexible = lib.flexible || (lib.flexible = {}); if (metaEl) { //console.warn(‘将根据已有的meta标签来设置缩放比例’); let match = metaEl.getAttribute(‘content’).match(/initial-scale=([\d.]+)/); if (match) { scale = parseFloat(match[1]); dpr = parseInt(1 / scale); } } else if (flexibleEl) { let content = flexibleEl.getAttribute(‘content’); if (content) { let initialDpr = content.match(/initial-dpr=([\d.]+)/); let maximumDpr = content.match(/maximum-dpr=([\d.]+)/); if (initialDpr) { dpr = parseFloat(initialDpr[1]); scale = parseFloat((1 / dpr).toFixed(2)); } if (maximumDpr) { dpr = parseFloat(maximumDpr[1]); scale = parseFloat((1 / dpr).toFixed(2)); } } } if (!dpr && !scale) { //let isAndroid = win.navigator.appVersion.match(/android/gi); let isIPhone = win.navigator.appVersion.match(/iphone/gi); let devicePixelRatio = win.devicePixelRatio; if (isIPhone) { // iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案 if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) { dpr = 3; } else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){ dpr = 2; } else { dpr = 1; } } else { // 其他设备下,仍旧使用1倍的方案 dpr = 1; } scale = 1 / dpr; } docEl.setAttribute(‘data-dpr’, dpr); if (!metaEl) { metaEl = doc.createElement(‘meta’); metaEl.setAttribute(’name’, ‘viewport’); metaEl.setAttribute(‘content’, ‘initial-scale=’ + scale + ‘, maximum-scale=’ + scale + ‘, minimum-scale=’ + scale + ‘, user-scalable=no’); if (docEl.firstElementChild) { docEl.firstElementChild.appendChild(metaEl); } else { let wrap = doc.createElement(‘div’); wrap.appendChild(metaEl); doc.write(wrap.innerHTML); } } function refreshRem(){ let width = docEl.getBoundingClientRect().width; if (width / dpr > 540) { width = 540 * dpr; } let rem = width / 10; docEl.style.fontSize = rem + ‘px’; flexible.rem = win.rem = rem; } win.addEventListener(‘resize’, function() { clearTimeout(tid); tid = setTimeout(refreshRem, 300); }, false); win.addEventListener(‘pageshow’, function(e) { if (e.persisted) { clearTimeout(tid); tid = setTimeout(refreshRem, 300); } }, false); if (doc.readyState === ‘complete’) { doc.body.style.fontSize = 12 * dpr + ‘px’; } else { doc.addEventListener(‘DOMContentLoaded’, function() { doc.body.style.fontSize = 12 * dpr + ‘px’; }, false); } refreshRem(); flexible.dpr = win.dpr = dpr; flexible.refreshRem = refreshRem; flexible.rem2px = function(d) { let val = parseFloat(d) * this.rem; if (typeof d === ‘string’ && d.match(/rem$/)) { val += ‘px’; } return val; }; flexible.px2rem = function(d) { let val = parseFloat(d) / this.rem; if (typeof d === ‘string’ && d.match(/px$/)) { val += ‘rem’; } return val; };});//})(window, window.lib || (window.lib = {})); ...

February 27, 2019 · 3 min · jiezi

VSCode中experimentalDecorators设置问题

前言最近用vue+typescript做项目,脚手架构建好项目后,发现vsCode一直发出警告提示,百度之后,解决了。但是又不仅仅是百度就解决了。问题的出现工作区有几个项目,新开的项目添加进来的位置在最后。警告提示:Experimental support for decorators is a feature that is subject to change in a future release. Set the ‘experimentalDecorators’ option to remove this warning.解决方法很多方法都是修改experimentalDecorators参数,但是vue-cli3构建项目的时候已经在tsconfig.json中配置了这个参数,然而并没有什么卵用。有的说新建一个jsconfig.json,配置experimentalDecorators参数,这一步在vue-cli3中已经预设了。有的说修改vsCode的配置,文件->首选项->设置 中搜索experimentalDecorators,设置为true,这个也不生效。解决最终在简书看到了一篇文章,博主通过新开窗口的方式,解决了这个问题。思考再三,我决定试试。直接把新项目移动到工作区项目的首位。然后,果然不报错了。问题似乎已经得到了完美的解决,但是我还有一个疑问。难道真的是必须要放在首位才能解决么?验证再次移动项目的顺序,又报错了。在排序第一的项目中加入含有experimentalDecorators配置的tsconfig.json,重启编辑器,不报错了。也就是说,vsCode编辑器在查找experimentalDecorators配置的时候,只会查找第一个工作区的项目,如果该项目有experimentalDecorators配置,则整个工作区使用该配置,如果没有,整个工作区都不会使用。结语运行环境ubuntu18.04+vsCode1.31.1+vue-cli3+typescript

February 26, 2019 · 1 min · jiezi

前端性能优化之gzip

gzip是GNUzip的缩写,它是一个GNU自由软件的文件压缩程序。它最早由Jean-loup Gailly和Mark Adler创建,用于UNⅨ系统的文件压缩。我们在Linux中经常会用到后缀为.gz的文件,它们就是GZIP格式的。现今已经成为Internet 上使用非常普遍的一种数据压缩格式,或者说一种文件格式。HTTP协议上的GZIP编码是一种用来改进WEB应用程序性能的技术。大流量的WEB站点常常使用GZIP压缩技术来让用户感受更快的速度。减少文件大小有两个明显的好处,一是可以减少存储空间,二是通过网络传输文件时,可以减少传输的时间。当然WEB服务器和客户端(浏览器)必须共同支持gzip。目前主流的浏览器Chrome,firefox,IE等都支持该协议。常见的服务器如Apache,Nginx,IIS同样支持gzip。下面就以Vue项目为例,介绍一下gzip的使用(vue-cli 2.*)1、在/config/index.js中,修改配置开启gzip// Gzip off by default as many popular static hosts such as// Surge or Netlify already gzip all static assets for you.// Before setting to true, make sure to:// npm install –save-dev compression-webpack-pluginproductionGzip: true,productionGzipExtensions: [‘js’, ‘css’],在修改productionGzip的默认值(false)为true之前,先安装所需的依赖npm install –save-dev compression-webpack-plugin。2、在nginx中开启gzip,/nginx/conf/nginx.conf中添加gzip配置http:{ #启用或禁用gzipping响应。# gzip on; #设置用于压缩响应的缓冲区number和size。默认情况下,缓冲区大小等于一个内存页面。这是4K或8K,具体取决于平台。# gzip_static on; #启用或禁用gzipping响应。# gzip_buffers 4 16k; #设置level响应的gzip压缩。可接受的值范围为1到9。# gzip_comp_level 5; #设置将被gzip压缩的响应的最小长度。长度仅由“Content-Length”响应头字段确定。# gzip_min_length 100; #匹配MIME类型进行压缩,text/html默认被压缩。# gzip_types text/plain application/javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;}修改完nginx配置,重启服务。关于gzip详细的配置和描述,请查阅 Module ngx_http_gzip_module至此,gzip已开启。你可以运行你的项目去检测一下。打开Chrome控制台,可以看到Network下的Response Headers中返回了Content-Encoding: gzip,表明gzip开启成功。而Request Headers里面的Accept-Encoding: gzip只是表示前端(用户浏览器)支持gzip的压缩方式。服务器支持gzip的方式可以有两种: 1、打包的时候生成对应的.gz文件,浏览器请求xx.js时,服务器返回对应的xxx.js.gz文件 2、浏览器请求xx.js时,服务器对xx.js进行gzip压缩后传输给浏览器 ...

February 13, 2019 · 1 min · jiezi

vue-cli3 项目优化之自动生成组件

介绍做前端的大家都知道通过 vue 开发的项目每次创建新组建的时候,都要新建一个目录,然后新增 .vue 文件,在这个文件中再写入 template 、 script 、 style 这些内容,虽然在写入的时候大家都有自己的自动补全共计,不过这些都是模板性的,每次都要这样重复操作,很麻烦有没有。本文就是通过node来帮助我们,自动去执行这些重复操作,而我们只需要告诉控制台我们需要创建的组件名字就可以了。本文自动创建的组件包含两个文件:入口文件 index.js 、vue文件 main.vue 1.1 chalk工具为了方便我们能看清控制台输出的各种语句,我们先安装一下 chalknpm install chalk –save-dev1.2 创建views在根目录中创建一个 scripts 文件夹在 scripts 中创建 generateView 文件夹在 generateView 中新建 index.js ,放置生成组件的代码在 generateView 中新建 template.js ,放置组件模板的代码,模板内容可根据项目需求自行修改index.js// index.jsconst chalk = require(‘chalk’)const path = require(‘path’)const fs = require(‘fs’)const resolve = (…file) => path.resolve(__dirname, …file)const log = message => console.log(chalk.green(${message}))const successLog = message => console.log(chalk.blue(${message}))const errorLog = error => console.log(chalk.red(${error}))// 导入模板const { vueTemplate, entryTemplate} = require(’./template’)// 生成文件const generateFile = (path, data) => { if (fs.existsSync(path)) { errorLog(${path}文件已存在) return } return new Promise((resolve, reject) => { fs.writeFile(path, data, ‘utf8’, err => { if (err) { errorLog(err.message) reject(err) } else { resolve(true) } }) })}log(‘请输入要生成的页面组件名称、会生成在 views/目录下’)let componentName = ‘‘process.stdin.on(‘data’, async chunk => { // 组件名称 const inputName = String(chunk).trim().toString() // Vue页面组件路径 const componentPath = resolve(’../../src/views’, inputName) // vue文件 const vueFile = resolve(componentPath, ‘main.vue’) // 入口文件 const entryFile = resolve(componentPath, ’entry.js’) // 判断组件文件夹是否存在 const hasComponentExists = fs.existsSync(componentPath) if (hasComponentExists) { errorLog(${inputName}页面组件已存在,请重新输入) return } else { log(正在生成 component 目录 ${componentPath}) await dotExistDirectoryCreate(componentPath) } try { // 获取组件名 if (inputName.includes(’/’)) { const inputArr = inputName.split(’/’) componentName = inputArr[inputArr.length - 1] } else { componentName = inputName } log(正在生成 vue 文件 ${vueFile}) await generateFile(vueFile, vueTemplate(componentName)) log(正在生成 entry 文件 ${entryFile}) await generateFile(entryFile, entryTemplate(componentName)) successLog(‘生成成功’) } catch (e) { errorLog(e.message) } process.stdin.emit(’end’)})process.stdin.on(’end’, () => { log(’exit’) process.exit()})function dotExistDirectoryCreate(directory) { return new Promise((resolve) => { mkdirs(directory, function() { resolve(true) }) })}// 递归创建目录function mkdirs(directory, callback) { var exists = fs.existsSync(directory) if (exists) { callback() } else { mkdirs(path.dirname(directory), function() { fs.mkdirSync(directory) callback() }) }}template.js// template.jsmodule.exports = { vueTemplate: compoenntName => { return &lt;template&gt; &lt;div class="${compoenntName}"&gt; ${compoenntName}组件 &lt;/div&gt;&lt;/template&gt;&lt;script&gt;export default { name: '${compoenntName}'};&lt;/script&gt;&lt;style lang="stylus" scoped&gt;.${compoenntName} {};&lt;/style&gt; }, entryTemplate: compoenntName => { return import ${compoenntName} from './main.vue'export default [{ path: "/${compoenntName}", name: "${compoenntName}", component: ${compoenntName}}] }}1.3 配置package.json"new:view": “node ./scripts/generateView/index"如果使用 npm 的话 就是 npm run new:view如果是 yarn 自行修改命令1.4 结果稍后再补上生成公用component的代码,基本差不多,改吧改吧就行了 ...

January 29, 2019 · 2 min · jiezi

Vue-router基本学习(1)

多页面应用:网页HTML文件是请求后台发过来的。每次切换页面都会从后台把页面文件传输回来。单页面应用:网页只有在第一次进入页面的、的时候请求服务器的HTML文件,接下来的页面跳转是基于内部的router。两种应用的优缺点:多页面应用只需要加载当前页面所需要的资源,所以首屏时间快。但是每切换一次页面都要去请求一次服务器资源。单页面应用第一次要将所有的资源全部加载,所以首屏时间慢,但是后续的跳转不需要再次向服务器发请求。多页面应用可以直接实现SEO搜索,但是单页面得有一套单独的SEO方案。单页面可以实现局部刷新,多页面实现不了。这里稍微的讲了一些单页面和多页面的一些知识,大家要知道 Vue 是一个单页面应用,其页面的跳转需要通过路由:Vue-router!!! vue-router的安装我们已经在前面的文章里讲过了,今天这篇文章就讲vue-router的使用。基本使用src/router/index.jsimport Vue from ‘vue’import Router from ‘vue-router’import Parent from ‘@/components/Parent’import Childs1 from ‘@/components/Childs1’import Childs2 from ‘@/components/Childs2’Vue.use(Router)export default new Router({ mode:‘history’, routes: [ { path:’/parent’, name:‘Parent’, component:Parent }, { path:’/child1’, name:‘Childs1’, component: Childs1 }, { path: ‘/child2’, name:‘Childs2’, component:Childs2 } ]})运行结果如下图:我们输入不同的路由不同的组件被渲染出。首先我们将需要在路由里面渲染的组件引入,然后配置路由。path:是我们需要配置的路径名,component: 是我们需要在该路径下渲染的组件。路由嵌套我们在开发的过程中不应该只有一级路由。比如上面的例子,child应该放在`parent的下面,name我们将怎么样实现路由的嵌套呢?当然是用路由嵌套啦~src/router/index.jsimport Vue from ‘vue’import Router from ‘vue-router’import Parent from ‘@/components/Parent’import Childs1 from ‘@/components/Childs1’import Childs2 from ‘@/components/Childs2’Vue.use(Router)export default new Router({ mode:‘history’, routes: [ { path:’/parent’, name:‘Parent’, component:Parent, children: [ {path:‘child1’, component: Childs1}, {path:‘child2’, component: Childs2} ] } ]})Parent.vue<template><div> Parent <router-view> </router-view></div></template>运行结果如下图:Parent.vue 的 <router-view> </router-view>是渲染其组路由组件的地方。我们可以看到url为/parent的时候,页面上只有paernt的字符串,当我们路由为两层的时候,parent和child全部展示在页面上。vue-router 会根据不同的路由加载不同的组件。动态路由如果我们要将某一种模式下的路由全部映射到同一个组件上,比如我们要将’/user/tom’ 和 ‘/user/David’ 都匹配到同样组件下面,那么动态路由是我们不二的选择。 src/router/index.jsimport Vue from ‘vue’import Router from ‘vue-router’import Parent from ‘@/components/Parent’import Childs1 from ‘@/components/Childs1’Vue.use(Router)export default new Router({ mode:‘history’, routes: [ { path:’/parent’, name:‘Parent’, component:Parent, children: [ {path: ‘child1/:name’, component:Childs1} ] } ]})Parent.vue<template><div> Parent <router-view></router-view></div></template>Childs1.vue<template> <div> Childs1– -{{$route.params.name}} </div></template>运行结果如下图:我们虽然在/child1后面输入不同的路径,但是最后全部映射到同一个组件上。this.$route.params对象存放我们的动态路由的内容。动态路由引起的组件复用动态路由就是将不同的路由映射到同一个组件上,如果两个路由是匹配到同一组件,那么Vue不会将当前组件销毁重建,而是直接替换不一样的内容,实现组件的复用。 src/router/index.js 同上Parent.vue<template><div> Parent <router-view></router-view></div></template>Childs1.vue<template> <div> Childs1– -{{$route.params.name}} <button @click=“change”>点我去aa</button> </div></template><script>export default { name:‘Childs1’, data(){ return{ title: 1 } }, methods:{ change(){ this.$router.push(’/parent/child1/aa’ + this.title++); } }, mounted(){ console.log(‘child1 mounted’,new Date().toLocaleString()); }}</script>运行结果如下图:我们使用编程式导航来进行路由切换,title的初始值唯一,在我们点击按钮进行页面切换的时候,title没有变成初始值,而是复用了前一个页面的组件,在原来的基础上自增。第二章图片也显示,只有第一次进入的时候进入了生命周期钩子,以后的页面切换不再进入钩子。编程式导航和声明式导航编程式导航是调用方法push进行路由跳转,声明式导航是类似于a标签一样的<router-link to=’/parent’></router-link>的标签进行跳转。to属性的内容就是我们要跳转的目标路由。声明式导航最终渲染到页面也是a标签。 声明式导航在被点击的时候会调用编程式导航的方法。Parent.vue*<template> <div> <ul> <router-link to=’/parent/child1/bb’> <li>点我去bb</li> </router-link> <router-link to=’/parent/child1/cc’> <li>点我去cc</li> </router-link> <router-link to=’/parent/child1/dd’> <li>点我去dd</li> </router-link> </ul> <router-view></router-view> </div></template>Childs1.vue同上 运行结果如下图:li的外面包裹着router-link,当我们点击的时候,路由就会跳转到我们to指向的URL,我们点击按钮的时候,调用了’this.$router.push(url)‘方法来进行跳转。这两种方法没有好与坏的区别,只是使用于不同的场景。router.push()push往history栈中加入一条记录,所以当我们使用浏览器的后退按钮时,还能够回到这一页。router.replace()replace是替换栈中当前页的记录,意味着history栈中不会再有当前页的记录。这种方法通常用来授权页,这样就不会有二次授权的情况出现。router.go()go是告诉浏览器在history栈中前进或者后退几步,所以我们一般的页面跳转用push才能在栈中新增一条记录,便于go使用。 ...

January 29, 2019 · 1 min · jiezi

vue-cli3.0 vue.config.js 配置详解

module.exports = { // 项目部署的基础路径 // 我们默认假设你的应用将会部署在域名的根部, // 比如 https://www.my-app.com/ // 如果你的应用时部署在一个子路径下,那么你需要在这里 // 指定子路径。比如,如果你的应用部署在 // https://www.foobar.com/my-app/ // 那么将这个值改为 /my-app/ baseUrl: ‘/’, // 将构建好的文件输出到哪里 outputDir: ‘dist’, // 放置静态资源的地方 (js/css/img/font/…) assetsDir: ‘’, // 用于多页配置,默认是 undefined pages: { index: { // 入口文件 entry: ‘src/index/main.js’, // 模板文件 template: ‘public/index.html’, // 输出文件 filename: ‘index.html’, // 页面title title: ‘Index Page’ }, // 简写格式 // 模板文件默认是 public/subpage.html // 如果不存在,就是 public/index.html. // 输出文件默认是 subpage.html. subpage: ‘src/subpage/main.js’ }, // 是否在保存的时候使用 eslint-loader 进行检查。 // 有效的值:ture | false | "error" // 当设置为 "error" 时,检查出的错误会触发编译失败。 lintOnSave: true, // 使用带有浏览器内编译器的完整构建版本 // 查阅 https://cn.vuejs.org/v2/guide/installation.html#运行时-编译器-vs-只包含运行时 runtimeCompiler: false, // babel-loader 默认会跳过 node_modules 依赖。 // 通过这个选项可以显式转译一个依赖。 transpileDependencies: [/* string or regex */], // 是否为生产环境构建生成 source map? productionSourceMap: true, // 调整内部的 webpack 配置。 // 查阅 https://github.com/vuejs/vue-docs-zh-cn/blob/master/vue-cli/webpack.md chainWebpack: () => {}, configureWebpack: () => {}, // CSS 相关选项 css: { // 将组件内的 CSS 提取到一个单独的 CSS 文件 (只用在生产环境中) // 也可以是一个传递给 extract-text-webpack-plugin 的选项对象 extract: true, // 是否开启 CSS source map? sourceMap: false, // 为预处理器的 loader 传递自定义选项。比如传递给 // sass-loader 时,使用 { sass: { ... } }。 loaderOptions: {}, // 为所有的 CSS 及其预处理文件开启 CSS Modules。 // 这个选项不会影响 *.vue 文件。 modules: false }, // 在生产环境下为 Babel 和 TypeScript 使用 thread-loader // 在多核机器下会默认开启。 parallel: require(‘os’).cpus().length > 1, // PWA 插件的选项。 // 查阅 https://github.com/vuejs/vue-docs-zh-cn/blob/master/vue-cli-plugin-pwa/README.md pwa: {}, // 配置 webpack-dev-server 行为。 devServer: { open: process.platform === ‘darwin’, host: ‘0.0.0.0’, port: 8080, https: false, hotOnly: false, // 查阅 https://github.com/vuejs/vue-docs-zh-cn/blob/master/vue-cli/cli-service.md#配置代理 proxy: null, // string | Object before: app => {} }, // 三方插件的选项 pluginOptions: { // … }} ...

January 27, 2019 · 2 min · jiezi

vue-cli 构建 vue 项目详解

构建一个 vue 项目最简单的方式就是使用脚手架工具 vue-cli 。前端的三大框架都有自己的脚手架工具,其作用就是用配置好的模板迅速搭建起一个项目工程来,省去自己配置 webpack 配置文件的基本内容,大大降低了初学者构建项目的难度。这节我们看看如何使用 vue-cli 构建 vue 项目以及对构建项目的具体分析。一、环境搭建node 和 npm 是必不可少的,这里不再介绍。1、安装 vue-cli$ npm install -g vue-cli检查是否安装成功:$ vue –version3.3.0<!– more –>2、构建项目$ vue init webpack hello-vue初始化的过程中,会有一个交互式的选项让你选择项目的一些配置,根据项目需求选择即可。为了方便后面几篇教程的演示,可以统一选择以下选项:? Project name hello-vue # 项目名称? Project description A Vue.js project # 项目描述? Author Deepspace <cxin1427@gmail.com> # 作者? Vue build standalone # 运行+编译时? Install vue-router? Yes # 安装 vue-router? Use ESLint to lint your code? Yes # 使用 ESLint 作为代码规范? Pick an ESLint preset Airbnb # 选择 Airbnb 的代码规范? Set up unit tests Yes # 安装单元测试? Pick a test runner karma # 测试模块? Setup e2e tests with Nightwatch? Yes # 安装 e2e 测试? Should we run npm install for you after the project has been created? (recommended) npm # 包管理器,npm构建完成之后,会提示构建成功信息:# Project initialization finished!# ========================To get started: cd hello-vue npm run devDocumentation can be found at https://vuejs-templates.github.io/webpack3、启动项目$ cd hello-vue$ npm run dev项目默认会在 8080 端口启动,如果端口有占用,会自动调整端口。打开浏览器输入:http://localhost:8080,会看到构建的项目的主页:4、目录结构使用编辑器打开(推荐使用 VSCode),下面具体看看目录结构:package.json :{ “scripts”: { “dev”: “webpack-dev-server –inline –progress –config build/webpack.dev.conf.js”, “start”: “npm run dev”, “unit”: “cross-env BABEL_ENV=test karma start test/unit/karma.conf.js –single-run”, “e2e”: “node test/e2e/runner.js”, “test”: “npm run unit && npm run e2e”, “lint”: “eslint –ext .js,.vue src test/unit test/e2e/specs”, “build”: “node build/build.js” }}在 package.json 中,根据我们在构建项目的时候的选项,有以下几个命令。npm run dev :项目开发阶段,项目启动的命令;npm run lint :使用 eslint 检查代码格式;npm run test:单元测试和 e2e 测试;npm run e2e : e2e 测试;npm run build:开发完成后执行,会把我们的源代码编译成最终的发布代码,生成在项目根目录中的 dist 文件夹下(初始化项目时不会生成)。config: 保存一些项目初始化配置。build :里面保存一些 webpack 的初始化配置。index.html : 是我们的首页。index 很多时候都被预设为首页,像 index.htm,index.php 等。src : 保存项目源代码的地方,我们下面会详细分析该文件夹里的文件。二、代码分析Vue 的核心架构分为两个部分:路由和组件,其实 React 也是一样的。我们在切入一个项目的时候,都是从这两个点出发。下面我们具体看看 src 文件夹。1、入口文件如果我们打开项目根目录下 build 目录中的 webpack.base.conf.js,会看到这样的代码(第22行):module.exports = { context: path.resolve(__dirname, ‘../’), entry: { app: ‘./src/main.js’ }, // …} 说明我们的入口文件就是 src 目录下的 main.js 文件。看看代码:// The Vue build version to load with the import command// (runtime-only or standalone) has been set in webpack.base.conf with an alias.import Vue from ‘vue’;import App from ‘./App’;import router from ‘./router’;Vue.config.productionTip = false;/* eslint-disable no-new */new Vue({ el: ‘#app’, router, components: { App }, template: ‘<App/>’,});看看这里面做了什么事情:引入 vue 并起名叫作 Vue引入 根目录下的 App.vue 文件(后缀名可不要)引入 router 文件下的 index.js 文件(文件夹后没有具体的文件,默认引入的就是 index.js 文件)通过 new 实例化 Vue 实例 ,实例化的时候声明了几个属性:el:’#app’:意思是将所有视图放在 id 值为 app 这个 dom 元素中,也就是项目根目录下的 index.html 中的那个 div : <div id=“app”></div>;components: { App }:意思是将上面引入的 App.vue 文件的内容将以 <App/> 这样的标签写进 <div id=“app”></div> 中;在开始的时候,我们并没有介绍说 Vue 使用的是虚拟 DOM ,那么,从这里我们看出,Vue 使用的也是虚拟 DOM (和React是一样的)。这里对虚拟 DOM 作下简单介绍:当我们修改应用程序时,不会对 DOM 进行更改,而是创建以 JavaScript 数据结构形式存在的 DOM 副本,然后插到文档当中。无论何时进行任何更改,都将对 JavaScript 数据结构进行更改,并将后者与原始数据结构进行比较(diff算法),然后将最终更改更新为真实 DOM。我们都知道 DOM 是非常重的,所以虚拟 DOM 是非常省性能的。2、App.vue通过入口文件中做的事情,我们其实已经知道 App.vue 的作用了:单页面应用的主组件。所有页面都是在 App.vue 下通过路由进行切换的。所以,我们可以理解为所有的路由(route)也是 App.vue 的子组件。我们看看代码:<template> <div id=“app”> <img src="./assets/logo.png"> <router-view/> </div></template><script>export default { name: ‘App’,};</script><style>#app { font-family: ‘Avenir’, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px;}</style>这里需要提一下:node 之所以可以识别出 *·vue 格式的文件,是因为 webpack 在编译时将 *.vue 文件中的 html 、js 、css 都抽出来形成新的单独文件。可通过 npm run build 命令编译源代码,查看 dist 文件下的文件来验证。App.vue 的内容分为三个部分:<template>…</template>、<script>…</script>、<style>…</style> ,分别在这三类标签里面写入结构、脚本、样式。我们先从 <template> 看起:里面一个 div 包裹着 img 标签和 router-view 标签。前面提到过: App.vue 是单页面应用的主组件。对照着前面在浏览器中打开的应用主页面,img 标签就是页面上方的 Vue 的 logo。那下面的内容去哪了呢?和 <router-view/> 有关系吗?这就要去看路由了。3、router/index.jsimport Vue from ‘vue’;import Router from ‘vue-router’;import HelloWorld from ‘@/components/HelloWorld’;Vue.use(Router);export default new Router({ routes: [ { path: ‘/’, name: ‘HelloWorld’, component: HelloWorld, }, ],});前面先引入了路由插件 vue-router,然后显式声明要用路由 Vue.use(Router) 。路由的配置非常地明了:给不同 path 分配不同的组件(或者页面),参数 name 只是用来识别。当我访问根路由 http://localhost:8080/#/ 时,App.vue 中的 <router-view/> 就会把引入的 HelloWorld 组件分配给我,放在了 img 标签的下面,打开 components 目录下的 HelloWorld.vue 就可以看到具体内容了。我们在看到浏览器中的 url 的时候会觉得奇怪,为什么在后面加了一个 # 号呢?这是因为 vue-router 默认 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,当 URL 改变时,页面不会重新加载。详见:https://router.vuejs.org/zh/g… 。这里可先跳过这点内容。现在,我们在浏览器访问 http://localhost:8080/#/vue 这个地址,会发现只出现了 Vue 的 logo。这是因为我们并没有配置 /vue 这个路由,找不到路由,那<router-view/> 这个标签就不会加载出来。到这里,我们就知道路由是如何根据 url 来分配不同的组件了。配置多个路由就很简单了:export default new Router({ routes: [ { path: ‘/’, name: ‘HelloWorld’, component: HelloWorld }, { path: ‘/about’, name: ‘about’, component: About }, { path: ‘/vue’, name: ‘vue’, component: Vue } ]})那如果要访问 http://localhost:8080/#/vue/demo 怎么办呢?export default new Router({ routes: [ { path: ‘/’, name: ‘HelloWorld’, component: HelloWorld, }, { path: ‘/about’, name: ‘about’, component: About, }, { path: ‘/vue’, name: ‘vue’, component: Vue, children: [ { path: ‘/demo’, component: demo, }, { path: ‘/project’, component: project, }, ], }, ],});给路由加多一个子路由配置即可。4、assets用来存放一些图片、样式等静态文件。三、总结欢迎关注我的博客:https://togoblog.cn/ ...

January 26, 2019 · 3 min · jiezi

基础知识:vue-cli项目搭建及配置

vue-cli脚手架搭建// 准备 npm install vue-cli -g确保已全局安装node、npm // 下载 vue init webpack my-project下载脚手架项目// 进入 cd my-project // 运行 npm start把服务跑起来 // 访问 localhost:8080// 了解 以下为vue-cli的结构图config/index.js端口// 更改端口port: 3000,打开浏览器// 是否在编译完成后,// 自动打开浏览器访问http://localhost:3000autoOpenBrowser: false, 代理proxyTable: { // 接口跨域 // 解决跨域的问题 ‘/lots-web/**’: { target: ‘http://localhost:8080’ // 接口的域名 }, // 开发环境本地数据挂载 // json数据文件路径:static/mock/index.json ‘/api’: { target: ‘http://localhost:7000’, pathRewrite: { ‘^/api’: ‘/static/mock’ } }}build/webpack.base.conf.js路径配置alias: { ‘vue$’: ‘vue/dist/vue.esm.js’, ‘@’: resolve(‘src’), // styles ‘styles’: resolve(‘src/assets/styles’)} scss预编译// 安装模块:// npm install –save-dev sass-loader// npm install –save-dev node-sass{ test: /.sass$/, loaders: [‘style’, ‘css’, ‘sass’]}修改文件:xxx.vue<style lang=‘scss’ scoped><style>build/utils.jsvariables.scss预编译// 全局引用variables.scss变量文件 // 安装模块:// npm install –save-dev sass-resources-loaderscss: generateLoaders(‘sass’).concat( { loader: ‘sass-resources-loader’, options: { resources: path.resolve(__dirname, ‘../src/assets/styles/variables.scss’) } })variables.styl预编译// 全局引用variables.styl变量文件 // 安装模块:// npm install –save-dev stylus// npm install –save-dev stylus-loaderconst stylusOptions = { import: [ path.join(__dirname, “../src/assets/styles/variables.styl”) ]}return { stylus: generateLoaders(‘stylus’, stylusOptions), styl: generateLoaders(‘stylus’, stylusOptions)}src/main.js初始 主文件import Vue from ‘vue’import App from ‘./App’import router from ‘./router’ // 路由// 设置为 false 以阻止 vue 在启动时生成生产提示Vue.config.productionTip = false new Vue({ el: ‘#app’, router, components: {App}, template: ‘’}) 详细 主文件// 入口 import router from ‘./router’ // 路由import store from ‘./store’ // 状态import api from ‘./utility/api’ // 接口 // 模块 import axios from ‘axios’ // 接口调用import ‘babel-polyfill’ // ie9和一些低版本的浏览器对es6新语法的不支持问题import fastClick from ‘fastclick’ // 延迟300毫秒import VueAwesomeSwiper from ‘vue-awesome-swiper’ // 图片轮播import BScroll from ‘better-scroll’ // 拖动插件 // 公用样式 import ‘styles/reset.css’ // 重置import ‘styles/common.css’ // 公共import ‘styles/border.css’ // 1像素边import ‘styles/iconfont.css’ // 文字图标import ‘swiper/dist/css/swiper.css’ // 图片轮播// 公用组件 import Fade from ‘@/pages/common/fade’ // 显隐过渡import Gallery from ‘@/pages/common/gallery’ // 画廊Vue.component(‘c-fade’, Fade)Vue.component(‘c-gallery’, Gallery) // 全局调用 Vue.use(VueAwesomeSwiper) // 图片轮播Vue.prototype.$scroll = BScrollVue.prototype.$http = axiosVue.prototype.$api = api // 其他 fastClick.attach(document.body) // 为消除移动端浏览器,从物理触摸到触发点击事件之间的300ms延时的问题 // 创建Vue new Vue({ el: ‘#app’, router, store, components: {App}, template: ‘<App/>’})src/App.vuevue入口文件// keep-alive数据缓存 <keep-alive :exclude=“exclude”> <router-view/></keep-alive>data(){ return { exclude: [ ‘Detail’ ] }}// 用法 // 1、如不填,则缓存全部组件// 2、keep-alive include=“City”,缓存name=‘City’的组件// 3、keep-alive exclude=“Detail”,不缓存name=‘Detail’的组件// 生命周期 // 当时用keep-alive的时候,会触发activated和deactivated生命周期// activated 当组件被激活的时候调用// deactivated 当组件被移除的时候调用src/router/index.js路由文件人口// 初始 import Vue from ‘vue’import Router from ‘vue-router’import Home from ‘@/pages/home/home’export default new Router({ routes: [ { path: ‘/home’, component: Home } ])} // 组件和路由路径 import Home from ‘@/pages/home/home’const path = { home: ‘/’} // 路由和组件渲染 routes: [ { path: path.home, component: Home }] // 路由"#“号去除 mode: ‘history’, // 当前路由添加.activelinkActiveClass: ‘active’,linkExactActiveClass: ‘active’, // 切换路由时界面始终显示顶部 scrollBehavior(to, from, savePosition){ return { x: 0, y: 0 }} // vue用$route获取router // $router// 路由:’/detail/:name’ // ‘/detail/lzm’// this.$route.params.name// 路由:’/detail’ // ‘detail?name=lzm’// this.$route.query.name src/store/index.js状态管理文件入口// 状态管理 import Vue from ‘vue’import Vuex from ‘vuex’import state from ‘./state’import mutations from ‘./mutations’import actions from ‘./actions’Vue.use(Vuex)export default new Vuex.Store({ state, mutations, actions}) // 第四步state.js let defaultCity = { id: 1, spell: ‘beijing’, name: ‘北京’}if(localStorage.city){ defaultCity = JSON.parse(localStorage.city) // 字符串转对象}const state = { city: defaultCity}export default state// 第三步mutations.js const mutations = { changeCity(state, payload){ state.city = payload localStorage.city = JSON.stringify(payload) // 当为对象是,要转字符串 }}export default mutations// 第二步actions.js const actions = { changeCity(context, payload){ context.commit(‘changeCity’, payload) }}export default actions// 第一步xxx.vue // template部分:<div @click=“handleClick(item)">{{city}}</div>// script部分:import { mapState, mapActions} from ‘vuex’export default { computed: { …mapState([‘city’]) }, methods: { …mapActions([‘changeCity’]) handleClick(city){} this.changeCity(city) } }}axios$http调用接口// 全局调用 // 修改main.js文件Vue.prototype.$http = axios// xxx.vue文件:this.$http .get(’/api/index.json’, { params: {…} }) .then( fn(data) ).catch( fn(data )); // 局部调用 // xxx.vue文件:import axios from ‘axios’axios.get(’/api/index.json’) .then( fn(data) ) .catch( fn(data) ); // 案例 getHomeData() { this.$http .get(this.$api.home, { params: { name: this.city.name } }) .then(res => { let resData = res.data; if (resData.ret && resData.data) { let data = resData.data this.bannerList = data.bannerList this.iconList = data.iconList this.likeList = data.recommendList this.weekendList = data.weekendList } }) .catch((err) => { console.log(err) })}移动端移动端初始配置// 移动端访问 // 修改package.json文件:–host 0.0.0.0// mac查看ip: ifconfig// windows查看ip: ipconfig// 手机访问地址: ip:7000 // 缩放比例 // 修改文件:index.html<meta minimum-scale=1.0, maximum-scale=1.0, user-scalable=no><meta width=“device-width, height=device-height, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no”> // 初始化样式 reset.css // 1px像素设备不一致 borer.css // 延迟300ms // 模块 fastclick 解决移动端事件延迟300ms// main.js文件加入:fastClick.attach(document.body) // stylus运用 // 模块 stylus stylus-loader 类似scss预编译// xxx.vue文件:style lang=“stylus"iconfont文字图标// 网址 [http://www.iconfont.cn][2] // 步骤 // 选择图标加入购物车 →// 添加到项目 →// 下载到本地 →// 字体和css复制到项目 →// 更改iconfont目录和删除代码 →// 引入iconfont.css →<span class=“iconfont user-icon”>&#x e624;><span>better-scroll拖动使界面滚动// 全局 // 修改main.js文件:import BScroll from ‘better-scroll’Vue.prototype.$scroll= BScrollxxx.vue文件:mounted() { this.scroll = new this.$scroll(elevent); // element为dom或$refs}, // 局部 // xxx.vue文件:import BScroll from ‘better-scroll’this.scrolll = new BScroll(this.$refs.wrapper)// 定位到某个元素 this.scroll.scrollToElement(element) vue-awesome-swiper图片轮播// 网址 [https://www.swiper.com.cn/][3] // 步骤 // 安装模块 vue-awesome-swiper 轮播插件(2.6.7)// 修改main.js:import “swiper/dist/css/swiper.css"Vue.use(VueAwesomeSwiper)xxx.vue文件:<swiper :options=“swiperOption” v-if=“hasBanner”> <swiper-slide v-for=“item in list”> <img :src=“item.imgUrl”> </swiper-slide> <div class=“swiper-pagination” slot=“pagination”></div></swiper>swiperOption: { pagination: ‘.swiper-pagination’, autoplay: 3000, paginationType: ‘fraction’, loop: true}router-link路由链接// router-link组件的active设置 // 全局设置:export default new VueRouter({ linkActiveClass: ‘active’, linkExactActiveClass: ‘active’, routes : [ … 省略 ]});// 局部设置:<router-link :to="‘home’” tag=“li” active-class=“active” exact-active-class=“active” exact><标题router-link>// 加上exact 则遵循路由完全一致模式,该路由下的路径不匹配 // 标准 <router-link :to=”’/detail?name=’ + item.name” tag=“div”></router-link> // 路由跳转 this.$router.push(’/’)、this.$router.replace(’/’) fade过渡动画// template <transition> <slot></slot></transition> // style <style lang=“stylus” scoped>.v-enter, .v-leave-to opacity 0.v-enter-active, .v-leave-active transition opacity .5s</style>// name name=“fade”.fade-entertouch拖动事件// touchstart/touchmove <div class=“letter” @click=“handleClickLetter” @touchstart.prevent=“handleTouchStart” @touchmove=“handleTouchMove” ref=“letter”> <div class=“letter-cont” ref=“letterCont”> <span class=“letter-item” v-for=“item in list” :key=“item”>{{item}}</span> </div></div>methods: { handleClickLetter(e) { const letter = e.target.innerHTML this.$emit(‘change’, letter) }, handleTouchStart() { this.letterHeight = this.$refs.letterCont.clientHeight / this.letterLen this.letterOffsetTop = this.$refs.letter.offsetTop + this.$refs.letterCont.offsetTop }, handleTouchMove(e) { let touchY = e.touches[0].clientY let letterScope = (touchY - this.letterOffsetTop) / this.letterHeight if (letterScope > 0 && letterScope < this.letterLen) { if (this.timer) clearTimeout(this.timer) this.timer = setTimeout(() => { this.letterIndex = Math.floor(letterScope) }, 16) } }}其他组件里name的作用// 1、递归组件会用到// 2、取消缓存的时候会用到// 3、浏览器vue插件显示组件的时候用到子父组件传值// 子组件:handleClick(){ this.$emit(‘change’, value)}// 父组件:<component @change=“handleClick”></component>handleClick(){} $refs// this.$refs.msg 普通元素,引用指向dom:<div ref=‘msg’>Hello, world<div>// this.$refs.child 组件,引用指向组件实例:<c-child ref=‘child’>Hello, world<c-child>$route获取url数据// 1. /detail/:id// /detail/1389435894this.$route.params.id// 2. /detail// /detail?id=1389435894this.route.query.id利用setTimeout节流if(this.timer) clearTimeout(timer);this.timer = setTimeout(()=>{ console.log(‘‘xxx’)}, 16);滚动监听// 1.window.onscroll = this.handleScroll// 2.window.addEventListener(‘scroll’, this.handleScroll)浏览器cookielocalStorage.city = citylocalStorage.clear() ...

January 25, 2019 · 4 min · jiezi

Vue动态组件和异步组件

动态组件如果我们打算在一个地方根据不同的状态引用不同的组件的话,比如tab页,那么Vue给我们提供动态组件。基本使用Parent.vue<template><div> <el-button-group> <el-button v-for=’(btn, index) in btnGroup’ :key=“index” :class="{active:btn.disabled}" @click=‘change(index)’>{{btn.name}} </el-button> </el-button-group> <div> <component :is=‘currentCom’></component> </div></div></template><script>import Childs1 from ‘./Childs1’import Childs2 from ‘./Childs2’import Childs3 from ‘./Childs3’import Childs4 from ‘./Childs4’export default { name:‘Parent’, components:{ Childs1, Childs2, Childs3, Childs4 }, data() { return { btnGroup: [ {name: ‘Childs1’, disabled: true}, {name: ‘Childs2’, disabled: false}, {name: ‘Childs3’, disabled: false}, {name: ‘Childs4’, disabled: false}, ], currentCom:‘Childs1’ } }, methods: { change(index){ let pre = Number(this.currentCom[this.currentCom.length -1]); this.btnGroup[pre -1].disabled = false; this.btnGroup[index].disabled = true; this.currentCom = ‘Childs’ + (index + 1); } }}</script><style scoped>.active{ background-color: red;}</style>运行结果如下图:当我们点击不同的按钮时,下面会切换不同的组件。实现动态组件的加载。is 的值可以是一个已经注册的组件的名字或者一个组件的选对象。当我们点击按钮时,这个按钮的 disabled 为 true 然后我们将给这个按钮一个active 的css类,同时改变 currentCom 的值keep-alive:动态组件的缓存如果我们需要频繁的切换页面,每次都是在组件的创建和销毁的状态间切换,这无疑增大了性能的开销。那么我们要怎么优化呢? Vue提供了动态组件的 缓存。keep-alive 会在切换组件的时候缓存当前组件的状态,等到再次进入这个组件,不需要重新创建组件,只需要从前面的缓存中读取并渲染。Parent.vue(其余地方代码和上面一样)<template><div> <el-button-group class=‘btn-group’> <el-button v-for=’(btn, index) in btnGroup’ :key=“index” :class="{active:btn.disabled}" @click=‘change(index)’> {{btn.name}} </el-button> </el-button-group> <div style=‘padding-top:100px;’> <keep-alive> <component :is=‘currentCom’></component> </keep-alive> </div></div></template><style scoped>.btn-group{ position:fixed;}.active{ background-color: red;}</style>Childs1.vue<template> <div> {{title}} <button @click=‘change’>点我+1</button> </div></template><script>export default { name:‘Childs1’, data(){ return{ title: 1 } }, methods:{ change(){ this.title += 1; } }, mounted(){ console.log(‘child1 mounted’); }}</script>Childs2.vue<template> <div> Childs2 </div></template><script>export default { name:‘Childs2’, mounted(){ console.log(‘child2 mounted’); }}</script>运行结果如下图: ‘对比:如果我们将<keep-alive></keep-alive>去掉,运行结果如下图:前一组图片在切换组件的时候,title从1加到3,然后等下次再切换回来的时候,title还是停留在3,从控制台可以看出,Childs1.vue这个组件的mounted的钩子函数只有一次。后一组图片,title一开始加到3,下一次进入这个组件的时候title又从1开始,控制台图片也显示这个组件经历个了多次钩子函数,说明组件是销毁重建的。 tips:因为缓存的组件只需要建立一次,所以如果我们要在每次进入组件的钩子函数里面做相应的操作的时候,会出现问题,所以请明确我们使用的场景,避免出现bug异步组件异步组件存在的意义在于加载一个体量很大的页面时,如果我们不设置加载的优先级的话,那么可能页面在加载视频等信息的时候会非常占用时间,然后主要信息就会阻塞在后面在加载。这对用户来说无疑不是一个很差的体验。但是如果我们设置加载的顺序,那么我们可以优先那些最重要的信息优先显示,优化了整个项目。一般来说我们是将加载组件和 路由 (vue-router)配合在一起使用,所以这里我就不细讲了,具体学习可以参考官网来进行学习。 ...

January 25, 2019 · 1 min · jiezi

收集vue2精佳文章,一月下半月 - 岂敢定居,一月三捷

一月: 一年之计在于春,一月是一年的开始一月下半月-岂敢定居,一月三捷。(01.16~01.31):寄徐丞 [宋] 赵师秀 病不窥园经一月,更无人迹损青苔。 池禽引子衡鱼去,野蔓开花上竹来。 亦欲鬓毛休似雪,争如丹汞只为灰。 秋风昨夜吹寒雨,有梦南游到海回。文章列表【收藏】2019年最新Vue相关精品开源项目库汇总创建vue-cli框架项目VuePress博客搭建笔记(二)个性化配置【前端笔记】Vuex快速使用vue -on如何绑定多个事件基于vue的验证码组件Vue自定义Toast插件Vue添加数据视图不更新问题聊一聊Vue组件模版,你知道它有几种定义方式吗?深入学习Vue SSR服务端渲染 用Nuxt.js打造CNode社区vue 源码学习(二) 实例初始化和挂载过程使用NodeJS 生成Vue中文版 docSet 离线文档手牵手教你写 Vue 插件Vue项目部署遇到的问题及解决方案预计今年发布的 Vue 3.0 到底有什么不一样的地方?记一次 Vue 单页面上线方案的优化vue-cli3使用svg问题的简单解决办法从react转职到vue开发的项目准备基于 Vue-Cli3 构建的脚手架模版新手福音用vue-cli3从0到1做一个完整功能手机站(一)vue-cli3 从搭建到优化Spring Security (三):与Vue.js整合电商网站项目总结:Vuex 带来全新的编程体验结合vue-cli来谈webpack打包优化vue开发环境配置跨域,一步到位Vue新手向:14篇教程带你从零撸一个Todo应用Vue2.0 核心之响应式流程基于Vue的任务节点图绘制插件(vue-task-node)Vue 实践小结vue项目接口管理【vue-cli3升级】老项目提速50%(二)Vuex 是什么,为什么需要【收藏】2019年最新Vue相关精品开源项目库汇总创建vue-cli框架项目VuePress博客搭建笔记(二)个性化配置RFCs for substantial changes / feature additions to Vue core 3.0February 14-15 - Vue.js AmsterdamMarch 25-27 - VueConf US in Tampa, FLApril 12th, VueDay 2019, Verona, Italy – Call for papers until 1st FebruaryIncoming workshop: Proven patterns for building Vue apps by Chris Fritz10 Best Tips for Learning Vue from Vue MastersImprove performance on large lists in VueBuild a Beautiful Website with VuePress and Tailwind.cssSelectively enable SSR or SPA mode in a Nuxt.js appGive Users Control Over App Updates in Vue CLI 3 PWAsWhen to “componentize” from the point of VueVue Route Component HooksWatch for Vuex State changes!GitHub - egoist/styled-vueGitHub - Justineo/vue-clampGitHub - edisdev/vue-datepicker-uiVue2+周报不积跬步,无以至千里;不积小流,无以成江海丁酉年【鸡年】/戊戌年【狗年】/己亥年【猪年】 对【Vue相关开源项目库汇总】的Star更新排名几个值得收藏的国外有关Vue.js网站(https://segmentfault.com/a/11… :conf.vuejs.org国外一个Vue.js视频教程scotch网站的技术视频教程vue-hackernews-2.0Weekly dose of handpicked Vue.js news!vuejsdevelopers-Vue开发者网站还是个人的?vuejsfeed-最新的Vue.js新闻、教程、插件等等vuecomponents-Vue.js组件集合社区madewithvuejs-收藏了用Vue.js实现的网站vuejsexamples-Vue.js的Demo满满的最新vueNYC资讯:VueNYCVueNYC - Vue.js: the Progressive Framework - Evan Youtwitter-search-VueNYC尤大大的PPT我已经上传了../PPT/Vue.js the Progressive Framework.pdf最新2018 VueConf资讯: (第二届VueConf将于2018年11月24日在杭州举行) ::资料:: ::PPT::更多资讯集web前端最近很火的vue2框架资源;定时更新,欢迎 Star 一下。:::【点击我】::: ...

January 25, 2019 · 1 min · jiezi

Calls to 'console.log' are not allowed

使用Vue CLI 3 的 vue create 创建vue+ts 项目,使用默认配置, 控制台报警告Calls to ‘console.log’ are not allowed,解决:在tsling.json中的rules下 添加: “no-console”: false。无需向在tsling.config中添加"extends":"./tslint.config"。重启服务,搞定。附tsling.json文件:{ “defaultSeverity”: “warning”, “extends”: [ “tslint:recommended” ], “linterOptions”: { “exclude”: [ “node_modules/**” ] }, “rules”: { “quotemark”: [true, “single”], “indent”: [true, “spaces”, 2], “interface-name”: false, “ordered-imports”: false, “object-literal-sort-keys”: false, “no-consecutive-blank-lines”: false, “max-line-length”: [ false ], “no-console”: false }}

January 21, 2019 · 1 min · jiezi

Vue CLI 3 报错,Cannot find module 'path'.

安装Vue CLI 3 创建vue typescript 项目 问题:使用vue create proName 后,在.vue文件"import path from ‘path’ ’" 报错 Cannot find module ‘path’. 检查node_modules/@types/node/index.d.ts, 发现 declare moudle “path"存在。解决:更换package.json 中的 “@vue/cli-plugin-typescript”: “^3.0.0” 为 “@vue/cli-plugin-typescript”: “^3.0.0-beta.15"重新执行 yarn

January 17, 2019 · 1 min · jiezi

Vue CLI3开发环境搭建

安装关于旧版本Vue CLI 的包名称由 vue-cli 改成了 @vue/cli。 如果你已经全局安装了旧版本的 vue-cli (1.x 或 2.x),你需要先通过 npm uninstall vue-cli -g 或 yarn global remove vue-cli 卸载它。Node 版本要求Vue CLI 需要 Node.js 8.9 或更高版本 (推荐 8.11.0+)。你可以使用 nvm 或 nvm-windows 在同一台电脑中管理多个 Node 版本。使用以下命令安装这个新的包npm install -g @vue/cli安装之后,用这个命令来检查其版本是否正确 (3.x)vue –version创建一个项目vue create projectname运行以下命令来创建一个新项目:vue create hello-world选择默认(基本的 Babel + ESLint)配置,还是手动配置,上下键控制vue-cli3.0在你创建后会有一个保存当前配置的功能因为之前创建过,提供保存配置的功能,这里选最后一个手动配置一般不要选择eslint 检验你的代码,否则你可能会遇到很多麻烦一般采用 vue-router(路由必备),vuex(全家桶的状态管理器),sass(css扩展语言),babel(使项目可用es6)(你的项目决定你用什么)空格多选TypeScriptPWAVue-routerVuexCSS预处理eslint prettier自动化测试单元测试 、e2e使用图形化界面配置项目vue uiCSS 相关Vue CLI 项目天生支持 PostCSS、CSS Modules 和包含 Sass、Less、Stylus 在内的预处理器。引用静态资源所有编译后的 CSS 都会通过 css-loader 来解析其中的 url() 引用,并将这些引用作为模块请求来处理。这意味着你可以根据本地的文件结构用相对路径来引用静态资源。另外要注意的是如果你想要引用一个 npm 依赖中的文件,或是想要用 webpack alias,则需要在路径前加上 ~ 的前缀来避免歧义。更多细节请参考处理静态资源。附上项目的vue.config.jsmodule.exports = { baseUrl: ‘’, outputDir: ‘dist’, //放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录。 assetsDir: ‘static’, //默认情况下,生成的静态资源在它们的文件名中包含了 hash 以便更好的控制缓存。如果你无法使用 Vue CLI 生成的 index HTML,你可以通过将这个选项设为 false 来关闭文件名哈希。 filenameHashing: true, pages: { index: { // page 的入口 entry: ‘src/main.js’, // 模板来源 template: ‘public/index.html’, // 在 dist/index.html 的输出 filename: ‘index.html’, // 当使用 title 选项时, // template 中的 title 标签需要是 <title><%= htmlWebpackPlugin.options.title %></title> title: ‘Index Page’, // 在这个页面中包含的块,默认情况下会包含 // 提取出来的通用 chunk 和 vendor chunk。 chunks: [‘chunk-vendors’, ‘chunk-common’, ‘index’] }, }, // eslint-loader 是否在保存的时候检查 lintOnSave: process.env.NODE_ENV !== ‘production’, // 是否使用包含运行时编译器的Vue核心的构建 runtimeCompiler: undefined, // 生产环境 sourceMap productionSourceMap: false, //该函数及可以修改配置并不返回任何东西,也可以返回一个被克隆或合并过的配置版本。 configureWebpack: config => { if (process.env.NODE_ENV === ‘production’) { // 为生产环境修改配置… } else { // 为开发环境修改配置… /* var webpack = require(‘webpack’); var webpackConfig = require(’./node_modules/@vue/cli-service/lib/config/dev.js’); var compiler = webpack(webpackConfig); require(‘webpack-dev-middleware-hard-disk’)(compiler, { publicPath: webpackConfig.output.publicPath, quiet: true })*/ } }, //会接收一个基于 webpack-chain 的 ChainableConfig 实例。允许对内部的 webpack 配置进行更细粒度的修改。 chainWebpack: (config) => { // 链式配置 // var webpackConfig = require(’./node_modules/@vue/cli-service/lib/config/dev.js’); // //配置插件:添加 // config // .plugin(‘webpack-dev-middleware-hard-disk’) // .use(require.resolve(‘webpack-dev-middleware-hard-disk’), { // publicPath:webpackConfig, // quiet: true // }); }, // 配置高于chainWebpack中关于 css loader 的配置 css: { sourceMap: true, loaderOptions: { css: { // 这里的选项会传递给 css-loader }, postcss: { // 这里的选项会传递给 postcss-loader } } }, //所有 webpack-dev-server 的选项都支持 // https://webpack.docschina.org/configuration/dev-server/ devServer: { open: true, host: ’localhost’, port: 3000, https: false, hotOnly: true, // proxy: { // ‘/api’: { // // 目标 API 地址 // target: ‘http://114.55.59.209:8080’,//开发环境 // // target: ‘http://192.168.6.163:8080/’,//域名环境 // //如果要代理 websockets // // ws: true, // // 将主机标头的原点更改为目标URL // changeOrigin: true, // pathRewrite:{ // ‘^/api’:’/’ //这个很重要 // } // } // }, before: app => { } }, // 构建时开启多进程处理 babel 编译 parallel: require(‘os’).cpus().length > 1, // https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-pwa pwa: {}, // 第三方插件配置 pluginOptions: { foo: { // 插件可以作为 options.pluginOptions.foo 访问这些选项。 } }}; ...

January 17, 2019 · 2 min · jiezi

vue服务端渲染——Nuxt.js全面配置

Nuxt.js 全面配置nuxt-config: 持续更新中其他系列★ vue-cli3 全面配置<span id=“top”>目录</span>√ 初始化项目√ 环境变量配置√ 打包分析√ 提供全局 scss 变量√ 按需引入 element-ui√ 配置 hard-source-webpack-plugin√ 去除多余 css√ Brotli 压缩<span id=“init”>☞ 初始化项目</span>npx create-nuxt-app <项目名>或npx create-nuxt-app <项目名>▲ 回顶部<span id=“env”>☞ 环境变量配置</span> 可以配置在客户端和服务端共享的环境变量module.exports = { env: { baseUrl: process.env.BASE_URL || ‘http://localhost:3000’ }} 通过以下两种方式来使用 baseUrl 变量通过 process.env.baseUrl通过 context.baseUrl,请参考context api▲ 回顶部<span id=“analyze”>☞ 打包分析</span> package.json 中添加 analyze 命令"analyze": “nuxt build –analyze” 修改 nuxt.config.jsexport default { build: { analyza: { analyzeMode: ‘static’ } }}▲ 回顶部<span id=“scss”>☞ 提供全局 scss 变量</span>方法一:npm i -S @nuxtjs/style-resourcesnpm i -D sass-loader node-sass 修改 nuxt.config.jsexport default { modules: [ ‘@nuxtjs/style-resources’, ], styleResources: { scss: ‘/assets/scss/variable.scss’ }}方法二:npm i -D nuxt-sass-resources-loader sass-loader node-sass 修改 nuxt.config.jsexport default { modules: [ [’nuxt-sass-resources-loader’, [’/assets/scss/variable.scss’]] ], styleResources: { scss: ‘~/assets/scss/variable.scss’ }}▲ 回顶部<span id=“elementui”>☞ 按需引入 element-ui</span>npm i -D babel-plugin-component// oryarn add -D babel-plugin-component 修改 nuxt.config.jsmodule.exports = { plugins: [’@/plugins/element-ui’], build: { babel: { plugins: [ [ ‘component’, { libraryName: ’element-ui’, styleLibraryName: ’theme-chalk’ } ] ] } },} 修改 plugins/element-ui.jsimport Vue from ‘vue’import { Button, Loading, Notification, Message, MessageBox} from ’element-ui’import lang from ’element-ui/lib/locale/lang/zh-CN’import locale from ’element-ui/lib/locale’// configure languagelocale.use(lang)// setVue.use(Loading.directive)Vue.prototype.$loading = Loading.serviceVue.prototype.$msgbox = MessageBoxVue.prototype.$alert = MessageBox.alertVue.prototype.$confirm = MessageBox.confirmVue.prototype.$prompt = MessageBox.promptVue.prototype.$notify = NotificationVue.prototype.$message = Message// import componentsVue.use(Button);// or// Vue.component(Button.name, Button)▲ 回顶部<span id=“hard”>☞ 配置 hard-source-webpack-plugin</span>npm i -D hard-source-webpack-plugin 修改 nuxt.config.jsmodule.exports = { build: { extractCSS: true, extend(config, ctx) { if (ctx.isDev) { config.plugins.push( new HardSourceWebpackPlugin({ cacheDirectory: ‘.cache/hard-source/[confighash]’ }) ) } } }}▲ 回顶部<span id=“removecss”>☞ 去除多余 css</span>npm i –D glob-all purgecss-webpack-plugin 若安装失败,请先用管理员身份安装以下全局依赖npm install –global windows-build-tools或yarn global add windows-build-tools 修改 nuxt.config.jsconst PurgecssPlugin = require(‘purgecss-webpack-plugin’)const glob = require(‘glob-all’)const path = require(‘path’)const resolve = dir => path.resolve(__dirname, dir);module.exports = { build: { extractCSS: true, extend(config, ctx) { if (!ctx.isDev) { config.plugins.push( new PurgecssPlugin({ paths: glob.sync([ resolve(’./pages//*.vue’), resolve(’./layouts//.vue’), resolve(’./components/**/.vue’) ]), extractors: [ { extractor: class Extractor { static extract(content) { const validSection = content.replace( /<style([\s\S]*?)</style>+/gim, "" ); return validSection.match(/[A-Za-z0-9-_:/]+/g) || []; } }, extensions: [‘vue’] } ], whitelist: [‘html’, ‘body’, ’nuxt-progress’] }) ) } } }}▲ 回顶部<span id=“brotli”>☞ Brotli 压缩</span>npm i shrink-ray-current 若安装失败,请先用管理员身份安装以下全局依赖npm install –global windows-build-tools或yarn global add windows-build-tools 修改 nuxt.config.jsexport default { render: { http2: { push: true }, compressor: shrinkRay() }}▲ 回顶部 ...

January 15, 2019 · 2 min · jiezi

新手福音!用vue-cli3从0到1做一个完整功能手机站(一)

开篇从今天起,小肆将和大家从头开始做一个完整的实战项目。其中遇到的每个知识点都是我们工作中常见的,这些知识点大多在网上都能找到但却没有哪个教程能都讲得到,那就由小肆来做吧。关注”技术放肆聊“,跟小肆一起行动起来!在这个项目中,小肆力争做到以下几点:应用目前最新的技术,并随时间更新。尽量多的增加知识点。尽量详细的讲解每个知识点,以便小伙伴们可以灵活应用到别处。尽量做最规范的代码提交记录,以便随时可以在github上查询变更。完全使用实际工作中模式。本项目后端接口采用成熟在线APP的测试服务器接口。对哪个知识点没有清楚理解,随时可以来撩我。涉及功能初始化:脚手架构建、git仓库配置、git提交规范配置、手机自适应配置。。。用户:登录、注册、找回密码、第三方登录、个人中心。。。新闻:滚动导航、幻灯片、文章列表、文章详情、图片懒加载。。。课程:音频播放、视频播放、自定义播放器、播放列表。。。社区:发帖、评论、点赞、收藏。。。支付:虚拟货币、微信支付、支付宝支付。。直播:视频流、礼物、弹幕。。。功能包括以上功能又不仅限于以上功能,这个系列每篇文章都会把涉及到的功能点详细介绍清楚,并会同步到本篇。小肆的代码并不一定是最优的解决方案,如果你有更好的方法,非常期望能与小肆联系,我会在文章中发出并标明出处多说无益,行动起来吧!项目初始化本项目使用最新版本的vue-cli 3.3搭建。安装vue-cli3sudo npm -g install @vue/cli小肆用的mac,所以需要添加sudo获取root权限来全局安装,win用户可以不加sudo。安装成功后输入vue -V你会看到你安装的版本号。创建项目vue creat mweb输入命令后选择手动选择功能(Manually select features)或会看到如下界面:在这里小肆全部选择了,选择TS是因为TS是JS的超集,所以初始化的时候小肆选了TS,不过前期还是会用JS讲解,以便未学习TS的伙伴们学习,后期会全部使用TS重构。这里的每个知识点之后项目实际使用我都会慢慢讲解。上图是安装过程我对每一项的选择。最后保存了配置项目就开始安装依赖了。初始化成功后会显示如下界面。项目预览命令行输入cd mweb进入项目目录。之后输入启动本地服务器npm run serve成功后能看到如下界面。另外vue-cli3提供了图形化配置界面。命令行输入vue ui即可启动。github配置项目初始化后已经有git的初始化配置了,这时候我们只需要把项目和github的远程仓库做连接就可以了。我们首先在github上新建项目,得到项目地址后命令行输入以下命令:git remote add origin git@github.com:Feleti/mweb.git因为我配置了ssh key所以地址以git开头,如果未配置的使用https开到的地址。git的使用之后我会单独出一篇文章讲解,这里就不详述了。上传代码到远程分支:git push –set-upstream origin master首次上传新分支输入以上命令,不是的话只要输入git push就可以了。上传成功后可以在github上看到了。小结今天的内容有点少,本来计划把项目前期配置的内容都放在这篇,可无奈啊,小肆今天回家晚啦,又有点别的事耽误了,现在快12点了,小肆再不发文今天就发不了了,那就之后再讲吧,记得关注小肆公众号”技术放肆聊“,跟进本课程,会让你学到你想学的。

January 15, 2019 · 1 min · jiezi

ONE-sys 整合前后端脚手架 koa2 + pm2 + vue-cli3.0 + element

项目地址https://github.com/fanshyiis/…本脚手架主要致力于前端工程师的快速开发、一键部署等快捷开发框架,主要目的是想让前端工程师在一个阿里云服务器上可以快速开发部署自己的项目。本着前端后端融合统一的逻辑进行一些轮子的整合、并加入了自己的一些脚手架工具,第一次做脚手架的开发,如有问题,请在issue上提出,如果有帮助到您的地方,请不吝赐个star技术栈选择前端整合:vue-cli3.0、axios、element等命令行工具整合:commander、chalk、figlet、shelljs等后端整合:node、 koa2、koa-mysql-session、mysql等服务器整合:nginx、pm2、node等基本功能模块实现聚合分离所谓聚合分离,首先是‘聚合’,聚合代码,聚合插件,做到一个项目就可完成前端端代码的编写,打包上线等功能的聚合。其后是‘分离’。前后端分离。虽然代码会在同一个项目工程中但是前后端互不干扰,分别上线,区别于常规的ejs等服务端渲染的模式,做到前端完全分离一键部署基于本地的命令行工具,可以快速打包view端的静态文件并上传到阿里云服务器,也可快速上传server端的文件到服务器文件夹,配合pm2的监控功能进行代码的热更新,无缝更新接口逻辑快速迭代提供基本的使用案例,包括前端的view层的容器案例与组件案例,组件的api设定以及集合了axios的中间件逻辑,方便用户快速搭建自己的项目,代码清晰,易于分析与修改,server端对mysql连接池进行简单的封装,完成连接后及时释放,对table表格与函数进行分层,代码分层为路由层、控制器层、sql操作层基本模块举例1.登录页面登录 -正确反馈 错误反馈 登录成功后session的设定注册 -重名检测 正确反馈 错误反馈主要模块功能模块增删查改基本功能的实现后台koa2服务模块配合koa-mysql-session进行session的设定储存checkLogin中间件的实现cors跨域白名单的设定middlewer 中间件的设定mysql连接池的封装等等。。。服务端nginx 的基本配置与前端端分离的配置pm2 多实例构建配置文件的配置文件 pm2config.json使用流程本地调试安装mysql (过程请百度)// 进入sql命令行$ mysql -u root -p// 创建名为nodesql的数据库$ create database nodesql安装pm2 (过程请百度)拉取项目代码git clone https://github.com/fanshyiis/ONE-syscd ONE-sys// 安装插件cnpm i 或 npm i 或者 yarn add// 安装linksudo npm link// 然后就能使用命令行工具了one start// 或者不愿意使用命令行的同学可以yarn run serve主要代码解析代码逻辑serverbinone -h启动效果启动项目yarn run v1.3.2$ pm2 restart ./server/index.js && vue-cli-service serveUse –update-env to update environment variables[PM2] Applying action restartProcessId on app [./server/index.js](ids: 0,1)[PM2] index ✓[PM2] one-sys ✓┌──────────┬────┬─────────┬─────────┬───────┬────────┬─────────┬────────┬─────┬───────────┬───────────┬──────────┐│ App name │ id │ version │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ user │ watching │├──────────┼────┼─────────┼─────────┼───────┼────────┼─────────┼────────┼─────┼───────────┼───────────┼──────────┤│ index │ 0 │ 0.1.0 │ fork │ 77439 │ online │ 2640 │ 0s │ 0% │ 15.4 MB │ koala_cpx │ disabled ││ one-sys │ 1 │ 0.1.0 │ cluster │ 77438 │ online │ 15 │ 0s │ 0% │ 20.2 MB │ koala_cpx │ disabled │└──────────┴────┴─────────┴─────────┴───────┴────────┴─────────┴────────┴─────┴───────────┴───────────┴──────────┘ Use pm2 show &lt;id|name&gt; to get more details about an app INFO Starting development server… 98% after emitting CopyPlugin DONE Compiled successfully in 10294ms16:31:55 App running at: - Local: http://localhost:8080/ - Network: http://192.168.7.69:8080/ Note that the development build is not optimized. To create a production build, run yarn build.页面展示线上调试阿里云服务器文件存放目录[root@iZm5e6naugml8q0362d8rfZ ]# cd /home/[root@iZm5e6naugml8q0362d8rfZ home]# lsdist server test[root@iZm5e6naugml8q0362d8rfZ home]#阿里云nginx配置 location ^ /api { proxy_pass http://127.0.0.1:3000; } location ^ /redAlert/ { root /home/dist/; try_files $uri $uri/ /index.html =404; } location ^~ /file/ { alias /home/server/controller/public/; } location / { root /home/dist/; index index.html index.htm; }其他方面如同本地配置有问题可以加群联系最后请star一个吧~~~ ...

January 14, 2019 · 2 min · jiezi

vue-cli3使用svg问题的简单解决办法

此解决办法使用的是 vue-cli 插件 vue-cli-plugin-svg-sprite效果如下:那个朋友圈图标就是我从网上找的svg图片使用方式如下:vue add svg-spritevue.config.js添加配置,在文件内最下方找到pluginOptionsmodule.exports = { pluginOptions: { svgSprite: { /* * The directory containing your SVG files. / dir: ‘src/assets/icons’, / * The reqex that will be used for the Webpack rule. / test: /.(svg)(?.)?$/, /* * @see https://github.com/kisenka/svg-sprite-loader#configuration / loaderOptions: { extract: true, spriteFilename: ‘img/icons.[hash:8].svg’ // or ‘img/icons.svg’ if filenameHashing == false }, / * @see https://github.com/kisenka/svg-sprite-loader#configuration */ pluginOptions: { plainSprite: true } } } };再执行:npm install svgo svgo-loader –save-dev然后再在 your vue.config.js file:module.exports = { chainWebpack: config => { config.module .rule(‘svg-sprite’) .use(‘svgo-loader’) .loader(‘svgo-loader’); }};然后再assets下创建icons文件夹,将你的svg图标放入,name就是svg的名字,如下方式使用:<svg-icon name=“aperture”></svg-icon>这个组件是插件帮你生成的就会看到你的svg图标出来了 ...

January 13, 2019 · 1 min · jiezi

Mock模拟后台接口数据的简单使用

在项目开发的过程中,有时候会出现后端数据还没出来,而前端需要数据的情况。这时候,如果等着后端人员开发完再进行测试,联调则会拖慢开发进度。这时候,Mock就显示出它的魅力。它可以进行生成随机数据,模拟后端接口数据,从而实现开发时,前后端分离,提高效率。在使用Mock之前,应该先和后端人员讨论接口文档的基本结构,确认接口文档的内容。在根据确认好的接口文档,使用Mock模拟数据。最近在vue-cli搭建的项目静态页面已逐渐完善,此时若能有数据模拟渲染,那作为前端新手更能熟悉开发流程。查阅文档和其他小伙伴的文章,开始了模拟数据之旅。Mock的简单使用1、安装npm i mockjs -S2、引入在src文件目录下,新建mock.js文件并引入:const Mock = require(‘mockjs’)之后,在main.js文件中加载mock.jsrequire(./mock.js)3、简单使用格式: Mock.mock(“请求的URL地址”,{“数据对象”})自己的代码:const Mock = require(‘mockjs’);const Random = Mock.Random; // 当需要生成随机数据时使用,更多的随机数据的生成使用参照官网示例// 示例1Mock.mock(“http://localhost:8080/getData”,{ “code”: 1, “msg”: “请求接口成功”, “data”: [ { “id”: 1, “name”: “英语”, “createTime”: “2019-01-01T21:18:02.000+0000”, “updateTime”: “2019-01-01T21:18:07.000+0000”, “ordinal”: 1 }, { “id”: 2, “name”: “趣味”, “createTime”: “2019-01-01T21:18:24.000+0000”, “updateTime”: “2019-01-01T21:18:28.000+0000”, “ordinal”: 2 } ]});// 示例2Mock.mock(“http://localhost:8080/getBanner”,{ “name”:“learn”, “title”: Random.ctitle(), // 随机生成中文标题 “describe”: “learnEnglish”, “imgs”: [ “https://m.360buyimg.com/babel/jfs/t1/29191/26/4235/95551/5c2f2996Eba0b025d/c6a2aa923a67f952.jpg”, “https://img1.360buyimg.com/da/jfs/t1/28807/10/4306/85260/5c30484cE8f828f42/3b36d2a6b80d10eb.jpg”, “https://img10.360buyimg.com/da/jfs/t18487/241/1444742474/110119/f5bc9082/5acb3af6N2af11d1c.jpg”, “https://m.360buyimg.com/babel/jfs/t1/22710/5/3081/75342/5c244f9eE54c2699a/74f8c021c36b6366.jpg” ]});4、进一步使用参照官方文档,在mock.js文件中引入Mock之后,根据数据模板生成模拟数据:Mock.mock( rurl?, rtype?, template|function( options ))rurl:可选。表示需要拦截的 URL,可以是 URL 字符串或 URL 正则,如/index.js => /^/index.js$/ rtype:可选。表示需要拦截的 Ajax 请求类型。例如 GET、POST、PUT、DELETE 等。 template:可选。表示数据模板,可以是对象或字符串。例如 { ‘id|1-10’:[{}] }。 function(options):可选。表示用于生成响应数据的函数。options 指向本次请求的 Ajax 选项集,含有 url、type 和 body 三个属性。① 记录数据模板。当拦截到匹配 url 的 Ajax 请求时,将根据数据模板 template 生成模拟数据,并作为响应数据返回。第三点的简单使用采用的就是这种形式。Mock.mock( rurl, template )② 记录用于生成响应数据的函数。当拦截到匹配 rurl 的 Ajax 请求时,函数 function(options) 将被执行,并把执行结果作为响应数据返回。Mock.mock( rurl, function( options ) )Mock.mock(“http://localhost:8080/getNewslist”, function(options){ return options.type});③ 记录数据模板。当拦截到匹配 rurl 和 rtype 的 Ajax 请求时,将根据数据模板 template 生成模拟数据,并作为响应数据返回。Mock.mock( rurl, rtype, template )Mock.mock(“http://localhost:8080/geNewsinfo”, “get”, { “code”: 1, “msg”: “请求接口成功”, “data”: [ { “id”: 1, “name”: “英语”, “createTime”: “2019-01-01T21:18:02.000+0000”, “updateTime”: “2019-01-01T21:18:07.000+0000”, “ordinal”: 1 } ]});④ 记录用于生成响应数据的函数。当拦截到匹配 rurl 和 rtype 的 Ajax 请求时,函数 function(options) 将被执行,并把执行结果作为响应数据返回。Mock.mock( rurl, rtype, function( options ) )Mock.mock(“http://localhost:8080/getImage”, “get”, function(options){ return options.type}); ...

January 12, 2019 · 1 min · jiezi

vue-router和webpack懒加载,页面性能优化篇

在vue单页应用中,当项目不断完善丰富时,即使使用webpack打包,文件依然是非常大的,影响页面的加载。如果我们能把不同路由对应的组件分割成不同的代码块,当路由被访问时才加载对应的组件(也就是按需加载),这样就更加高效了。——引自vue-router官方文档如何实现??vue异步组件vue-router配置路由,使用vue的异步组件技术,可以实现懒加载,代码如下:// 每个组件都会生成一个js文件import Vue from ‘vue’import Router from ‘vue-router’import Login from ‘../view/List.vue’;Vue.use(Router);export default new Router({routes: [ { path: ‘/home/list’, name: ’list’, components: resolve => require([’../view/List.vue’], resolve) }],动态import(webpack > 2.4)vue、webpack官方推荐情况一:每个组件都会打包生成一个js文件const List = () => import(’../view/List.vue’)// 在路由配置中什么都不需要改变,像往常一样使用组件:export default new Router({routes: [ { path: ‘/home/list’, name: ’login’, components: Login }, { path: ‘/home/user’, name: ‘user’, components: User }],情况二:所有组件合并打包在一个异步块chunk中const List = () => import(/* webpackChunkName: “home” / ‘./List.vue’)const User = () => import(/ webpackChunkName: “home” / ‘./User.vue’)// 在路由配置中什么都不需要改变,像往常一样使用组件:export default new Router({routes: [ { path: ‘/home/list’, name: ’list’, components: List }, { path: ‘/home/user’, name: ‘user’, components: User }],// 在webpack.base.config.js中配置 ChunkFileName:output: {path: config.build.assetsRoot,filename: ‘[name].js’,chunkFilename: ‘[name].js’,publicPath: process.env.NODE_ENV === ‘production’ ? config.build.assetsPublicPath : config.dev.assetsPublicPath},另一种写法,更简洁:同样需要在webpack.base.config.js中配置 ChunkFileName:{ path: ‘/home/list’, name: ’list’, component: () => import(/ webpackChunkName:“list”/ ‘../view/List.vue’)},{ path: ‘/home/user’, name: ‘user’, component: () => import(/ webpackChunkName:“user”*/ ‘../view/User.vue’)},webpack提供的require.ensure()语法如下:摘自官网require.ensure(dependencies: String[], callback: function(require), chunkName: String多个路由指定相同的chunkName,在这里chunkName为home,会合并打包成一个js文件。{ path: ‘/home/list’, name: ’list’, // component:list component: r => require.ensure([], () => r(require(’../view/Lst.vue’)), ‘home’)},{ path: ‘/home/user’, name: ‘user’, // component:user component: r => require.ensure([], () => r(require(’../view/User.vue’)), ‘home’)}// 在webpack.base.config.js中配置 ChunkFileName 和 publicPath:output: {path: config.build.assetsRoot,filename: ‘[name].js’,chunkFilename: ‘[name].js’,publicPath: ‘./’,publicPath: process.env.NODE_ENV === ‘production’ ? config.build.assetsPublicPath : config.dev.assetsPublicPath},在实践过程中应该会遇到各种问题,到时候再继续补充,前端新手,多多指教! ...

January 5, 2019 · 1 min · jiezi

组件调用错误,路径问题

使用vue-cli构建项目,在项目进行的过程中,某个详情页调用组件报错,在别的页面中同样调用过该组件,但是没有报错。错误信息如下:This dependency was not found:* play.vue in ./node_modules/babel-loader/lib!./node_modules/vue-loader/lib/selector.js?type=script&index=0!./src/components/detail/detail.vueTo install it, you can run: npm install –save play.vue引用组件代码:<script> import play from ‘play.vue’; import foot_contact from ‘../home/foot_contact.vue’; export default { name: “detail”, components: { play, foot_contact, }, data() { return { activeIndex: ‘1’, activeIndex2: ‘1’ } }, methods: { handleSelect(key, keyPath) { console.log(key, keyPath); } } }</script>经查证,是路径问题。因为子组件与父组件在同一个目录下,所以引入子组件时,我直接使用了组件的文件名(play.vue)。这使得vue在编译时,把它当做node_modules下的模块,因此要求你安装。在项目中引用组件是需要写相对路径的,即使是在同一目录下。在我的项目中,需要改正的也就是’./play.vue’。在信息时代,知识的分享使得问题的解决比以前容易很多,只有不断总结与前进,你才能与时俱进。感谢网友们的分享:https://segmentfault.com/q/10…

January 3, 2019 · 1 min · jiezi

@Vue/Cli 3 Invalid Host header 错误解决办法

我的host设置报错如下:解决办法:@Vue/Cli 3 在vue.config.js里加上.disableHostCheck(true)vue-cli 在webpack.dev.conf.js里加上devServer: { disableHostCheck: true}最后

January 2, 2019 · 1 min · jiezi

最详细的Vue Hello World应用开发步骤

很多Vue的初学者想尝试这个框架时,都被webpack过于复杂的配置所吓倒,导致最后无法跑出一个期望的hello word效果。今天我就把我第一次使用webpack打包一个Vue Hello World应用的所有步骤详细记录下来,供Vue的初学者参考。安装nodejs和npm,这两个就不用说了,网上很多教程。本地随便新建一个文件夹,进入后运行命令npm init, 一路next下去,自动生成package.json。运行命令npm install –save-dev webpack-dev-server,安装一个轻量级的服务器,该服务器用于vue应用开发完毕后的本地测试。重复执行命令npm install –save-dev <name>,也就是把下列命令粘贴到cmd里进行执行:npm install –save-dev css-loadernpm install –save-dev vue-template-compilernpm install –save-dev webpacknpm install –save-dev vue-loadernpm install –save-devvue-router参数-save-dev的效果是让这些安装的module出现在package.json的devDependencies区域内,如下图红色区域所示:这些都是开发时依赖。我们再用下列命令安装运行时依赖:npm install –save vue vuex然后再在package.json里手动加入如下这一段内容:目的是开发完毕后,使用命令npm run dev可以启动webpack-dev-server,运行我们的vue应用,并带上参数–inline –hot。在项目文件夹根目录下创建一个名为src的文件夹,文件夹里新建一个文件index.vue,把如下内容拷贝进去:<style>h2{color: red;}</style><template><h2>Jerry: Hello, World!</h2></template><script>module.exports = {data: function(){return {};}}</script>再回到根目录下,新建一个文件main.js:import Vue from ‘vue’;import AppJerry from ‘./src/index.vue’new Vue({el: “#demo”,components: {app: AppJerry}});这段代码首先将我们在src文件夹的index.vue里实现的应用导出,存储到变量AppJerry里,再将这个应用安装到html页面id为demo的div标签里。安装是通过创建Vue实例并将div元素的id传入构造函数里进行的。当然,我们还没创建html文件,所以马上创建一个名为index.html的文件:<!DOCTYPE html><html lang=“en”><head><meta charset=“UTF-8”><title>hello world</title></head><body><div id=“demo”><app></app></div><script src=“dist/build.js”></script></body></html>我们注意到这个index.html里引用了一个dist/build.js的文件,这个文件用来干嘛的?这里就不得不提webpack在现代前端开发技术中起的重要作用了。WebPack可以看做是模块打包机:它做的事情是,分析我们的前端项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言,比如Scss,TypeScript等,并将其打包为合适的格式以供浏览器使用。具体到我们这个例子,就是说webpack把我们src文件夹下的index.vue打包转换成浏览器能识别的js文件,webpack的输出就是dist文件夹下的build.js文件。为了让webpack清楚地知道它要完成什么样的任务,我们通过创建一个配置文件webpack.config.js来完成webpack任务指定。这个配置文件的内容:var path = require(‘path’);module.exports = {entry: ‘./main.js’,output: {path: path.resolve(__dirname, ‘./dist’),publicPath: ‘/dist/’,filename: ‘build.js’},resolve: {alias: {‘vue$’: ‘vue/dist/vue.esm.js’}},module: {loaders: [{test: /.vue$/,loader: ‘vue-loader’},{test: /.(png|jpg|eot|svg|ttf|woff)/,loader: ‘url?limit=40000’}]}}里面定义了webpack执行任务的入口是main.js文件,任务输出的文件夹是项目文件夹里的dist目录,输出文件是build.js, webpack扫描的文件通过vue-loader指定,特征是以.vue结尾的文件。到目前为止,这个基于Vue的hello world应用的开发和配置都结束了,是不是很简单?我们可以来测试了。直接在命令行里敲webpack命令,就会自动执行打包操作,并在控制台上看到build.js文件成功生成的消息:这个打包后的文件尺寸很大,有323KB,包含了vue.js本身的内容和我们index.vue里的转换后的内容。下图高亮区域就是我们index.vue里的实现被webpack处理后生成对应的JavaScript代码。使用npm run dev启动webpack-dev-server,看到提示说在localhost:8080上可以访问我们的应用了。浏览器里访问,看到Hello World的输出,说明我们成功地走完了一个基于webpack的Vue应用开发流程。要获取更多Jerry的原创文章,请关注公众号"汪子熙":uto-orient/strip%7CimageView2/2/w/1240) ...

January 1, 2019 · 1 min · jiezi

vue-cli引用mui的JS文件遇到的问题

因项目的需要,采用了MUI的滚动事件(scroll),遇到了不少的问题,做个记录,方便以后查询。问题一:引入MUI顶部滑动样式后,顶部滑动条全屏显示<div id=“slider” class=“mui-slider mui-fullscreen”> <div id=“sliderSegmentedControl” class=“mui-scroll-wrapper mui-slider-indicator mui-segmented-control mui-segmented-control-inverted”> <div class=“mui-scroll”> <a class=“mui-control-item mui-active” href="#item1mobile" data-wid=“tab-top-subpage-1.html”> 全部 </a> <a class=“mui-control-item” href="#item2mobile" data-wid=“tab-top-subpage-2.html”> 家居生活 </a> <a class=“mui-control-item” href="#item3mobile" data-wid=“tab-top-subpage-3.html”> 北京 </a> <a class=“mui-control-item” href="#item4mobile" data-wid=“tab-top-subpage-4.html”> 社会 </a> <a class=“mui-control-item” href="#item5mobile" data-wid=“tab-top-subpage-5.html”> 娱乐 </a> </div> </div></div>解决方案:查看官方文档,文档说明:区域滚动组件默认为absolute定位,全屏显示。所以你需要手动删掉全屏这个类,即 mui-fullscreen问题二:没有滚动效果解决方案:根据官方文档:若使用区域滚动组件,需手动初始化scroll控件,因此,在需要用到该滚动效果的组件中,引入mui.js文件,并初始化import mui from ‘../../lib/mui/js/mui.js’; // 建了lib文件夹,存放mui相关文件mui(’.mui-scroll-wrapper’).scroll({deceleration: 0.0005 //flick 减速系数,系数越大,滚动速度越慢,滚动距离越小,默认值0.0006});问题三:初始化之后报错控制台错误消息为:caller’, ‘callee’, and ‘arguments’ properties may not be accessed on strict mode functions or the arguments objects for calls to them。原因:webpack启用了严格模式,而MUI没有,所以两者冲突了。 解决方案:在.babelrc文件中加上:“ignore”: ["./src/lib/mui/js/.js" // 建了lib文件夹,存放mui相关文件]另一种解决方法:该方法试过,出现另一种报错:export ‘default’ (imported as ‘mui’) was not found in ‘../../lib/mui/js/mui.js’。不知道是不是因人而异呢==,有朋友成功了而我的不行23331. 安装babel-plugin-transform-remove-strict-modecnpm i babel-plugin-transform-remove-strict-mode -D2. 在.babelrc文件的plugins节点中配置:“transform-remove-strict-mode"问题四:终于可以滑动了,点击滑动报错:控制台错误消息为:Unable to preventDefault inside passive event listener due to target being treated as passive. See https://www.chromestatus.com/features/5093566007214080解决方法: {touch-action: pan-y;}2016年Google I/O上提出的概念,目的是用来提升页面滑动的流畅度。问题五:顶部可以滑动之后,底部Tab不能切换控制台错误消息为:Unable to preventDefault inside passive event listener due to target being treated as passive. See https://www.chromestatus.com/features/5093566007214080原因: Tab样式(也是MUI的)与MUI的JS文件冲突,具体什么冲突不清楚,有兴趣可以看源码,我还晕乎乎的 解决方法: 找到Tab栏mui-tab-item的所有样式,复制一份,重新赋予新的样式类名,如mui-tab-item-my问题六:刚进入页面无法滑动,要刷新之后方可滑动原因:滑动时机不对,如前面代码显示的那样,在导入mui后就初始化滑动控件,此时,当重新进入页面时,组件的DOM结构还未渲染好,就初始化,自然不会有效果。 解决方法:放到mounted钩子函数中,在这个生命周期函数中,DOM结构已被渲染好,可以初始化滑动控件mounted(){ // 初始化滑动控件 mui(’.mui-scroll-wrapper’).scroll({ deceleration: 0.0005 //flick 减速系数,系数越大,滚动速度越慢,滚动距离越小,默认值0.0006 });} ...

December 29, 2018 · 1 min · jiezi

vue引入阿里图标库(iconfont)单色和彩色图标

使用组件库时,图标往往不能满足需求,所以我们常常需要用到第三方图标库。阿里图标库是我们的常客。有两种形式,一是单色,二是彩色的。单色图标的引用1、在iconfont官网选图标,加入购物车,加入项目,下载到本地,解压2、在项目src目录新建目录font,用于存放刚才下载解压的代码3、在main.js导入iconfont.css文件import ‘./font/iconfont/iconfont.css'4、在代码中使用class=“iconfont icon-XXX"就可以使用图标了这是直接引用,而像Element-UI则是将其与自己的图标进行了融合。Element-UI引入第三方图标库:在iconfont官网选图标,加入购物车,加入项目编辑项目,修改FontClass/Symbol 前缀为:el-icon-xx (xx为自己定义的类名,注意不要与Element自身的图标类名重合)将图标项目下载至本地,解压在项目src目录新建目录font,用于存放刚才下载解压的代码打开iconfont.css文件,将以下代码加进去:[class^=“el-icon-my”],[class*=” el-icon-my"]/这里有空格/*{ font-family: “iconfont” !important; font-size: 16px; font-style: normal; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;}在main.js导入iconfont.css文件 import ‘./font/iconfont/iconfont.css’打开在阿里icon的项目,复制你想要的图标代码使用方式与Element-UI自带的图标一样彩色图标1、在iconfont官网选图标,加入购物车,加入项目,注意选择Symbol,再下载到本地2、在项目src目录新建目录font,用于存放刚才下载解压的代码,或者只拷贝其 iconfont.js文件3、在main.js导入iconfont.js文件4、写入图标代码<svg class=“icon” aria-hidden=“true”> <use xlink:href="#icon-lianxi"></use></svg>注意: 在这里要用#加class名5、写入svg图标通用样式.icon {width: 1em; height: 1em;vertical-align: -0.15em;fill: currentColor;overflow: hidden;}补充:aria-hidden 的意思 图标的可访问性 现代的辅助技术能够识别并朗读由 CSS 生成的内容和特定的 Unicode 字符。为了避免屏幕识读设备抓取非故意的和可能产生混淆的输出内容(尤其是当图标纯粹作为装饰用途时),我们为这些图标设置了 aria-hidden=“true” 属性。感谢大神的分享:https://www.cnblogs.com/golov…https://www.jianshu.com/p/59d…

December 28, 2018 · 1 min · jiezi

vue cli 3.x 的坑之 px2rem-loader

使用 vue cli 3.x脚手架搭建项目,在 vue.config.js 里面配置 px2rem-loader 后,一直报错Module build failed (from ./node_modules/px2rem-loader/index.js):Error: undefined:1:40: missing ‘{‘在 px2rem-loader 的 issues 有相同的问题,作者回复建议使用 postcss 插件来代替这个 loaderhttps://github.com/Jinjiang/p…module.exports = { css: { loaderOptions: { postcss: { plugins: [require(‘postcss-px2rem’)({ remUnit: 75 })] } } }}

December 21, 2018 · 1 min · jiezi