google play 安装

前置条件:科学上网

1. 在apkmirror网站上下载 Google Play Service 与 Google Play Store 安装包

2. 安装成功后在科学上网的环境下使用

故障排除

  1. 安装完成后,无法登陆(确保已科学上网)。报错信息为Couldn’t sign in, There was a problem communicating with Google servers. Try again later.

  2. 已登陆但报错:从服务器检索信息时出错。DF-DFERH-01。

  3. 明明已科学上网且登陆成功,但经常无法访问Google 服务。

这些问题都是同一个原因引起的:国产手机系统默认将Google Play Service的请求地址更改为googleapis.cn,而google并未在大陆提供服务,故无法使用,默认状态下,需要很久才能判定googleapis.cn响应超时,转而去请求googleapis.com。可通过root权限修改手机host文件,将谷歌服务框架的请求修改为googleapis.com,或在科学上网工具中加入一条规则,使googleapis.cn重定向到googleapis.com来解决问题。也可以通过请求googleapis.cn时断开网络再重新连接,使对googleapis.cn的请求直接判定为失败,从而直接重定向到googleapis.com上。

上面的办法都是些治标不治本的法子,建议买外国手机。。。

前端通常使用逻辑运算符作为条件判断语句的条件,只关心返回值是 truthy 还是 falsy。但非常容易忽略逻辑运算符可以被应用于任意类型值,多个任意类型值的逻辑运算返回值到底是什么。

下面所有代码示例中的返回值均指运算返回值,而不是 console.log 函数返回值

||(或)

一个||(或)运算链将返回从左向右第一个真值,如果不存在真值,则返回运算链的最后一个值,例如:

console.log(1 || 0); // 返回值为1(第一个真值)
console.log(true || 'no matter what'); // 返回值为true(第一个真值)
console.log(null || 0 || 1); // 返回值为1(第一个真值)
console.log(null || 0 || undefined); // 返回值为undefined(运算链最后一个值)

&&(与)

一个&&(与)运算链将返回从左向右第一个假值,如果不存在假值,则返回运算链的最后一个值,例如:

console.log(1 && 0); // 返回值为0(第一个假值)
console.log(true && 'no matter what'); // 返回值为'no matter what'(运算链最后一个值)
console.log(1 && 2 && null && 3); // 返回值为null(第一个假值)
console.log(1 && 2 && 3); // 返回值为3(运算链最后一个值)

!(非)

!(非)运算符将操作数转化为布尔类型,并返回相反的值,两个非运算!!用来将某个值转化为布尔类型,也可以使用内置的 Boolean 函数来转换为布尔类型。非运算符在所有逻辑运算符中优先级最高,它总在&&||前执行

console.log(!null); // 返回值为true
console.log(!!null); // 返回值为false
console.log(Boolean(null)); // 返回值为false

ORM

ORM是Object-Relational-Mapping的缩写。即通过面向对象的语法,完成关系型数据库的操作,这样的对象-关系映射模型就是ORM。通常ORM是作为MVC架构中的Model层。

ORM使用对象封装了数据库操作,不用书写SQL语言。开发者只要面向对象编程,通过数据对象交互,不用关心底层数据库。

ORM优点:

  • 数据模型在一个地方定义,易于更新与维护。

  • ORM有现成的工具,很多功能可以自动完成,如数据预处理、事务等。

  • 迫使你使用MVC架构,ORM是天然的Model。

  • 基于ORM的业务代码简单,代码量少,语义性好,易理解。

  • 不必编写性能不佳的SQL语句。

ORM缺点:

  • ORM库通常都不是轻量级工具,是有一定学习曲线的。

  • 对于复杂查询,ORM要么无法表达,要么性能不如原生SQL。

  • ORM抽象了数据库层,开发者无法了解底层的数据库操作,也无法定制一些特殊SQL。

ODM

ORM对应的是关系型数据库,如MySQL,那么ODM就对应的是文档型数据库,如MongoDB。ODM是Object-Document-Mapping缩写,即对象文档映射。MongoDB对应Node的ODM库是Mongoose。

复杂的软件一定要有架构设计,好的架构模式使得软件更易于维护与扩展。架构模式(architectural pattern),属于编程方法论。

MVC 模式

MVC 是 View-Model-Controller 的缩写,该架构模式是指将软件系统分为三个基本部分:

  • 模型(Model):用于封装与应用程序业务逻辑相关的数据以及对数据的处理方法。Model 有对数据直接访问的权力,例如对数据库的访问。Model 不依赖 View 和 Controller,也就是说 Model 不关心它会被如何显示或如何被操作。但是 Model 中数据的变化一般会通过一种刷新机制被公布。为了实现这种机制,那些用于监视此 Model 的 View 必须事先在此 Model 上注册,从而使 View 可以了解在数据 Model 上发生的改变。(如:软件设计模式中的观察者模式)

  • 视图(View):能够实现数据有目的地显示。在 View 中一般没有程序上的逻辑。为了实现 View 上的刷新功能,View 需要访问它监视的数据模型(Model),因此应该事先在被它监视的数据那时注册。

  • 控制器(Controller):起到不同层面间的组织作用,用于控制应用程序的流程。它处理事件并作出响应。“事件”包括用户的行为和数据 Model 上的改变。

Read more »

URI

统一资源标识符(Uniform Resource Identifier),是用于唯一标识某一互联网资源的字符串。

URL

统一资源定位符(Uniform Resource Locator),URL 是 URI 以定位方式的一种实现。

统一资源定位符的完整格式如下:
[协议类型]://[访问资源需要的凭证信息]@[服务器地址]:[端口号]/[资源层级 UNIX 文件路径][文件名]?[查询]#[片段 ID]

其中[访问凭证信息]、[端口号]、[查询]、[片段 ID]都属于选填项。

