为 electron 项目新建一个目录,并初始化 npm

例如新建文件目录为 testDesktopApp,再初始化 npm

npm init
# 一路回车即可

修改 package.json 文件,将 name 修改为最终桌面可执行程序的名称,将 main 中的 index.js 修改为 main.js 防止与要打包项目的 js 文件冲突,并在 script 中添加 start 命令。

{
  "name": "testdesktopapp",
  "version": "1.0.0",
  "description": "",
  "main": "main.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "electron ."
  },
  "author": "",
  "license": "ISC"
}
Read more »

前置环境 nodeJS v10.16.0,node 版本最好不要低于 v8.0.0

安装 cordova

npm install -g cordova
# 若安装过慢,请使用淘宝镜像
npm install -g cordova --registry=https://registry.npm.taobao.org

创建新的 cordova 项目

# testApp为目录名path
# test.example.com为项目id
# testApp为项目名name
cordova create testApp test.example.com testApp

image.png

发送使用信息选 No

Read more »

我们在 vue 的使用过程中常常会遇到这样的问题,想要在局部的 vue 文件中修改一个组件中的全局样式,且不影响全局,只在当前的 vue 文件中生效。我们直觉上就是通过 style 标签上 scoped 属性来实现局部生效,不影响全局。但是事实上这样做并没有效果,局部的样式并没有生效,这是为什么呢?

让我们用一个例子来说明问题,假设我们在当前组件 A 中使用的另一个组件 B,组件 B 中使用了一个全局的样式:字为红色。我们想让 B 组件在 A 组件中使用时字为蓝色,而在其他地方使用时字依然是红色。我们在 A 组件中给 style 标签设置了 scoped 属性,然后设置.foo 的类为蓝色,结果并未生效。

Read more »

问题描述

属性为display: inline-block的元素之间,换行显示或用空格分隔的情况下会产生间距。

<ul>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
</ul>
ul li {
  display: inline-block;
}

这种间距会影响到我们布局,如何去除这种间距?

经典解决方案

使用html解决,将inline-block元素写在一行里,或让标签首尾不换行

<!-- 将inline-block元素写在一行 -->
<ul>
  <li></li><li></li><li></li><li></li>
</ul>
<!-- 标签首尾不换行 -->
<ul>
  <li></li><li></li><li></li><li></li>
</ul>

缺点:影响代码美观与格式化

使用css解决,设置父元素font-size为0,或设置子元素margin或letter-spacing或word-spacing属性为负值

/* 设置font-size */
ul {
  font-size: 0;
}
ul li {
  font-size: 14px;
}
/* 设置margin或letter-spacing或word-spacing */
ul li {
  margin: -1;
}
ul li {
  letter-spacing: -1;
}
ul li {
  word-spacing: -1;
}

缺点:跨浏览器兼容不好

终级解决方案

在父元素上使用display: flex

ul {
  display: flex;
}
ul li {
  display: inline-block;
}

让图片适应外层div大小

在我们展示网络资源图片时通常会遇到在一个固定的宽度内展示不同大小的图片,如果我们让图片撑满100%去适应外层div的大小,那么大于div尺寸的图片将按外层div大小展示,而小于外层div尺寸的图片则会被拉伸至外层div的尺寸,两个尺寸相差悬殊的话,小图会被拉伸地很模糊。

我们通过限定内层图片的最大宽度为外层div的宽度来使大于外层div尺寸的图片适配,而我们不去限定内层图片的宽度以使小于外层div尺寸的图片不被拉伸,直接展示。

<div class="img-container">
  <img src="www.test.com/test.png" />
</div>

<style>
.img-container {
  /* 图片不要限定高,否则图片无法按照原有比例展示,会变形 */
  width: 650px; /* 若是外层还有div且宽度固定,则可以使用100% */
}
.img-container img {
  /* 图片不要限定高,否则图片无法按照原有比例展示,会变形 */
  max-width: 650px; /* 也可以使用100% */
}
</style>

node配置服务器跨域使pdfjs加载非同源文件

pdfjs因为同源策略,只能加载本地的pdf,想要加载远程的pdf就会报跨域的错,查看官方文档后发现pdfjs本身并不阻止加载远程pdf文件,只要文件服务器配置好跨域即可。

这里使用了node中的express框架搭建了一个简单的静态文件服务器。

// pdfjs官网issue提供的跨域配置方案
// {
//   "Access-Control-Allow-Origin": "*",
//   "Access-Control-Allow-Headers": "range",
//   "Access-Control-Expose-Headers": "content-range, content-length, accept-ranges",
//   "Access-Control-Allow-Methods": "*"
// }
// 引入express
const express = require("express");
const app = express();

// 根据官方文档中的issue配置跨域
app.all("*", function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "range");
  res.header(
    "Access-Control-Expose-Headers",
    "content-range, content-length, accept-ranges"
  );
  res.header("Access-Control-Allow-Methods", "*");
  next();
});

// 配置静态文件目录
app.use(express.static("public"));

// 监听服务器的某个端口
const server = app.listen(8082, function() {
  console.log("server-start");
});

配置好跨域后,你会发现还是报跨域的错,在pdfjs源码中查找file origin does not match viewer,就会发现源码中只要不是同源就会抛出异常,注释掉原码中的throw error即可。