例如:http://www.example.com/index.html

URN

统一资源命名符(Uniform Resource Name),URN 是 URI 以命名方式的一种实现。

在旧的规范中,URN 相当于 URI,是一种规范性的定义。在新的规范中,URN 作为规范性定义的功能已被 URI 取代,URN 和 URL 则成为了 URI 的一种实现,特定情况下 URI 可能同时拥有 URN 与 URL。

URN 的格式:urn:<NID>:<NSS>,NID 为命名空间,NSS 为唯一名称

例如:urn:issn:0167-6423

写在前面:在前后端分离的理念越来越普及的今天,作为一个前端开发,除了前端技术水平要过硬外,最需要花时间学习的莫过于 HTTP 协议。因为前后端分离后,基于 HTTP 协议的 ajax 请求是前后端交互的桥梁,对 HTTP 协议了解的缺失将造成前后端交互与协作的极大麻烦。这一点对初学者尤为重要,在学好 HTML、CSS、JavaScript 与一个现代框架的基础上,一定要花一定的时间学习 HTTP 协议。

简介

HTTP(Hyper Text Transfer Protocol)即超文本传输协议。

  • 它是一种 client-server 协议,通常是由浏览器这样的接受方发起,旨在获得文本、图片、视频、布局描述、脚本等 Web 文档。

  • HTTP 协议是一种可扩展协议,在网络模型中是基于 TCP 的应用层协议。

Read more »

浏览器进程与线程

一些基本概念:

  • 进程是系统资源分配的最小单位

  • 进程之间相互独立

  • 线程是系统资源调度的最小单位

  • 一个进程由一个或多个线程组成

  • 多个线程在进程中协作完成任务

  • 同一进程下的各个线程之间共享程序的内存空间(包括代码段、数据集、堆栈等)

浏览器是多进程的,例如,每打开一个 Tab 页,就相当于创建了一个独立的浏览器进程

Read more »

管理启动项

若是通过正常的安装程序安装的软件并且可以设置为开机启动的,可以在 windows10 的设置——应用——启动中找到并设置开关。

新增启动项

若是在设置中无法设置开机启动的,则可以将应用程序的快捷方式放在启动文件夹下,启动文件夹路径为 C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp,即可将该应用程序设置为开机启动。

注意:系统语言为中文时,启动文件夹路径不变,但可能显示为中文名称。

使用到的库

vuedraggable——基于SortableJS的vue库,表单设计器拖拽设计功能的核心。

iview——核心UI框架,大部分组件都基于iview组件库

开发思考

  1. 字段写活后,代码书写逻辑中并不知晓代码运行时传入的字段,只能通过增加额外的固定的字段来告知书写逻辑运行时传入的活字段是什么。

  2. 异步问题。所有的后端数据都要通过异步的ajax请求获取,当有同步需求时,使用async和await。值得注意的是await只能在async内部使用,即async函数只能return出一个promise而无法将await的值return出来。

  3. 在Array.prototype.map方法中使用async函数做为回调,想要等待所有promise返回值后再进行下一步的操作,应使用promise.all方法。也可以尝试promise的一个库——bluebird,这个库中有异步处理map等数组遍历的方法。

  4. vue生命周期相关。mounted与updated钩子函数不会承诺所有子组件也被挂载,若要等视图渲染完成后执行某代码逻辑,应将该逻辑放在mounted或updated中的vm.$nextTick回调中。

  5. computed计算属性set的妙用。通常如果后端数据库中保存的值与前端表单中要双向绑定的值不同时,我们会在异步获取数据时将后端值转为前端值,在提交逻辑中再将前端值转为后端值。这种情况下,前后端值不一致的区间是从获取开始直到提交给后端结束,这样的代码逻辑在写业务时确实没有问题,但是在字段写活的情况下,获取数据与提交表单的逻辑中并不知道哪些字段前端所需要值与后端值不一致需要处理,而唯一知道当前字段是谁,是否需要做处理的地方只有表单双向绑定的地方,因此允许前后端值不一致的地方仅剩表单中双向绑定时的一个时间点了,而不是一个很大的区间。那么我们要使前后端值不一致一区间最小化,即只在表单中双向绑定的地方允许前后端值不一致,其他时候都是使用后端值。这就要用到computed计算属性了,双向绑定中不再绑定后端传过来的值,而是绑定一个后端值转为前端值的计算属性,这是计算属性的get,光有get只能实现双向绑定的回填,无法实现双向绑定的修改,那么重点就是计算属性的set,在计算属性的set中写一个函数,将双向绑定值再次转回为后端要求的格式,这样就实现了前后端值不一致区间的最小化,仅剩双向绑定时的一个点。

terser

由于老牌工具uglify不支持es6,且uglify-es不再更新,我们选择terser作为js代码压缩工具。

# 全局安装terser命令行工具
npm install -g terser
# 使用terser
terser ./foo.js -c pure_funcs=[console.log],toplevel=true -m -o bar.js
# -c即compress表示普通的压缩代码
# pure_funcs表示删除代码中的console.log方法
# toplevel为true表示只在顶级作用域压缩清理变量
# -m即mangle会压缩变量名等等
# -o代表输出路径

其他配置可以参考terser官网

terser-webpack-plugin

这是terser的webpack插件版。由于vue-cli工具中已经用到了terser-webpack-plugin,因此在vue-cli新建的项目中可以直接引入terser-webpack-plugin,无需安装。

根据vue-cli3文档,所有对webpack的个性化配置都要写在vue.config.js中,示例如下:

// vue.config.js
const TerserPlugin = require("terser-webpack-plugin");
module.exports = {
  configureWebpack: {
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          compress: {
            pure_funcs: ["console.log"]
          }
        }
      })
    ]
  }
}
0%