if (origin !== viewerOrigin && protocol !== 'blob:') {
  // throw new Error('file origin does not match viewer\'s');
}

使用全局的 window 对象

文件下载一般直接访问文件的静态服务器地址即可,故可以使用 window.location.href 与 window.open 来实现下载,这种方法可能会受到浏览禁止弹窗的影响

window.location.href = "www.test.com/download/test.pdf";
// 或者使用window.open()
window.open("www.test.com/download/test.pdf");

使用 a 标签与链接地址

这种方式兼容性最好,一般应该使用这种方式

// 创建a标签
const ele = document.createElement("a");
// 设置download属性使浏览器能打开的文件不再默认打开而是下载,也可以设置下载文件名
ele.download = "export";
// 设置a标签链接,可以使用queryString传参
ele.href = "www.test.com/download/test.excel?id=1&name=2";
// 模拟鼠标点击a标签
ele.click();

使用 ajax 与 a 标签

这种方式不兼容 IE,因为 IE 对 blob 等支持不全。需要注意的是,请求时还要设置 responseType 为 blob,否则接收二进制流时会遇到乱码问题。

// 请求下载接口
axios({
  url: "www.test.com/download/",
  method: "post",
  data: {
    id: 0,
    name: 1,
  },
  responseType: "blob",
})
  .then((res) => {
    // 获取文件数据后,创建a标签
    const ele = document.createElement("a");
    // 设置download属性
    ele.download = "export";
    // 使用blob接收文件,注意要设置type,否则文件为乱码,data应该放在数组中(arrayBuffer)
    // 2003版 后缀为xls的文件type值为application/vnd.ms-excel
    // 2007版 后缀为xlsx的文件type值为application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
    const blob = new Blob([res.data], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
    // 使用blob创建访问链接
    ele.href = URL.createObjectURL(blob);
    // 模拟鼠标点击
    ele.click();
    // 释放访问链接
    URL.revokeObjectURL(ele.href);
  })
  .catch((err) => console.error(err));

如何在打生产环境包时去除console信息

方法一、修改node_modules中的@vue包下关于terserOptions的配置

配置路径为node_modules/@vue/cli-service/lib/config/terserOptions.js

在compress对象中加上 drop_console: true 即可在打生产环境包时去除所有的 console。若不想删除所有的console信息,只是想删除console.log,则配置compress对象中的 pure_funcs 字段为 [“console.log”]。

方法二、在vue.config.js中直接修改webpack配置

既然核心方法是在webpack打包时利用terser插件实现去除console的效果,那么直接在vue.config.js中配置webpack即可

// 引入terser插件
const TerserPlugin = require("terser-webpack-plugin");
// 使用configureWebpack字段配置webpack
module.exports = {
  // 下面两种配置方式选一即可
  // 一、配置式
  configureWebpack: {
    optimization: {
      minimizer: [
        new TerserPlugin({
          terserOptions: {
            compress: {
              pure_funcs: ["console.log"]
            }
          }
        })
      ]
    }
  },
  // 二、链式操作
  chainWebpack: config => {
    config.optimization.minimizer([new TerserPlugin({
      terserOptions: {
        compress: {
          pure_funcs: ["console.log"]
        }
      }
    })])
  }
};

如何获取浏览器类型

在javascript中我们经常需要通过浏览器类型的不同使用不同的兼容逻辑,那么如何获取浏览器类型呢?我们可以使用navigator.userAgent,再通过字符串的indexOf方法去判断里面有没有诸如”AppleWebKit”等字符串来判定浏览器类型。

如何获取伪元素的CSS属性

伪元素是例如::after,::before等形式的css生成的元素。javascript中没有直接获取伪元素的选择器,但是有获取伪元素属性的方法。

window.getComputedStyle()

我们可以使用window.getComputedStyle()方法获取伪元素,再使用getPropertyValue()方法获取属性值。

语法:window.getComputedStyle(element[, pseudoElement])

element为伪元素所在的元素,pseudoElement为伪元素自身。

// 假如我们要获取的是class为test的::after伪元素,并获取到它的content值
const element = document.querySelector(".test");
const afterStyle = window.getComputedStyle(element, "::after")
const afterContent = afterStyle.getPropertyValue("content");

如果想要修改伪元素的属性怎么办呢?可以直接在取到的属性上赋值吗?答案是否定的,因为这里的style是计算出来的(看方法名就知道),所以是只读的,无法修改。我们并没有办法直接修改到伪元素的属性,只能通过获取styleSheet,再使用addRules(兼容IE)和insertRules(现代浏览器)方法来新增覆盖掉原来的伪元素样式。或者利用DOM原素的data-属性来修改。或者通过改变class类来改变伪元素。

// 修改styleSheet
document.styleSheets[0].addRule('.test::after','content: hellow'); // 支持IE
document.styleSheets[0].insertRule('.test::after { content: hellow }', 0); // 支持非IE的现代浏览器
<!-- CSS代码 -->
<style>
.test::after {
  content: attr(data-attr);
}
</style>

<!-- HTML代码 -->
<div class="test" data-attr="hellow"></div>

<!-- JacaScript代码 -->
<script>
const element = document.querySelector(".test");
element.setAttribute("data-attr", "hellow");
</script>
0%