mr-jili / mr_blog Goto Github PK
View Code? Open in Web Editor NEWMr ji的个人博客
Mr ji的个人博客
1.安装node
2.全局安装 cnpm install vue-cli -g
3.vue init webpack 项目名称
? Project name y
? Project description A Vue.js project
? Author jili <[email protected]>
? Vue build standalone
? Install vue-router? Yes
? Use ESLint to lint your code? Yes? Pick an ESLint preset Standard
? Set up unit tests Yes
? Pick a test runner jest //是否需要安装单元测试工具Karma+Mocha
? Setup e2e tests with Nightwatch? Yes //是否安装e2e来进行用户行为模拟测试
? Should we run `npm install` for you after the project has been created? (recommended) npm
.
|-- build // 项目构建(webpack)相关代码
| |-- build.js // 生产环境构建代码
| |-- check-version.js // 检查node、npm等版本
| |-- dev-client.js // 热重载相关
| |-- dev-server.js // 构建本地服务器
| |-- utils.js // 构建工具相关
| |-- webpack.base.conf.js // webpack基础配置
| |-- webpack.dev.conf.js // webpack开发环境配置
| |-- webpack.prod.conf.js // webpack生产环境配置
|-- config // 项目开发环境配置
| |-- dev.env.js // 开发环境变量
| |-- index.js // 项目一些配置变量
| |-- prod.env.js // 生产环境变量
| |-- test.env.js // 测试环境变量
|-- src // 源码目录
| |-- components // vue公共组件
| |-- store // vuex的状态管理
| |-- App.vue // 页面入口文件
| |-- main.js // 程序入口文件,加载各种公共组件
|-- static // 静态文件,比如一些图片,json数据等
| |-- data // 群聊分析得到的数据用于数据可视化
|-- .babelrc // ES6语法编译配置
|-- .editorconfig // 定义代码格式
|-- .gitignore // git上传需要忽略的文件格式
|-- README.md // 项目说明
|-- favicon.ico
|-- index.html // 入口页面
|-- package.json // 项目基本信息
.
{
"name": "y", //项目名称
"version": "1.0.0", //项目版本
"description": "A Vue.js project", //描述
"author": "jili <[email protected]>",
"private": true, //私有
"scripts": {
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"start": "npm run dev",
"unit": "jest --config test/unit/jest.conf.js --coverage",
"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"
},
"dependencies": { //生产环境 项目运行时所依赖的模块
"vue": "^2.5.2",
"vue-router": "^3.0.1"
},
"devDependencies": { //开发环境 项目开发时所依赖的模块
},
"engines": {
"node": ">= 6.0.0",
"npm": ">= 3.0.0"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
}
'use strict'
const path = require('path')
module.exports = {
dev: {
// Paths
assetsSubDirectory: 'static', //编译输出的二级目录
assetsPublicPath: '/', //编辑发布的根目录,可配置为资源服务器域名或者cdn域名
proxyTable: { //使用proxyTable代理的接口(跨域处理)
'/api1': {
target: 'http://172.22.0.58:8082',
// changeOrigin: true, //将changeOrigin选项设置为true时,代理会将请求转换为预期的目标服务器
pathRewrite: {
'^/api1': ''
}
},
'/api': {
target: 'http://192.168.101.202:9001', //本地
// changeOrigin: true,
pathRewrite: {
'^/api': ''
}
},
'/test': { //测试
target: 'http://123.56.6.167:2000',
changeOrigin: true,
pathRewrite: {
'^/test': ''
}
},
'/pre': { //预发布
target: 'http://123.56.6.167:3000',
changeOrigin: true,
pathRewrite: {
'^/pre': ''
}
},
'/pro': { //生产
target: 'http://123.56.6.167:4000',
changeOrigin: true,
pathRewrite: {
'^/pro': ''
}
}
},
host: '0.0.0.0',
port: 8080, // 端口
autoOpenBrowser: true, // 是否自动打开浏览器
errorOverlay: true, // 在浏览器是否展示错误蒙层
notifyOnErrors: true, // 是否展示错误的通知
// vagrant也会在这方面存在很多问题,在这些情况下,使用poll选项(以轮询的方式去检查文件是否改变)可以设定为true
// 或者具体的数值,指定文件查询的具体周期。
poll: false,
// Use Eslint Loader?
useEslint: true,
// 如果设置为true,在浏览器中,eslint的错误和警告会以蒙层的方式展现。
showEslintErrorsInOverlay: false,
/**
* Source Maps
*/
// source maps的格式
devtool: 'cheap-module-eval-source-map',
// 指定是否通过在文件名称后面添加一个查询字符串来创建source map的缓存
cacheBusting: true,
// 关闭css的source map
cssSourceMap: true
},
build: {
// html文件生成的地方
index: path.resolve(__dirname, '../dist/index.html'),
// 编译生成的文件目录
assetsRoot: path.resolve(__dirname, '../dist'),
//编译生成的静态文件的目录
assetsSubDirectory: 'static',
//编译发布的根目录,可配置为资源服务器域名或者cdn域名
assetsPublicPath: '/',
/**
* Source Maps
*/
//为true最终打包的文件中会出现一些map文件,map文件的作用在于:项目打包后,代码都是经过压缩加密的,如果运行时报错,输出的错误信息无法准确得知是哪里的代码报错。
productionSourceMap: true,
devtool: '#source-map',
//是否开启生产环境的gzip压缩
productionGzip: false,
// 开启gzip压缩的文件的后缀名称
productionGzipExtensions: ['js', 'css'],
// 如果这个选项是true的话,那么则会在build后,会在浏览器中生成一份bundler报告
bundleAnalyzerReport: process.env.npm_config_report
}
}
//本地环境
'use strict'
const merge = require('webpack-merge')
const prodEnv = require('./prod.env')
module.exports = merge(prodEnv, {
NODE_ENV: '"development"',
ENV_CONFIG: '"dev"',
BASE_URL: '"/api"'
})
//测试环境
'use strict'
const merge = require('webpack-merge')
const devEnv = require('./dev.env')
module.exports = merge(devEnv, {
NODE_ENV: '"testing"',
ENV_CONFIG: '"test"',
BASE_URL: '"http://172.22.1.22:9006"'
})
//预发布环境
'use strict'
const merge = require('webpack-merge')
const prodEnv = require('./prod.env')
module.exports = merge(prodEnv, {
NODE_ENV: '"development"',
ENV_CONFIG: '"pre"',
BASE_URL: '"http://123.56.6.167:3000"'
})
//生产环境
'use strict'
module.exports = {
NODE_ENV: '"production"',
ENV_CONFIG: '"pro"',
BASE_URL: '"http://123.56.6.167:4000"'
}
'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
const createLintingRule = () => ({
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: 'pre',
include: [resolve('src'), resolve('test')],
options: {
formatter: require('eslint-friendly-formatter'),
emitWarning: !config.dev.showEslintErrorsInOverlay
}
})
module.exports = {
context: path.resolve(__dirname, '../'),
entry: {
app: './src/main.js' //编译入口文件
},
output: { //编译输出路径
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
resolve: { //一些解决方案配置
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
}
},
resolveLoader:{},
module: {
//各种不同类型文件加载器配置
rules: [
...(config.dev.useEslint ? [createLintingRule()] : []),
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
}
]
},
node: {
setImmediate: false,
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty'
}
}
{
//设定转码规则
"presets": [
["env", { "modules": false }],
"stage-2"
],
//转码用的插件
"plugins": ["transform-runtime"],
"comments": false,
//对BABEL_ENV或者NODE_ENV指定的不同的环境变量,进行不同的编译操作
"env": {
"test": {
"presets": ["env", "stage-2"],
"plugins": [ "istanbul" ]
}
}
}
root = true
[*] // 对所有文件应用下面的规则
charset = utf-8 // 编码规则用utf-8
indent_style = space // 缩进用空格
indent_size = 2 // 缩进数量为2个空格
end_of_line = lf // 换行符格式
insert_final_newline = true // 是否在文件的最后插入一个空行
trim_trailing_whitespace = true // 是否删除行尾的空格
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/>'
})
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
component: () => import('@/components/HelloWorld')
}
]
})
配置热加载: //自动更新
下载webpack-dev-server依赖 npm install -g webpack-dev-server --save-dev
命令行执行命令,启动服务器8080端口 webpack-dev-server --inline --hot
dev、test、prod环境区分:
debug = process.env.NODE_ENV == 'production'
配置文件:
var debug = process.env.NODE_ENV == 'production' ? false : true
配置webpack.config.js
```
//省略一堆配置...
devServer:{
host: 'localhost', //可选,ip
port: 3000, //可选,端口
contentBase:path.resolve(__dirname,'dist'), //可选,基本目录结构
compress: true //可选,压缩
}
```
new webpack.HotModuleReplacementPlugin(), //热加载插件
Vue.js 是采用 Object.defineProperty 的 getter 和 setter,并结合观察者模式来实现数据绑定的。当把一个普通 Javascript 对象传给 Vue 实例来作为它的 data 选项时,Vue 将遍历它的属性,用 Object.defineProperty 将它们转为 getter/setter。用户看不到 getter/setter,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>双向数据绑定</title>
</head>
<body>
<input type="text" id="message" />
<div id="msg"></div>
<script>
var obj = {};
Object.defineProperty(obj, "data", {
get: function () {
console.log("get")
},
set: function (newValue) {
document.getElementById("message").value = newValue
document.getElementById("msg").innerText = newValue
}
})
document.getElementById("message").onkeyup = function (e) {
console.log(e.target.value);
obj.data = e.target.value;
};
//柯里化**
// var curry = function(func){
// var args = [].slice.call(arguments,1);
// console.log(args);
// return function(){
// var newArgs = args.concat([].slice.call(arguments));
// console.log(newArgs);
// return func.apply(this,newArgs);
// }
// }
// function add(a, b) {
// return a + b;
// }
// var addCurry = curry(add,1);
// console.log(addCurry(3));//3
</script>
</body>
</html>
//尤雨溪版
var obj = {foo:123}
convert(obj)
function convert(obj){
Object.keys(obj).forEach(key=>{
let internalVal = obj[key];
Object.defineProperty(obj,key,{
get(){
return internalVal;
},
set(newVal){
internalVal = newVal;
}
})
})
}
// obj.foo ="jili1111111111111"
这里只是简单的了解下,待续~~~
详细了解 :https://github.com/Mr-jili/mvvm
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>attachment upload</title>
<script src="node_modules\jquery\dist\jquery.min.js"></script>
<script src="node_modules\bootstrap\dist\js\bootstrap.min.js"></script>
<link rel="stylesheet" href="node_modules\bootstrap\dist\css\bootstrap.css">
<style>
input{
position: absolute;
top: 0;
width: 90px;
height: 38px;
top: 0;
opacity: 0;
}
#file_view{
text-align: right;
}
ul,li{
list-style: none;
}
</style>
</head>
<body>
<div id="newPageGrey">
<div class="cushion_enclosure_box" style="position: relative;padding-top: 10px;">
<button type="button" class="btn btn-info" id="cushion_enclosure">上传附件</button>
<div id="file_view"></div>
</div>
</div>
</body>
<script>
$('#newPageGrey').on('click', '#cushion_enclosure', function () {
debugger
var file_input_ele = $('#newPageGrey .file_input')
if (file_input_ele.length) {
for (var i = 0; i < file_input_ele.length; i++) {
if (file_input_ele.eq(i).attr('id') == 'uploaderInput') {
file_input_ele.eq(i).remove()
}
}
}
var file_num = (file_input_ele.eq(file_input_ele.length - 1)).attr('file_num') == undefined ? 0 : parseFloat((
file_input_ele.eq(file_input_ele.length - 1)).attr('file_num'))
if (!file_input_ele.length) {
var uploadFile =
'<input name="files0" id="uploaderInput" file_num="0" class="file_input" type="file" accept="application/pdf,image/png, image/jpeg,image/jpg"/>'
} else {
var uploadFile = '<input name="files' + (file_num + 1) + '" id="uploaderInput" file_num="' + (file_num + 1) +
'" class="file_input" type="file" accept="application/pdf,image/png, image/jpeg,image/jpg"/>'
}
$('#file_view').append($(uploadFile))
$('#uploaderInput').bind('change', function (e) {
// 可以做一些其他的事,比如图片预览
var that = this;
var fileObj = this.files[0]
var windowURL = window.URL || window.webkitURL
if (fileObj) {
var dataURl = windowURL.createObjectURL(fileObj)
}
var file_index = $(this).val().lastIndexOf('\\')
var format_index = $(this).val().lastIndexOf('.')
var file_name = $(this).val().substring(file_index + 1)
var format_name = $(this).val().substring(format_index + 1)
// 文件格式
if (format_name != 'jpg' && format_name != 'JPEG' && format_name != 'JPG' && format_name != 'jpeg' &&
format_name != 'png' && format_name != 'PNG' && format_name != 'pdf' && format_name != 'PDF') {
alert('请上传jpg、pdf、png、jpeg格式文件!')
$(this).val('')
return
}
var file_html = ''
if (!file_input_ele.length) {
file_html += '<ul class="row cushion_enclosure_box_list" style="list-style:none;">' +
'<li class="col-lg-10 col-md-10 col-sm-10 col-xs-10 files_name">' + file_name + '</li>' +
'<li class="col-lg-1 col-md-1 col-sm-1 col-xs-1 open_view" style="padding:0;"><a href="' + dataURl +
'" target="_blank">查看</a></li>' +
'<li class="col-lg-1 col-md-1 col-sm-1 col-xs-1 delete_file fontblue" file_num="0" style="padding:0;">删除</li>' +
'</ul>'
} else {
file_html += '<ul class="row cushion_enclosure_box_list" style="list-style:none;">' +
'<li class="col-lg-10 col-md-10 col-sm-10 col-xs-10 files_name">' + file_name + '</li>' +
'<li class="col-lg-1 col-md-1 col-sm-1 col-xs-1 open_view" style="padding:0;"><a href="' + dataURl +
'" target="_blank">查看</a></li>' +
'<li class="col-lg-1 col-md-1 col-sm-1 col-xs-1 delete_file fontblue" file_num="' + (file_num + 1) +
'" style="padding:0;">删除</li>' +
'</ul>'
}
$('#newPageGrey').find('.cushion_enclosure_box').append(file_html)
$(this).removeAttr('id')
})
$('#uploaderInput').click()
})
// 附件 删除
$('#newPageGrey').on('click', '.delete_file', function () {
var index = $(this).attr('file_num')
var file_input = $(this).parent('.cushion_enclosure_box_list').siblings('#file_view').find('.file_input')
for (var i = 0; i < file_input.length; i++) {
if (file_input.eq(i).attr('file_num') == index) {
file_input.eq(i).remove()
}
}
$(this).parent('.cushion_enclosure_box_list').remove()
var file_input_ele = $('#newPageGrey .file_input')
if (file_input_ele.length) {
for (var i = 0; i < file_input_ele.length; i++) {
file_input_ele.eq(i).attr('file_num', i)
file_input_ele.eq(i).attr('name', 'files' + i)
}
}
var file_li1 = $('#newPageGrey').find('li.delete_file')
for (var i = 0; i < file_li1.length; i++) {
file_li1.eq(i).attr('file_num', i)
}
})
$('#newPageGrey').on('change', '.file_input', function () {
var file_input_ele = $('#newPageGrey .file_input')
if (file_input_ele.length) {
for (var i = 0; i < file_input_ele.length; i++) {
file_input_ele.eq(i).attr('file_num', i)
file_input_ele.eq(i).attr('name', 'files' + i)
}
}
var file_li1 = $('#newPageGrey').find('li.delete_file')
for (var i = 0; i < file_li1.length; i++) {
file_li1.eq(i).attr('file_num', i)
}
})
//后台上传
// var upload_file = $('#newPageGrey #file_view').find('.file_input')
// var form = new FormData(document.getElementById("XXX"));
// for (var i = 0; i < upload_file.length; i++) {
// if (upload_file.eq(i).attr('id') && (i !== 0)) {
// upload_file.eq(i).remove()
// break // 当有空input一定是最后一个,可以跳出循环
// }
// upload_file.eq(i).attr('name', 'files' + i)
// var key = 'files' + i
// var val = upload_file.eq(i).val()
// form.append(key, val)
// }
</script>
</html>
创建新节点
createDocumentFragment() //创建一个DOM片段
createElement() //创建一个具体的元素
createTextNode() //创建一个文本节点
//文档碎片 利于优化
var element = document.getElementById('ul'); // assuming ul exists
var fragment = document.createDocumentFragment();
var browsers = ['Firefox', 'Chrome', 'Opera',
'Safari', 'Internet Explorer'];
browsers.forEach(function(browser) {
var li = document.createElement('li');
li.textContent = browser;
fragment.appendChild(li);
});
element.appendChild(fragment);
添加、移除、替换、插入
appendChild() //添加
removeChild() //移除
replaceChild() //替换
insertBefore() //插入
查找
getElementsByTagName() //通过标签名称
getElementsByName() //通过元素的Name属性的值
getElementById() //通过元素Id,唯一性
将指定的文本解析为HTML或XML,并将结果节点插入到DOM树中的指定位置。它不会重新解析它正在使用的元素,因此它不会破坏元素内的现有元素。这避免了额外的序列化步骤,使其比直接innerHTML操作更快。
element.insertAdjacentHTML(position, text);
position参数:
beforebegin 元素自身的前面。
afterbegin 插入元素内部的第一个子节点之前
beforeend 插入元素内部的最后一个子节点之后
afterend 元素自身的后面
// <div id="one">one</div>
var d1 = document.getElementById('one');
d1.insertAdjacentHTML('afterend', '<div id="two">two</div>');
// 此时,新结构变成: // <div id="one">one</div><div id="two">two</div>
// ES6 version
// let html = `<div id="two">two</div>`;
// div.insertAdjacentHTML(`beforeend`, html);
deno是使用Go语言代替C++重新编写跨平台底层内核驱动,上层仍然使用V8引擎,最终提供一个安全的TypeScript运行时
链接:https://github.com/denoland/deno
TypeScript 是一种由微软开发的自由和开源的编程语言。它是 JavaScript 的一个超集,TypeScript 在 JavaScript 的基础上添加了可选的静态类型和基于类的面向对象编程。
TypeScript是一个应用程序级的JavaScript开发语言。(这也表示TypeScript比较牛逼,可以开发大型应用,或者说更适合开发大型应用)
TypeScript是JavaScript的超集,可以编译成纯JavaScript。这个和我们CSS离的Less或者Sass是很像的,我们用更好的代码编写方式来进行编写,最后还是有好生成原生的JavaScript语言。
TypeScript跨浏览器、跨操作系统、跨主机、且开源。由于最后他编译成了JavaScript所以只要能运行JS的地方,都可以运行我们写的程序,设置在node.js里。
TypeScript始于JavaScript,终于JavaScript。遵循JavaScript的语法和语义,所以对于我们前端从业者来说,学习前来得心应手,并没有太大的难度。
TypeScript可以重用JavaScript代码,调用流行的JavaScript库。
TypeScript提供了类、模块和接口,更易于构建组件和维护。
首先安装TypeScript
npm install typescript -g
tsc --version
编写HelloWorld程序
终端输入:
1.npm init -y (初始化项目,生成package.json文件)
2.tsc --init (它是一个TypeScript项目的配置文件,可以通过读取它来设置TypeScript编译器的编译参数)
3.npm install @types/node --dev-save (主要是解决模块的声明文件问题)
4.编写hello.ts文件
var a:string = "HelloWorld"
console.log(a)
5.tsc hello.ts 编译成hello.js文件
6.node hello.js
Undefined
Number
String
Boolean
enum 枚举类型
any 任意类型
void 空类型
Array
Tuple 元祖类型
Null
Number类型有
enum类型
一般应用于固定数据
// enum REN{ nan , nv ,yao}
// console.log(REN.yao) //返回了2,这是索引index,跟数组很象。
enum REN{
nan = '男',
nv = '女',
yao= '妖'
}
console.log(REN.yao) //返回了妖 这个字
any类型
TypeScript友好的为我们提供了一种特殊的类型any,比如我们在程序中不断变化着类型,又不想让程序报错,这时候就可以使用any了。
var t:any =10
t = "jspang"
t = true
console.log(t)
举个typescript语法的例子:
function searchXiaoJieJie3(...xuqiu:string[]):string{
let yy:string = '找到了'
for (let i =0;i<xuqiu.length;i++){
yy = yy + xuqiu[i]
if(i<xuqiu.length){
yy=yy+'、'
}
}
yy=yy+'的小姐姐'
return yy
}
var result:string = searchXiaoJieJie3('22岁','大长腿','瓜子脸','水蛇腰')
console.log(result)
局部变量·全局变量·var与let和javascript差不多,不一一言论
声明数组的方法
由let var 关键字来实现,ts中声明较复杂
let arr1:number[ ] //声明一个数值类型的数组
let arr2:Array<string> //声明一个字符串类型的数组
数组赋值
//定义一个空数组,数组容量为0
let arr1:number[] = []
//定义一个数组时,直接给数组赋值
let arr2:number[] = [1,2,3,4,5]
//定义数组 的同事给数组赋值
let arr3:Array<string> = ['jspang','技术胖','金三胖']
let arr4:Array<boolean> = [ true,false,false]
//切记:
let arr5:number[] = [1,2,true] //报错 必须存储number类型的数据
let arr1:number[] = new Array()
let ara2:number[] = new Array(1,2,3,4,5)
let arr3:Array<string> = new Array('jspang','技术胖','金三胖')
let arr4:Array<boolean> = new Array(true,false,false)
let jspang:string = '技术胖'
let jspanga:String = new String("jspang.com")
console.log(jspang) //技术胖
console.log(jspanga) //[String: 'jspang.com']
let something:string = "清早起来打开窗,心情美美的,我要出去找小姐姐,心情美美的。"
let xiaoJieJie:string = "小姐姐"
console.log(something.replace(xiaoJieJie,'小哥哥')) // /小姐姐/g全局匹配
1.不传递任何参数
let d:Date = new Date()
console.log(d) //2018-09-06T06:48:12.504Z
2.传递一个整数
let d:Date = new Date(1000)
let da:Date = new Date(2000)
console.log(d) //1970-01-01T00:00:01.000Z
console.log(da) //1970-01-01T00:00:02.000Z
3.传递一个字符串
let d1:Date = new Date('2018/09/06 05:30:00')
let d2:Date = new Date('2018-09-06 05:30:00')
let d3:Date = new Date('2018-09-06T05:30:00')
console.log(d1)
console.log(d2)
console.log(d3) //2018-09-05T21:30:00.000Z结果一样
4.传递表示年月日时分秒的变量
let d:Date = new Date(year,month,day,hours,minutes,seconds,ms);
构造函数中可以传一个参数,也可以传递两个参数。一个是字符串描述,另一个是修饰符,比如g是全局修饰符,i是忽略大小写,m是多行模式。
let reg1:RegExp = new RegExp("jspang") //表示字符串规则里含有jspang
console.log(reg1)
let reg2:RegExp = new RegExp("jspang",'gi')
console.log(reg2)
let reg3:RegExp = /jspang/
let reg4:RegExp = /jspang/gi
RegExp对象包含两个方法:test( )和exec( ),功能基本相似,用于测试字符串匹配。
按需加载插件。只需要引入模块即可,无需单独引入样式。babel-plugin-import
npm install babel-plugin-import --save-dev
// 在 .babelrc 或 babel-loader 中添加插件配置
// 注意:webpack 1 无需设置 libraryDirectory
{
"plugins": [
["import", {
"libraryName": "vant",
"libraryDirectory": "es",
"style": true
}]
]
}
//以Vant为例
import { Button, Cell } from 'vant';
Vue.use(Button);
头条题目描述:
const obj = {
selector: {
to: {
toutiao: "FE Coder"
}
},
target: [1, 2, {
name: 'byted'
}]
};
get(obj, 'selector.to.toutiao', 'target[0]', 'target[2].name')
//结果:FE Coder 1 byted
思路一:
function get(data, ...args) {
const reg = /\[[0-9]+\]/gi;
return args.map((item) => {
const paths = item.split('.');
let res = data;
paths.map((path) => {
if (reg.test(path)) {
const match = path.match(reg)[0];
console.log(match)
// 将target[0]里的target储存到cmd里
const cmd = path.replace(match, '');
// 获取数组索引
console.log(cmd)
const arrIndex = match.replace(/[\[\]]/gi, '');
console.log(cmd, arrIndex)
res = res[cmd][arrIndex];
} else {
res = res[path];
}
});
return res;
});
}
思路二:
function get(data, ...args) {
const res = JSON.stringify(data);
return args.map(item => {
return (new Function(`try {return ${res}.${item} } catch(e) {}`))()
})
}
p{}
.class{}
[type=radio]{}
:hover{}
::before{}
#ID{}
[type=checkbox]+label{}
not(.class){}
*
权重计算规则:
backgroundimage:url('1.jpg),url('2.jpg')
border-box / padding-box / content-box
border-box / padding-box / content-box
float 布局
- 元素“浮动” 2. 脱离文档流 3. 但不脱离文本流
盒模型
在标准模式下的盒模型: width /height = 内容的宽度 / 内容的高度
在怪异模式下的盒模型:width / height = 内容的宽度 + border + padding / 内容的高度 + border + padding
box-sizing有两个值一个是content-box,另一个是border-box。
当设置为box-sizing:content-box时,将采用标准模式解析计算;
当设置为box-sizing:border-box时,将采用怪异模式解析计算。
position属性 (z-index设置层级)
BFC(块格式化上下文 )
清除浮动
第一种
.clearfix:after{
content: "";
display: block;
height: 0;
clear:both;
visibility: hidden;
}
第二种
// 给父容器添加 overflow:hidden 或者 auto 样式,通过触发BFC方式,实现浮动
第三种
// 新添标签
<div class="clear">额外标签法</div>
第四种
// 双伪元素清除浮动(强烈推荐)
.clearfix:before,
.clearfix:after {
display: table;
content: ""; /*不用有内容也可以*/
}
.clearfix:after {
clear: both;
}
.clearfix {
*zoom: 1;
}
href 锚点或资源之间定义一个链接或者关系,在 link和a 等元素上使用
src 是引入。在 img、script、iframe 等元素上使用。
title:既是html标签,又是html属性,title作为属性时,用来为元素提供额外说明信息.
alt:alt是html标签的属性,alt属性则是用来指定替换文字,只能用在img、area和input元素中(包括applet元素),用于网页中图片无法正常显示时给用户提供文字说明使其了解图像信息.
举例说明:
<ul> <p>111</p> <span>222</span> <li>1</li> <li>2</li> <li>3</li> </ul>
li:nth-of-type(2):表示ul下的第二个li元素
li:nth-child(2):表示既是li元素又是在ul下的第二个元素(找不到)。
建议一般使用nth-of-type,不容易出问题。
单冒号(:)用于CSS3伪类,双冒号(::)用于CSS3伪元素。 对于CSS2之前已有的伪元素,比如:before,单冒号和双冒号的写法::before作用是一样的。
方法1: .div1{ position:absolute; left:50%; top:50%; transform: translate(-50%,-50%); }
方法2: .div2{ position: absolute; left:0; top: 0; bottom: 0; right: 0; margin: auto; }
方法3: .div3{ position: absolute; left: 50%; top:50%; margin-left:-200px; margin-top: -200px; }
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
伪类选择器单冒号 伪元素两个冒号
:not()选择器称为否定选择器
:empty()选择器表示的就是空
:first-child()选择器表示的是选择父元素的第一个子元素的元素E
:nth-child()选择某个元素的一个或多个特定的子元素。
:nth-last-child()从某父元素的最后一个子元素开始计算,来选择特定的元素
:nth-of-type(n)选择器和:nth-child(n)选择器非常类似,不同的是它只计算父元素中指定的某种类型的子元素。
:only-child表示的是一个元素是它的父元素的唯一一个子元素。
:first-line为某个元素的第一行文字使用样式。
:first-letter 为某个元素中的文字的首字母或第一个字使用样式。
:before 在某个元素之前插入一些内容。
:after 在某个元素之后插入一些内容。::first-line选择元素的第一行,
::before和::after这两个主要用来给元素的前面或后面插入内容,这两个常用"content"配合使用,见过最多的就是清除浮动
ie和ff都存在,相邻的两个div的margin-left和margin-right不会重合,但是margin-top和> margin-bottom却会发生重合。
解决方法,养成良好的代码编写习惯,同时采用margin-top或者同时采用margin-bottom。
px 在缩放页面时无法调整那些使用它作为单位的字体、按钮等的大小;
em 的值并不是固定的,会继承父级元素的字体大小,代表倍数;
rem 的值并不是固定的,始终是基于根元素 的,也代表倍数。
压缩打包,图片整合,避免使用Hack,解决兼容问题,使用简写,让CSS能保证日后的维护
在css中给div添加上“vertical-align:middle”属性。
// animation transition 区别:
他们的主要区别是transition需要触发一个事件才能改变属性, 而animation不需要触发任何事件的情况下才会随时间改变属性值,并且transition为2帧,从from .... to,而animation可以一帧一帧的
transform的主要用途是用来做元素的特殊变形
Transition属性是一个简单的动画属性,animation的简化版本
animation则根据这个keyframes提供的属性变化方式去计算元素动画当中的属性
@keyframes 'wobble'{
0%{
left:100px
}
30%{
left:300px;
}
100%{
left:500px;
}
}
.animate{
left:100px;
-webkit-animation:wobble 0.5s ease-out;
-webkit-animation-fill-mode:backwards;
}
图像拼合,是把网页中一些背景图片整合到一张图片文件中,再利用CSS的“background-image”,“background- repeat”,“background-position”的组合进行背景定位,减少很多图片请求的开销,减少请求耗时
visibility:hidden、display:none、z-index=-1、opacity:0
a,a:hover,a:active,a:visited,a:link,a:focus{
-webkit-tap-highlight-color:rgba(0,0,0,0);
-webkit-tap-highlight-color: transparent;
outline:none;background: none;
text-decoration: none;border:none;
-webkit-appearance: none; }
1.我父组件里传一个json数据,但是子组件大多时候都是NULL,但是有的时候子组件又可以接收到
props: ['charData'],
data() {
return {
dataList: []
}
}
watch: {
charData: function (newVal,oldVal) {
}
}
//监听charData的值,当它由空转变时就会触发,这时候就能取到,拿到值后要做的处理方法也需要在watch里面执行
2.vue拦截器
// 引入axios
import axios from 'axios'
// axios配置
Vue.prototype.$http = axios
// 配置默认axios参数
axios.defaults.baseURL = '/'
axios.defaults.timeout = 1000000
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'
// 添加请求拦截器
axios.interceptors.request.use(function (config) {
let token = localStorage.getItem('token')
if(token== null && router.currentRoute.path == '/login'){// 本地无token,不为登录 跳转至登录页面
router.push('/login')
}else{
if(config.data==undefined){
config.data = {
"token":token
}
}else{
Object.assign(config.data,{"token":token})
}
}
return config
}, function (error) {
iView.Message.error('请求失败')
return Promise.reject(error)
})
// 返回结果拦截
axios.interceptors.response.use(function (response) {
if(response.hasOwnProperty("data") && typeof response.data == "object"){
if(response.data.code === 998){// 登录超时 跳转至登录页面
iView.Message.error(response.data.msg)
router.push('/login')
return Promise.reject(response)
}else if (response.data.code === 1000) {// 成功
return Promise.resolve(response)
}
} else {
return Promise.resolve(response)
}
}, function (error) {
// 请求取消 不弹出
if(error.message != '0000'){
iView.Message.error('请求失败')
}
// 请求错误时做些事
return Promise.reject(error)
})
3.使用keep-alive标签后部分安卓机返回缓存页位置不精确问题
//router全局配置即可
<div id="app">
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>
</div>
const router = new Router({
scrollBehavior(to, from, savedPosition) {
if (savedPosition && to.meta.keepAlive) {
return savedPosition;
}
return { x: 0, y:0 };
},
});
4.页面返回出现空白屏问题
//全局配置,共用
const router = new Router({
scrollBehavior(to, from, savedPosition) {
// keep-alive 返回缓存页面后记录浏览位置
if (savedPosition && to.meta.keepAlive) {
return savedPosition;
}
// 异步滚动操作
return new Promise((resolve) => {
setTimeout(() => {
resolve({ x: 0, y: 1 });
}, 0);
});
},
});
5.vue-router中的全局钩子函数
//在路由跳转之前做什么 权限判定
router.beforeEach((to, from, next) => {
let token = router.app.$storage.fetch("token");
let needAuth = to.matched.some(item => item.meta.login);
if(!token && needAuth) return next({path: "/login"});
next();
});
//使用钩子函数对路由进行权限跳转
router.beforeEach((to, from, next) => {
const role = localStorage.getItem('ms_username');
if(!role && to.path !== '/login'){
next('/login');
}else if(to.meta.permission){
// 如果是管理员权限则可进入,这里只是简单的模拟管理员权限而已
role === 'admin' ? next() : next('/403');
}else{
// 简单的判断IE10及以下不进入富文本编辑器,该组件不兼容
if(navigator.userAgent.indexOf('MSIE') > -1 && to.path === '/editor'){
Vue.prototype.$alert('vue-quill-editor组件不兼容IE10及以下浏览器,请使用更高版本的浏
览器查看', '浏览器不兼容通知', {
confirmButtonText: '确定'
});
}else{
next();
}
}
})
//暂无使用
router.afterEach((to, from) => {})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
[v-cloak]{
display: none
}
</style>
</head>
<body>
<div id="box">
<p v-cloak>{{msg}}</p>
</div>
<script src="js/vue.js"></script>
<script>
new Vue({
el:"#box",
data:{
msg:"hellovue"
}
})
</script>
</body>
</html>
在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
应用场景:需要在视图更新之后,基于新的视图进行操作。
////点击按钮显示原本以 v-show = false 隐藏起来的输入框,并获取焦点。
showsou(){
this.showit = true
this.$nextTick(function () {
// DOM 更新了
document.getElementById("keywords").focus()
})
}
//点击获取元素宽度。
<div id="app">
<p ref="myWidth" v-if="showMe">{{ message }}</p>
<button @click="getMyWidth">获取p元素宽度</button>
</div>
getMyWidth() {
this.showMe = true;
//this.message = this.$refs.myWidth.offsetWidth;
//报错 TypeError: this.$refs.myWidth is undefined
this.$nextTick(()=>{
//dom元素更新后执行,此时能拿到p元素的属性
this.message = this.$refs.myWidth.offsetWidth;
})
}
forEach只支持同步代码
//解决方法
async function test() {
let arr = [3, 2, 1]
for(let item of arr){
const res = await fetch(item)
console.log(res)
}
console.log('end')
}
//OR
async function test() {
let arr = [3, 2, 1]
await Promise.all(
arr.map(async item => {
const res = await fetch(item)
console.log(res)
})
)
console.log('end')
}
function fetch(x) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(x)
}, 500 * x)
})
}
test()
<!--预期结果 -->
// 1 2 3 end
<!-- 属性name -->
<a :[name]="url"> ... </a>
<!-- 计算属性sss和s -->
<img :[sss]="/img/test.png"/>
<!-- 方法change1和change2 -->
<img :[change1()]="change2()"/>
data: {
name: 'href',
sss: 'src'
}
computed: {
top() {
return 'top'
},
name: {
get () {
return this.name
},
set (val) {
this.name = val
}
}
}
computed可缓存,但不可传参,会根据data中的属性变化而变化,即是根据响应式依赖来变化,而Date不是响应式依赖,即不会变化;method则每次都会进行计算,但可传参。
watch用于处理异步或开销较大的操作,如输入搜索时。
<!-- 属性名可加引号也可不加,属性小驼峰 -->
<div :style="{ 'color': 'red', fontSize: fontSize + 'px' }">样式3</div>
data: {
isActive: true,
activeClass: 'active'
}
<!-- 使用数组时变量和字符串需要通过引号来区分 -->
<div :class="[isActive ? activeClass : '', 'errorClass']"></div>
<!-- 使用对象时类名不加引号可表示变量也可表示字符串 -->
<div :class="[{ active: isActive }, 'errorClass']"></div>
可使用template包裹元素,template会被当成不可见的包裹元素
<template v-if="ok">
<h1>Title</h1>
<p>Paragraph 1</p>
<p>Paragraph 2</p>
</template>
多条件判断
<div v-if="type === 'A'">
A
</div>
<div v-else-if="type === 'B'">
B
</div>
<div v-else-if="type === 'C'">
C
</div>
<div v-else>
Not A/B/C
</div>
添加key防止vue重复利用不想被重复利用的元素,如下的input如果不添加key,则vue会重复使用key,进而input的value值在切换后还会被保留,因为vue仅仅替换了placeholder
<template v-if="loginType === 'username'">
<label>Username</label>
<input placeholder="Enter your username" key="username-input">
</template>
<template v-else>
<label>Email</label>
<input placeholder="Enter your email address" key="email-input">
</template>
v-if是组件的销毁和重建,如果初始条件为false,则什么都不做,直到变为真,所以切换开销高,运行条件很少改变时适用
v-show是display:none和block之间的CSS切换,基于渲染,不管初始条件如何都会渲染,所以初始渲染开销高,切换频率高时适用
Vue.set(object, key, value)
this.$set(object, key, value)
this.items.splice(index, 1, newValue)
// 不要直接Object.assign(this.items, {age: 18}
this.items = Object.assign({}, this.items, {
age: 18,
favoriteColor: 'Vue Green'
})
.passive:滚动的默认事件会立即出发,即告诉浏览器不想阻止默认事件的触发,可提升移动端性能
<div :scroll.passive="onScroll">...</div>
.capture:添加事件监听器时使用事件捕获模式,即元素自身触发的事件先在此处理,然后才交由内部元素进行处理
.self:只当在 event.target 是当前元素自身时触发处理函数,即事件不是从内部元素触发的
.once:点击事件只会触发一次
键盘修饰符:
<input v-on:keyup.enter="submit">
使用v-bind="obj"会将对象的每个属性都作为一个独立的prop传入进去,所以接受时也需要逐个属性接收。
<test v-bind="obj"></test>
props虽然是单向数据流,但对于引用类型,子组件还是可以改变父组件的状态
props会在组件实例创建之前进行验证,所以实例的属性再default或validator中是不可用的。
<base-layout>
<template v-slot:header>
<h1>Here might be a page title</h1>
</template>
<!-- 默认插槽也可不用加上template和v-slot -->
<template v-slot:default>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
</template>
<template v-slot:footer>
<p>Here's some contact info</p>
</template>
</base-layout>
<!-- current-user组件 -->
<span>
<slot :user="user">
{{ user.lastName }}
</slot>
</span>
<!-- 父级组件通过自定义名称访问子级作用域 -->
<current-user>
<template v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</template>
</current-user>
<!-- 支持缩写和解构 -->
<current-user>
<template #default="{ user = { firstName: Gust } }">
{{ user.firstName }}
</template>
</current-user>
区分:this.$router指路由器,this.$route指当前路由
通配符:捕获所有路由或 404 Not found路由
// 含通配符的路由都要放在最后,因为优先级由定义顺序决定
{
// 会匹配所有路径
path: '*'
}
{
// 会匹配以 `/user-` 开头的任意路径
path: '/user-*'
}
当使用一个通配符时,$route.params内会自动添加一个名为 pathMatch 参数。它包含了 URL 通过通配符被匹配的部分:
// 给出一个路由 { path: '/user-*' }
this.$router.push('/user-admin')
this.$route.params.pathMatch // 'admin'
// 给出一个路由 { path: '*' }
this.$router.push('/non-existing')
this.$route.params.pathMatch // '/non-existing'
点击 等同于调用 router.push(...)方法,因为会在内部调用该方法,进而在history栈添加一个新的记录
使用了push时,如果提供的path不完整,则params会被忽略,需要提供路由的 name 或手写完整的带有参数的 path:
const userId = '123'
router.push({ name: 'user', params: { userId }}) // -> /user/123
router.push({ path: `/user/${userId}` }) // -> /user/123
// 这里的 params 不生效
router.push({ path: '/user', params: { userId }}) // -> /user
router.push/router.replace/router.go 效仿于 window.history.pushState/window.history.replaceState/window.history.go
命名视图:router-view可设置名字,如果router-view没有设置名字,那么默认为 default
<router-view></router-view>
<router-view name="a"></router-view>
<router-view name="b"></router-view>
const router = new VueRouter({
routes: [
{
path: '/',
components: {
default: Foo,
a: Bar,
b: Baz
}
}
]
})
路由使用props:可将路由参数设置为组件属性
const User = {
props: ['id'],
template: '<div>User {{ id }}</div>'
}
// 通过布尔值设置
const router = new VueRouter({
routes: [
{ path: '/user/:id', component: User, props: true },
// 对于包含命名视图的路由,你必须分别为每个命名视图添加 `props` 选项:
{
path: '/user/:id',
components: { default: User, sidebar: Sidebar },
props: { default: true, sidebar: false }
}
]
})
// 通过函数设置query
// URL /search?q=vue 会将 {name: 'vue'} 作为属性传递给 SearchUser 组件
const router = new VueRouter({
routes: [
{ path: '/search', component: SearchUser, props: (route) => ({ name: route.query.q }) }
]
})
beforeRouteEnter:可使用beforeRouteEnter来提前获取接口数据,同时需要在next后才能访问到实例:
beforeRouteEnter(to, from, next) {
axios('/text.json').then(res => {
next(vm => {
vm.datas = res
})
})
}
路由设置有参数时,如果跳转页面后再通过返回键返回时,路由会保留有参数,如果通过push跳转返回,则不会保留该参数,这在第三方调用模块传参时需要注意。
{
title: '退款方式',
render: (h, params) => {
return h('Select', {
props: {
clearable: true,
value: 0
},
on: {
'on-change': (val) => {
this.item_str[params.index].type = val
}
}
}, this.action.map(item => {
return h('Option', {
props: {
value: item.value,
label: item.name
}
})
}))
}
},
{
title: '退款金额',
render: (h, params) => {
return h('Input', {
props: {
value: '',
size: 'small'
},
on: {
input: (val) => {
console.log(params)
this.item_str[params.index].amount = val
}
}
})
}
},
{
title: '退款原因',
render: (h, params) => {
return h('Input', {
props: {
value: ''
},
on: {
input: (val) => {
console.log(params)
this.item_str[params.index].reason = val
}
}
})
}
},
{
title: '操作',
render: (h, params) => {
return h('div', [
h('Button', {
style: {
color: '#3399ea',
cursor: 'pointer'
},
on: {
click: () => {
this.showDetail()
}
}
}, '添加'),
h('Button', {
style: {
color: '#3399ea',
cursor: 'pointer'
},
on: {
click: () => {
}
}
}, '删除')
])
}
}
Nginx是一款轻量级的HTTP服务器,采用事件驱动的异步非阻塞处理方式框架,这让其具有极好的IO性能,时常用于服务端的反向代理和负载均衡。
new Set([iterable]),返回一个Set对象,这里可以需要Array.from进行转换
var set = new Set([1]);
set.add(100) // Set { 1,100 }
set.delete(1) // Set { 100 }
set.has(3) // false
//set.clear() // 清除所有成员
set.size //数量
console.log(set.entries()) //遍历
console.log(set.keys()) //遍历
console.log(set.values()) //遍历
for(let item of set.entries()){
console.log(item)
}
for(let item of set.keys()){
console.log(item)
}
Array.from(new Set([1,3,1,NaN,NaN,null,undefined,null,undefined])) //[ 1, 3, NaN, null, undefined ]
var arr = [1,4,5,6];
var set = new Set(arr)
console.log([...set])
var text = "yuan";
var stringSet = new Set(text);
console.log(stringSet); // Set(4) {"y", "u", "a", "n"}
stringSet.size; //4
let a = new Set([1, 2, 3]);
let b = new Set([4, 3, 2]);
// 并集
let union = new Set([...a, ...b]); // Set {1, 2, 3, 4}
// 交集
let intersect = new Set([...a].filter (x => b.has(x))); // Set { 2, 3}
// 差集
let difference = new Set([...a].filter (x => !b.has(x))); // Set { 1 }
对象保存键值对。任何值(对象或者原始值) 都可以作为一个键或一个值。
var myMap = new Map();
var keyObj = {},
keyFunc = function () {},
keyString = "a string";
// 添加键
myMap.set(keyString, "和键'a string'关联的值");
myMap.set(keyObj, "和键keyObj关联的值");
myMap.set(keyFunc, "和键keyFunc关联的值");
myMap.size; // 3
// 读取值
myMap.get(keyString); // "和键'a string'关联的值"
myMap.get(keyObj); // "和键keyObj关联的值"
myMap.get(keyFunc); // "和键keyFunc关联的值"
myMap.get("a string"); // "和键'a string'关联的值"
// 因为keyString === 'a string'
myMap.get({}); // undefined, 因为keyObj !== {}
myMap.get(function() {}) // undefined, 因为keyFunc !== function () {}
将 NaN 作为 Map 的键
var myMap = new Map();
myMap.set(NaN, "not a number");
myMap.get(NaN); // "not a number"
var otherNaN = Number("foo");
myMap.get(otherNaN); // "not a number"
使用 for..of 方法迭代 Map
var myMap = new Map();
myMap.set(0, "zero");
myMap.set(1, "one");
for (var key of myMap.keys()) {
console.log(key);
}
// 将会显示两个log。 一个是 "0" 另一个是 "1"
for (var value of myMap.values()) {
console.log(key,value);
}
// // 将会显示两个log。 一个是 "zero" 另一个是 "one"
for (var [key, value] of myMap.entries()) {
console.log(key,value);
}
// 将会显示两个log。 一个是 "0 zero" 另一个是 "1 one"
Map对象也能与数组合并
var first = new Map([
[1, 'one'],
[2, 'two'],
[3, 'three'],
]);
var second = new Map([
[1, 'uno'],
[2, 'dos']
]);
// Map对象同数组进行合并时,如果有重复的键值,则后面的会覆盖前面的。
var merged = new Map([...first, ...second, [1, 'eins']]);
console.log(merged.get(1)); // eins
console.log(merged.get(2)); // dos
console.log(merged.get(3)); // three
用来检查一个数值是否为有限的(finite),即不是Infinity。
如果参数类型不是数值,Number.isFinite一律返回false
用来判断一个数值是否为整数
Number.isInteger(25) // true
Number.isInteger(5E-324) // false
Number.isInteger(5E-325) // true 5E-325由于值太小,会被自动转为0,因此返回true。
Number.isInteger(25.1) // false
Number.isInteger() // false
Number.isInteger(null) // false
Number.isInteger('15') // false
Number.isInteger(true) // false
可在对象的值超出指定位数时将其转换为指数计数法。
function precise(x) {
return Number.parseFloat(x).toPrecision(4);
}
console.log(precise(123.456));
// expected output: "123.5"
console.log(precise(0.004));
// expected output: "0.004000"
console.log(precise('1.23e+5'));
// expected output: "1.230e+5"
for..in..
Object.keys(obj)
Object.getOwnPropertyNames(obj)
Object.getOwnPropertySymbols(obj)
Reflect.ownKeys(obj)
方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };
const returnedTarget = Object.assign(target, source);
console.log(target);
// expected output: Object { a: 1, b: 4, c: 5 }
console.log(returnedTarget);
// expected output: Object { a: 1, b: 4, c: 5 }
方法返回一个给定对象自身可枚举属性的键值对数组,其排列与使用 for...in 循环遍历该对象时返回的顺序一致(区别在于 for-in 循环也枚举原型链中的属性)
const object1 = { foo: 'bar', baz: 42 };
console.log(Object.entries(object1)[1]);
// expected output: Array ["baz", 42]
const object2 = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.entries(object2)[2]);
// expected output: Array ["2", "c"]
const result = Object.entries(object2).sort((a, b) => a - b);
console.log(Object.entries(result)[1]);
// expected output: Array ["1", Array ["1", "b"]]
当数组中元素是值类型,forEach绝对不会改变数组;当是引用类型,则可以改变数组
不支持链式调用
var arr1 = [
{name:'鸣人',age:16},
{name:'佐助',age:17}
];
var arr2 = [1,2,3];
arr1.forEach(item => {
item.age = item.age + 1}
);
//=> [{name:'鸣人',age:17},{name:'佐助',age:18}]
arr2.forEach(item => {
item = item * 2}
)
// => [1,2,3]
过滤数据,返回一个新数组
let newArr = [1,2,3,4,5].filter(item =>{
if(item > 3) return item
})
// => [4,5]
map即映射,原数组被映射成对应新数组
map方法不能使用于过滤
let arr = [1,2,3]
arr = arr.map(item=>item*2)
//1,4,9
let newArr = [1,2,3,4,5].map(item => { if(item > 3) return item })
// => [undefined, undefined, undefined, 4, 5]
判断大小
直接改变原始数组
[1,2,3,7,8,65,5,4].sort((a,b)=>{
return a - b;
})
let Users = [
{name:'鸣人',age:16},
{name:'卡卡西',age:28},
{name:'自来也',age:50},
{name:'佐助',age:17}
];
Users.sort((a,b)=> {
a.age - b.age
})
// => 鸣人、佐助、卡卡西、自来也
某一条件成立则返回true 类似于||
在空数组上调用固定返回 false
let result = [2,4,6,7].some(item=>item > 6)
//true
全部成立返回true 类似于&&
在空数组上调用固定返回 true
let result = [2,4,6,7].every(item=>item > 6)
//false
let result1 = [].every(item=>item)
//true
中断遍历,IE11不支持,兼容使用Lodash的_.findIndex()
返回当前中断索引
let ass4 = [1,5,6,8,5].findIndex(item=>{
return item > 6
})
//3
// 累加对象数组里的值
var initialValue = 0;
var sum = [{x: 1}, {x:2}, {x:3}].reduce(function (accumulator, currentValue) {
return accumulator + currentValue.x;
},initialValue)
// console.log(sum) // logs 6
// 将二维数组转化为一维
var flattened = [[0, 1], [2, 3], [4, 5]].reduce(
function(a, b) {
return a.concat(b);
},
[]
);
// flattened is [0, 1, 2, 3, 4, 5]
// 计算数组中每个元素出现的次数
var names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];
var countedNames = names.reduce(function (allNames, name) {
if (name in allNames) {
allNames[name]++;
}
else {
allNames[name] = 1;
}
return allNames;
}, {});
// countedNames is:
// { 'Alice': 2, 'Bob': 1, 'Tiff': 1, 'Bruce': 1 }
// 按属性对object分类
var people = [
{ name: 'Alice', age: 21 },
{ name: 'Max', age: 20 },
{ name: 'Jane', age: 20 }
];
function groupBy(objectArray, property) {
return objectArray.reduce(function (acc, obj) {
var key = obj[property];
if (!acc[key]) {
acc[key] = [];
}
acc[key].push(obj);
return acc;
}, {});
}
var groupedPeople = groupBy(people, 'age');
// groupedPeople is:
// {
// 20: [
// { name: 'Max', age: 20 },
// { name: 'Jane', age: 20 }
// ],
// 21: [{ name: 'Alice', age: 21 }]
// }
// 数组去重
let arr = [1,2,1,2,3,5,4,5,3,4,4,4,4];
let result = arr.sort().reduce((init, current) => {
if(init.length === 0 || init[init.length-1] !== current) {
init.push(current);
}
return init;
}, []);
// console.log(result); //[1,2,3,4,5]
// reduce兼容处理
if (!Array.prototype.reduce) {
Object.defineProperty(Array.prototype, 'reduce', {
value: function(callback /*, initialValue*/) {
if (this === null) {
throw new TypeError( 'Array.prototype.reduce ' +
'called on null or undefined' );
}
if (typeof callback !== 'function') {
throw new TypeError( callback +
' is not a function');
}
// 1. Let O be ? ToObject(this value).
var o = Object(this);
// 2. Let len be ? ToLength(? Get(O, "length")).
var len = o.length >>> 0;
// Steps 3, 4, 5, 6, 7
var k = 0;
var value;
if (arguments.length >= 2) {
value = arguments[1];
} else {
while (k < len && !(k in o)) {
k++;
}
// 3. If len is 0 and initialValue is not present,
// throw a TypeError exception.
if (k >= len) {
throw new TypeError( 'Reduce of empty array ' +
'with no initial value' );
}
value = o[k++];
}
// 8. Repeat, while k < len
while (k < len) {
// a. Let Pk be ! ToString(k).
// b. Let kPresent be ? HasProperty(O, Pk).
// c. If kPresent is true, then
// i. Let kValue be ? Get(O, Pk).
// ii. Let accumulator be ? Call(
// callbackfn, undefined,
// « accumulator, kValue, k, O »).
if (k in o) {
value = callback(value, o[k], k, o);
}
// d. Increase k by 1.
k++;
}
// 9. Return accumulator.
return value;
}
});
}
<div id="app">
{{message}}
<span @click=handleClick();>切换</span>
</div>
<script type="text/javascript">
var app=new Vue({
el:'#app',
data(){
return {
message:'hello Vue!',
x:0
}
},
methods:{
handleClick(){
this.x++;
if(this.x % 2 == 0){
this.message='hello vue1';
}else{
this.message='hello vue2';
}
}
}
})
</script>
v-if操作的是DOM元素
v-show操作的是属性
v-if: 判断是否加载,可以减轻服务器的压力,在需要时加载。
v-show:调整css dispaly属性,可以使客户端操作更加流畅
computed:计算属性将被混入到 Vue 实例中。所有 getter 和 setter 的 this 上下文自动地绑定为 Vue 实例。
注意如果你为一个计算属性使用了箭头函数,则 this 不会指向这个组件的实例,不过你仍然可以将其实例作为函数的第一个参数来访问。
watch:尽量减少箭头函数使用(this指向不同),一个对象,键是需要观察的表达式,值是对应回调函数。值也可以是方法名,或者包含选项的对象。Vue 实例将会在实例化时调用 $watch(),遍历 watch 对象的每一个属性。
//computed:
<div id="app">
<input type="text" v-model="firstName" />
<input type="text" v-model="lastName" />
{{fullName}}
</div>
<script>
new Vue({
el: '#app',
data: {
firstName: 'hello',
lastName: 'vue'
},
computed:{
fullName:function(){
return this.firstName+""+this.lastName;
}
}
});
var vm = new Vue({
data: { a: 1 },
computed: {
// 仅读取
aDouble: function () {
return this.a * 2
},
// 读取和设置
aPlus: {
get: function () {
return this.a + 1
},
set: function (v) {
this.a = v - 1
}
}
}
})
vm.aPlus // => 2
vm.aPlus = 3
vm.a // => 2
vm.aDouble // => 4
//watch:
<div id="app">
<input type="text" v-model="firstName" />
<input type="text" v-model="lastName" />
{{fullName}}
</div>
<script>
new Vue({
el: '#app',
data: {
firstName: 'hello',
lastName: 'vue',
fullName: 'hello vue'
},
watch: {
'firstName': function(newval, oldval) {
console.log(newval,oldval);
this.fullName = this.firstName + this.lastName;
},
'lastName': function(newval, oldval) {
console.log(newval,oldval);
this.fullName = this.firstName + this.lastName;
}
}
});
</script>
deep: true 深度watcher
immediate: true 该回调将会在侦听开始之后被立即调用
$mount作用为手动挂载,可用于延时挂载
app.$watch('temperature',function(newVal,oldVal){
console.log(newVal,oldVal);
})
new Vue({
data:{
},
...
}).$mount('#app')
<div id="app">
{{itemSort}}
</div>
<script type="text/javascript">
var app=new Vue({
el:'#app',
created(){
sortNumber=(a,b)=>{
return a-b
}
},
data(){
return {
items:[4,3,5,7,8,100,1,50,45,23],
}
},
methods:{ },
computed:{
itemSort:function(){
return this.items.sort(sortNumber);
},
}
})
</script>
<div id="app">
<ul>
<li v-for='item in sortItem'>
{{item.name}}-{{item.age}}
</li>
</ul>
</div>
<script type="text/javascript">
var app=new Vue({
el:'#app',
created(){
//数组对象方法排序:
sortByKey=(array,key)=>{
return array.sort(function(a,b){
var x=a[key];
var y=b[key];
return ((x<y)?-1:((x>y)?1:0));
});
}
},
data(){
return {
itemsArr:[
{name:'jili',age:22},
{name:'cheng',age:10},
{name:'lala',age:9}
]
}
},
methods:{
},
computed:{
sortItem:function(){
return sortByKey(this.itemsArr,'age');
}
}
})
</script>
//v-text可以简写为{{}},vue中有个指令叫做 v-once 可以通过v-once与v-text结合,实现仅执行一次性的插值
<span v-once>这个将不会随msg属性的改变而改变: {{ msg }}</span>
v-html用于输出html,它与v-text区别在于v-text输出的是纯文本,浏览器不会对其再进行html解析,但v-html会将其当html标签解析后输出。
需要注意的是:在生产环境中动态渲染HTML是非常危险的,因为容易导致XSS攻击。所以只能在可信的内容上使用v-html,永远不要在用户提交和可操作的网页上使用
v-model通常用于表单组件的绑定,例如input,select等。它与v-text的区别在于它实现的表单组件的双向绑定,如果用于表单控件以外标签是没有用的。
<div id="app">
<p>原始文本信息:{{message}}</p>
<h3>文本框</h3>
<p>v-model:<input type="text" v-model="message"></p>
</div>
<script>
var app=new Vue({
el:'#app',
data:{
message:'hello Vue!'
}
})
</script>
<!-- 多选按钮 -->
<div id="app">
<h3>多选绑定一个数组</h3>
<p>
<input type="checkbox" id="JSPang" value="JSPang" v-model="web_Names">
<label for="JSPang">JSPang</label><br/>
<input type="checkbox" id="Panda" value="Panda" v-model="web_Names">
<label for="JSPang">Panda</label><br/>
<input type="checkbox" id="PanPan" value="PanPan" v-model="web_Names">
<label for="JSPang">PanPan</label>
<p>{{web_Names}}</p>
</p>
</div>
<script>
var app=new Vue({
el:'#app',
data:{
web_Names:[]
}
})
</script>
<!-- 单选按钮 -->
<div id="app">
<h3>单选按钮绑定</h3>
<input type="radio" id="one" value="男" v-model="sex">
<label for="one">男</label>
<input type="radio" id="two" value="女" v-model="sex">
<label for="one">女</label>
<p>{{sex}}</p>
</div>
<script>
var app=new Vue({
el:'#app',
data:{
sex:'男'
}
})
</script>
1、直接绑定class样式
<div :class="className">1、绑定classA</div>
2、绑定classA并进行判断,在isOK为true时显示样式,在isOk为false时不显示样式。
<div :class="{classA:isOk}">2、绑定class中的判断</div>
3、绑定class中的数组
<div :class="[classA,classB]">3、绑定class中的数组</div>
4、绑定class中使用三元表达式判断
<div :class="isOk?classA:classB">4、绑定class中的三元表达式判断</div>
5、绑定style
<div :style="{color:red,fontSize:font}">5、绑定style</div>
6、用对象绑定style样式
<div :style="styleObject">6、用对象绑定style样式</div>
var app=new Vue({
el:'#app',
data:{
styleObject:{
fontSize:'24px',
color:'green'
}
}
})
在模板中跳过vue的编译,直接输出原始值。就是在标签中加入v-pre就不会输出vue中的data值了。
{{message}}这时并不会输出我们的message值,而是直接在网页中显示{{message}}
使用 v-cloak 防止页面加载时出现 vuejs 的变量名
<!-- 直接在css中添加 -->
[v-cloak] {
display: none;
}
CSS3淡入淡出效果
@-webkit-keyframes fadeInOut {
0% {
opacity: 1;
}
25% {
opacity: 0;
}
50% {
opacity: 0;
}
75% {
opacity: 1;
}
}
.anim_fade_image {
position: absolute;
-webkit-animation-name: fadeInOut;
-webkit-animation-timing-function: ease-in-out;
-webkit-animation-iteration-count: infinite;
-webkit-animation-duration: 5s;
-webkit-animation-direction: alternate;
}
<div class="anim_fade_image">hello world</div>
如果文本长度超过一行,它将被截断并以省略号结束。
<p class="truncate-text">If I exceed one line's width, I will be truncated.</p>
<style>
.truncate-text {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
width: 200px;
}
</style>
伪类
&:after {
content: '';
background: inherit;
filter: blur(0.4rem);
opacity: 0.7;
z-index: -1;
}
css中filter属性
1 grayscale灰度
2 sepia褐色(有种复古的旧照片感觉)
3 saturate饱和度
4 hue-rotate色相旋转
5 invert反色
6 opacity透明度
7 brightness亮度
8 contrast对比度
9 blur模糊
0 drop-shadow阴影
垂直对齐
.main{
position: relative;
top: 50%;
-webkit-transform: translateY(-50%);
-o-transform: translateY(-50%);
transform: translateY(-50%);
}
基于文件格式使用不同的样式
a[href^="http://"]{
padding-right: 20px;
background: url(external.gif) no-repeat center right;
}
/* emails */
a[href^="mailto:"]{
padding-right: 20px;
background: url(email.png) no-repeat center right;
}
/* pdfs */
a[href$=".pdf"]{
padding-right: 20px;
background: url(pdf.png) no-repeat center right;
}
背景渐变动画
button {
background-image: linear-gradient(#5187c4, #1c2f45);
background-size: auto 200%;
background-position: 0 100%;
transition: background-position 0.5s;
}
button:hover {
background-position: 0 0;
}
CSS:表格列宽自适用
//给td元素添加white-space: nowrap;能让文本正确的换行
td {
white-space: nowrap;
}
盒子阴影
.box-shadow {
background-color: #FF8020;
width: 160px;
height: 90px;
margin-top: -45px;
margin-left: -80px;
position: absolute;
top: 50%;
left: 50%;
}
.box-shadow:after {
content: "";
width: 150px;
height: 1px;
margin-top: 88px;
margin-left: -75px;
display: block;
position: absolute;
left: 50%;
z-index: -1;
-webkit-box-shadow: 0px 0px 8px 2px #000000;
-moz-box-shadow: 0px 0px 8px 2px #000000;
box-shadow: 0px 0px 8px 2px #000000;
}
包裹长文本
pre {
white-space: pre-line;
word-wrap: break-word;
}
制造模糊文本
.blurry-text {
color: transparent;
text-shadow: 0 0 5px rgba(0,0,0,0.5);
}
用CSS动画实现省略号动画
.loading:after {
overflow: hidden;
display: inline-block;
vertical-align: bottom;
animation: ellipsis 2s infinite;
content: "\2026"; /* ascii code for the ellipsis character */
}
@keyframes ellipsis {
from {
width: 2px;
}
to {
width: 15px;
}
}
样式重置
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
outline: none;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
html { height: 101%; }
body { font-size: 62.5%; line-height: 1; font-family: Arial, Tahoma, sans-serif; }
article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { display: block; }
ol, ul { list-style: none; }
blockquote, q { quotes: none; }
blockquote:before, blockquote:after, q:before, q:after { content: ''; content: none; }
strong { font-weight: bold; }
table { border-collapse: collapse; border-spacing: 0; }
img { border: 0; max-width: 100%; }
p { font-size: 1.2em; line-height: 1.0em; color: #333; }
/* reset */
html,body,h1,h2,h3,h4,h5,h6,div,dl,dt,dd,ul,ol,li,p,blockquote,pre,hr,figure,table,caption,th,td,form,fieldset,legend,input,button,textarea,menu{margin:0;padding:0;}
header,footer,section,article,aside,nav,hgroup,address,figure,figcaption,menu,details{display:block;}
table{border-collapse:collapse;border-spacing:0;}
caption,th{text-align:left;font-weight:normal;}
html,body,fieldset,img,iframe,abbr{border:0;}
i,cite,em,var,address,dfn{font-style:normal;}
[hidefocus],summary{outline:0;}
li{list-style:none;}
h1,h2,h3,h4,h5,h6,small{font-size:100%;}
sup,sub{font-size:83%;}
pre,code,kbd,samp{font-family:inherit;}
q:before,q:after{content:none;}
textarea{overflow:auto;resize:none;}
label,summary{cursor:default;}
a,button{cursor:pointer;}
h1,h2,h3,h4,h5,h6,em,strong,b{font-weight:bold;}
del,ins,u,s,a,a:hover{text-decoration:none;}
body,textarea,input,button,select,keygen,legend{font:12px/1.14 arial,\5b8b\4f53;color:#333;outline:0;}
body{background:#fff;}
a,a:hover{color:#333;}
典型的CSS清除浮动
.clearfix:after {
content: ".";
display: block;
clear: both;
visibility: hidden;
line-height: 0;
height: 0;
}
.clearfix { display: inline-block; }
html[xmlns] .clearfix { display: block; }
* html .clearfix { height: 1%; }
新版清除浮动
.clearfix:before, .container:after { content: ""; display: table; }
.clearfix:after { clear: both; }
/* IE 6/7 */
.clearfix { zoom: 1; }
跨浏览器的透明
.transparent {
filter: alpha(opacity=50); /* internet explorer */
-khtml-opacity: 0.5; /* khtml, old safari */
-moz-opacity: 0.5; /* mozilla, netscape */
opacity: 0.5; /* fx, safari, opera */
}
通用媒体查询
/* Smartphones (portrait and landscape) ----------- */
@media only screen and (min-device-width : 320px) and (max-device-width : 480px) {
/* Styles */
}
/* Smartphones (landscape) ----------- */
@media only screen and (min-width : 321px) {
/* Styles */
}
/* Smartphones (portrait) ----------- */
@media only screen and (max-width : 320px) {
/* Styles */
}
/* iPads (portrait and landscape) ----------- */
@media only screen and (min-device-width : 768px) and (max-device-width : 1024px) {
/* Styles */
}
/* iPads (landscape) ----------- */
@media only screen and (min-device-width : 768px) and (max-device-width : 1024px) and (orientation : landscape) {
/* Styles */
}
/* iPads (portrait) ----------- */
@media only screen and (min-device-width : 768px) and (max-device-width : 1024px) and (orientation : portrait) {
/* Styles */
}
/* Desktops and laptops ----------- */
@media only screen and (min-width : 1224px) {
/* Styles */
}
/* Large screens ----------- */
@media only screen and (min-width : 1824px) {
/* Styles */
}
/* iPhone 4 ----------- */
@media only screen and (-webkit-min-device-pixel-ratio:1.5), only screen and (min-device-pixel-ratio:1.5) {
/* Styles */
}
锚链接伪类
a:link { color: blue; }
a:visited { color: purple; }
a:hover { color: red; }
a:active { color: yellow; }
CSS3:全屏背景
html {
background: url('images/bg.jpg') no-repeat center center fixed;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
}
内容垂直居中
.container {
min-height: 6.5em;
display: table-cell;
vertical-align: middle;
}
CSS3渐变模板
#colorbox {
background: #629721;
background-image: -webkit-gradient(linear, left top, left bottom, from(#83b842), to(#629721));
background-image: -webkit-linear-gradient(top, #83b842, #629721);
background-image: -moz-linear-gradient(top, #83b842, #629721);
background-image: -ms-linear-gradient(top, #83b842, #629721);
background-image: -o-linear-gradient(top, #83b842, #629721);
background-image: linear-gradient(top, #83b842, #629721);
}
CSS3 斑马线
tbody tr:nth-child(odd) {
background-color: #ccc;
}
三角形列表项目符号
ul {
margin: 0.75em 0;
padding: 0 1em;
list-style: none;
}
li:before {
content: "";
border-color: transparent #111;
border-style: solid;
border-width: 0.35em 0 0.35em 0.45em;
display: block;
height: 0;
width: 0;
left: -1em;
top: 0.9em;
position: relative;
}
CSS3 列文本
#columns-3 {
text-align: justify;
-moz-column-count: 3;
-moz-column-gap: 12px;
-moz-column-rule: 1px solid #c4c8cc;
-webkit-column-count: 3;
-webkit-column-gap: 12px;
-webkit-column-rule: 1px solid #c4c8cc;
}
跨浏览器设置最小高度
#container {
min-height: 550px;
height: auto !important;
height: 550px;
}
CSS3 鲜艳的输入
input[type=text], textarea {
-webkit-transition: all 0.30s ease-in-out;
-moz-transition: all 0.30s ease-in-out;
-ms-transition: all 0.30s ease-in-out;
-o-transition: all 0.30s ease-in-out;
outline: none;
padding: 3px 0px 3px 3px;
margin: 5px 1px 3px 0px;
border: 1px solid #ddd;
}
input[type=text]:focus, textarea:focus {
box-shadow: 0 0 5px rgba(81, 203, 238, 1);
padding: 3px 0px 3px 3px;
margin: 5px 1px 3px 0px;
border: 1px solid rgba(81, 203, 238, 1);
}
强制换行
pre {
white-space: pre-wrap; /* css-3 */
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
white-space: -pre-wrap; /* Opera 4-6 */
white-space: -o-pre-wrap; /* Opera 7 */
word-wrap: break-word; /* Internet Explorer 5.5+ */
}
在可点击的项目上强制手型
a[href], input[type='submit'], input[type='image'], label[for], select, button, .pointer {
cursor: pointer;
}
CSS3对话气泡
.chat-bubble {
background-color: #ededed;
border: 2px solid #666;
font-size: 35px;
line-height: 1.3em;
margin: 10px auto;
padding: 10px;
position: relative;
text-align: center;
width: 300px;
-moz-border-radius: 20px;
-webkit-border-radius: 20px;
-moz-box-shadow: 0 0 5px #888;
-webkit-box-shadow: 0 0 5px #888;
font-family: 'Bangers', arial, serif;
}
.chat-bubble-arrow-border {
border-color: #666 transparent transparent transparent;
border-style: solid;
border-width: 20px;
height: 0;
width: 0;
position: absolute;
bottom: -42px;
left: 30px;
}
.chat-bubble-arrow {
border-color: #ededed transparent transparent transparent;
border-style: solid;
border-width: 20px;
height: 0;
width: 0;
position: absolute;
bottom: -39px;
left: 30px;
}
<div class="chat-bubble">
请查看以下状况:
1.是否有空格
2.字符长度
<span class="chat-bubble-arrow-border chat-bubble-arrow"></span>
</div>
H1-H5默认样式
h1,h2,h3,h4,h5{
color: #005a9c;
}
h1{
font-size: 2.6em;
line-height: 2.45em;
}
h2{
font-size: 2.1em;
line-height: 1.9em;
}
h3{
font-size: 1.8em;
line-height: 1.65em;
}
h4{
font-size: 1.65em;
line-height: 1.4em;
}
h5{
font-size: 1.4em;
line-height: 1.25em;
}
CSS悬浮提示文本
a {
border-bottom:1px solid #bbb;
color:#666;
display:inline-block;
position:relative;
text-decoration:none;
}
a:hover,
a:focus {
color:#36c;
}
a:active {
top:1px;
}
/* Tooltip styling */
a[data-tooltip]:after {
border-top: 8px solid #222;
border-top: 8px solid hsla(0,0%,0%,.85);
border-left: 8px solid transparent;
border-right: 8px solid transparent;
content: "";
display: none;
height: 0;
width: 0;
left: 25%;
position: absolute;
}
a[data-tooltip]:before {
background: #222;
background: hsla(0,0%,0%,.85);
color: #f6f6f6;
content: attr(data-tooltip);
display: none;
font-family: sans-serif;
font-size: 14px;
height: 32px;
left: 0;
line-height: 32px;
padding: 0 15px;
position: absolute;
text-shadow: 0 1px 1px hsla(0,0%,0%,1);
white-space: nowrap;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
-o-border-radius: 5px;
border-radius: 5px;
}
a[data-tooltip]:hover:after {
display: block;
top: -9px;
}
a[data-tooltip]:hover:before {
display: block;
top: -41px;
}
a[data-tooltip]:active:after {
top: -10px;
}
a[data-tooltip]:active:before {
top: -42px;
}
<a data-tooltip href="">百度搜索</a>
深灰色的圆形按钮
.graybtn {
-moz-box-shadow:inset 0px 1px 0px 0px #ffffff;
-webkit-box-shadow:inset 0px 1px 0px 0px #ffffff;
box-shadow:inset 0px 1px 0px 0px #ffffff;
background:-webkit-gradient( linear, left top, left bottom, color-stop(0.05, #ffffff), color-stop(1, #d1d1d1) );
background:-moz-linear-gradient( center top, #ffffff 5%, #d1d1d1 100% );
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#d1d1d1');
background-color:#ffffff;
-moz-border-radius:6px;
-webkit-border-radius:6px;
border-radius:6px;
border:1px solid #dcdcdc;
display:inline-block;
color:#777777;
font-family:arial;
font-size:15px;
font-weight:bold;
padding:6px 24px;
text-decoration:none;
text-shadow:1px 1px 0px #ffffff;
}
.graybtn:hover {
background:-webkit-gradient( linear, left top, left bottom, color-stop(0.05, #d1d1d1), color-stop(1, #ffffff) );
background:-moz-linear-gradient( center top, #d1d1d1 5%, #ffffff 100% );
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#d1d1d1', endColorstr='#ffffff');
background-color:#d1d1d1;
}
.graybtn:active {
position:relative;
top:1px;
}
在可打印的网页中显示URLs
@media print {
a:after {
content: " [" attr(href) "] ";
}
}
CSS3 圆点图案
body {
background: radial-gradient(circle, white 10%, transparent 10%),
radial-gradient(circle, white 10%, black 10%) 50px 50px;
background-size: 100px 100px;
}
CSS font属性缩写
p {
font: italic small-caps bold 1.2em/1.0em Arial, Tahoma, Helvetica;
}
论文页面的卷曲效果
ul.box {
position: relative;
z-index: 1; /* prevent shadows falling behind containers with backgrounds */
overflow: hidden;
list-style: none;
margin: 0;
padding: 0;
}
ul.box li {
position: relative;
float: left;
width: 250px;
height: 150px;
padding: 0;
border: 1px solid #efefef;
margin: 0 30px 30px 0;
background: #fff;
-webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.27), 0 0 40px rgba(0, 0, 0, 0.06) inset;
-moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.27), 0 0 40px rgba(0, 0, 0, 0.06) inset;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.27), 0 0 40px rgba(0, 0, 0, 0.06) inset;
}
ul.box li:before,
ul.box li:after {
content: '';
z-index: -1;
position: absolute;
left: 10px;
bottom: 10px;
width: 70%;
max-width: 300px; /* avoid rotation causing ugly appearance at large container widths */
max-height: 100px;
height: 55%;
-webkit-box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);
-moz-box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);
-webkit-transform: skew(-15deg) rotate(-6deg);
-moz-transform: skew(-15deg) rotate(-6deg);
-ms-transform: skew(-15deg) rotate(-6deg);
-o-transform: skew(-15deg) rotate(-6deg);
transform: skew(-15deg) rotate(-6deg);
}
ul.box li:after {
left: auto;
right: 10px;
-webkit-transform: skew(15deg) rotate(6deg);
-moz-transform: skew(15deg) rotate(6deg);
-ms-transform: skew(15deg) rotate(6deg);
-o-transform: skew(15deg) rotate(6deg);
transform: skew(15deg) rotate(6deg);
}
鲜艳的锚链接
a {
color: #00e;
}
a:visited {
color: #551a8b;
}
a:hover {
color: #06e;
}
a:focus {
outline: thin dotted;
}
a:hover, a:active {
outline: 0;
}
a, a:visited, a:active {
text-decoration: none;
color: #fff;
-webkit-transition: all .3s ease-in-out;
}
a:hover, .glow {
color: #ff0;
text-shadow: 0 0 10px #ff0;
}
禁用移动Webkit的选择高亮
body {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
css3实现头像变灰
-webkit-filter: grayscale(100%);
-webkit-filter: grayscale(1);
filter: grayscale(100%);
filter: gray;
图片与文字在同意div中中间对齐
<div class="image-text">
<img src="xxxx"/>
<p>文字<p/>
</div>
.image-text {
display:inline-block;
vertical-align:middle;
}
实现水平和垂直翻转
transform: scale(-1, 1);//水平翻转
transform: scale(1, -1);//垂直翻转
三角符号绘制
···
.icon-arrow-bottom {
width: 0;
height: 0;
border: 100px solid #000;
border-color: #000 transparent transparent transparent;
}
.icon-arrow-top {
width: 0;
height: 0;
border: 100px solid #000;
border-color: transparent transparent #000 transparent;
}
···
代码说明:
<div id="app">
<div v-jili="color" id="demo">
{{num}}
</div>
<div>
<button @click="add">Add</button>
</div>
</div>
<script>
Vue.directive('jili',function(el,binding,vnode){
console.log(el,binding,vnode); //el 当前元素 binding 包含指令的很多信息。
el.style='color:'+binding.value;
});
var app=new Vue({
el:'#app',
data:{
num:10,
color:'green'
},
methods:{
add:function(){
this.num++;
}
}
})
</script>
1.bind 被绑定
2.inserted 绑定到节点
3.update 组件更新
4.componentUpdated 组件更新完成
5.unbind 解绑
扩展实例构造器,意为当有多个地方使用同一个标签路径,我们在实例上封装一个自动调用的方法,方法,并挂载到自定义元素上
var authorExtend = Vue.extend({
template:"<p><a :href='authorUrl'>{{authorName}}</a></p>",
data:function(){
return{
authorName:'度娘',
authorUrl:'http://www.baidu.com'
}
}
});
//new authorExtend().$mount('元素')
Vue.set 的作用就是在构造器外部操作构造器内部的数据、属性或者方法。
由于Javascript的限制,Vue不能自动检测以下变动的数组。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="../assets/js/vue.js"></script>
<title>Vue.set 全局操作</title>
</head>
<body>
<h1>Vue.set 全局操作</h1>
<hr>
<div id="app">
<ul>
<li v-for=" aa in arr">{{aa}}</li>
</ul>
</div>
<button onclick="add()">外部添加</button>
<script type="text/javascript">
function add(){
console.log("我已经执行了");
app.arr[1]='ddd'; //不能变动
//Vue.set(app.arr,1,'ddd');
}
var outData={
arr:['aaa','bbb','ccc']
};
var app=new Vue({
el:'#app',
data:outData
})
</script>
</body>
</html>
preview(1)
function preview(oper){
if (oper < 10){
bdhtml=window.document.body.innerHTML;//获取当前页的html代码
sprnstr="<!--startprint"+oper+"-->";//设置打印开始区域
eprnstr="<!--endprint"+oper+"-->";//设置打印结束区域
prnhtml=bdhtml.substring(bdhtml.indexOf(sprnstr)+18); //从开始代码向后取html
prnhtml=prnhtml.substring(0,prnhtml.indexOf(eprnstr));//从结束代码向前取html
window.document.body.innerHTML=prnhtml;
window.print();
window.document.body.innerHTML=bdhtml;
} else {
window.print();
}
}
/**
//data数据
let arr = [
[
["1-7", "2-6"], "4-6", [
["2-0", "1-4"],
["3-9"], "4-5"
]
]
];
//递归实现
function flat(arr) {
const result = [];
function _flat(arr) {
arr.forEach(element => {
if (Array.isArray(element)) {
_flat(element);
} else {
result.push(element);
}
})
}
_flat(arr)
return result;
}
console.log(flat(arr))
/**
<input type="text" name="" id="demo" onkeyup="clearNoNum(this)"/>
//数字输入匹配
function clearNoNum(obj) {
obj.value = obj.value.replace(/[^\d.]/g, ""); //清除“数字”和“.”以外的字符
obj.value = obj.value.replace(/\.{2,}/g, "."); //只保留第一个. 清除多余的
obj.value = obj.value.replace(".", "$#$").replace(/\./g, "").replace("$#$", ".");
obj.value = obj.value.replace(/^\./g, ""); //验证第一个字符是数字而不是.
obj.value = obj.value.replace(/^(\-)*(\d+)\.(\d\d).*$/, "$1$2.$3"); //只能输入两个小数
if (obj.value.indexOf(".") < 0 && obj.value != "") {
//以上已经过滤,此处控制的是如果没有小数点,首位不能为类似于 01、02的金额
obj.value = parseFloat(obj.value);
}
}
//空格处理
function clearNoNum(obj) {
obj.value = obj.value.replace(/\s/g, "");
}
/**
* @author
* @description:深拷贝
**/
//递归
function deepClone(obj) {
let result = Array.isArray(obj) ? [] : {};
if (obj && typeof obj === 'object') {
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
if (obj[key] && typeof obj[key] === 'object') {
result[key] = deepClone(obj[key])
} else {
result[key] = obj[key]
}
}
}
}
return result;
}
//1.JSON.parse与JSON.stringify
/2.通过jQuery的extend方法实现深拷贝
var array = [1,2,3,4];
var newArray = $.extend(true,[],array);
//3.Object.assign()拷贝
//当对象中只有一级属性,没有二级属性的时候,此方法为深拷贝,但是对象中有对象的时候,此方法,在二级属性以后就是浅拷贝
/**
* @author
* @description:bind封装
**/
Function.prototype.bind2 = function (context) {
var self = this;
return function () {
self.apply(context);
}
}
/**
* @author
* @description:promise
**/
class Promise {
callbacks = [];
failbacks = [];
constructor(fn) {
fn(this.resolve.bind(this), this.reject.bind(this));
}
resolve(res) {
if (this.callbacks.length > 0) this.callbacks.shift()(res, this.resolve.bind(this), this.reject.bind(this));
}
reject(res) {
this.callbacks = [];
if (this.failbacks.length > 0) this.failbacks.shift()(res, this.resolve.bind(this), this.reject.bind(this));
}
catch (fn) {
this.failbacks.push(fn);
}
then(fn) {
this.callbacks.push(fn);
return this;
}
}
/**
* @author
* @description:new封装
**/
function create() {
// 创建一个空的对象
let obj = new Object()
// 获得构造函数
let Con = [].shift.call(arguments)
// 链接到原型
obj.__proto__ = Con.prototype
// 绑定 this,执行构造函数
let result = Con.apply(obj, arguments)
// 确保 new 出来的是个对象
return typeof result === 'object' ? result : obj
}
/**
* @author
* @description:extends实现
**/
//子类 extends 父类
Function.prototype.extends = function(func, options){
for(var key in func.prototype){
this.prototype[key] = func.prototype[key];
}
for(var name in options){
this.prototype[name] = options[name];
}
}
/**
* @author
* @description:高级递归排序
**/
function quickSort(arr) {
if(arr.length <= 1) {
return arr; //递归出口
}
var left = [],
right = [],
current = arr.splice(0,1);
for(let i = 0; i < arr.length; i++) {
if(arr[i] < current) {
left.push(arr[i]) //放在左边
} else {
right.push(arr[i]) //放在右边
}
}
return quickSort(left).concat(current,quickSort(right));
}
前言
技术栈:jQuery+bootstrap
语义::contains 选择器选取包含指定字符串的元素。 语法:$(":contains(text)")
<div role="group" style="display:inline">
<input type="text" id="belongcompanyid" placeholder="search name" autocomplete="off">
<div role="form" style="overflow-y:hidden;">
<div id="belongcompanyList" style="max-height: 297px;overflow-y: auto;overflow-x: hidden;display: none;">
</div>
</div>
</div>
systmeCustomer();
function systmeCustomer() {
$.ajax({
type: "get",
url: "./index.json",
data: {},
async: false,
dataType: "json",
success: function(data) {
console.log(data);
if (data.result_code == "0") {
$("#belongcompanyList").empty();
var datalist = data.data_list;
var auditHtml = "";
for (var i = 0; i < 26; i++) {
var ch = String.fromCharCode(65 + i);
var auditHtml1 = "";
var auditHtml2 = "";
auditHtml1 +=
'<div class="row">' +
'<div class="col-lg-2 col-md-2 col-sm-2 col-xs-2" style="text-align: right;float:left;">' +
ch +
"</div>" +
'<div class="col-lg-10 col-md-10 col-sm-12 col-xs-12 PList" style="border-left:1px solid #fff">';
for (var j = 0; j < datalist.length; j++) {
if (datalist[j].py.toUpperCase() == ch) {
auditHtml2 +=
"<p belong_company_id=" +
datalist[j].company_id +
' class="billIdClick">' +
datalist[j].company_name +
"</p>";
}
}
if (auditHtml2 == "") {
auditHtml1 = "";
} else {
auditHtml1 += auditHtml2;
}
auditHtml += auditHtml1;
auditHtml += "</div>" + "</div>";
}
$("#belongcompanyList").append(auditHtml);
} else {
alert(data.result_msg);
}
}
});
}
//模糊搜索
$("#belongcompanyid").blur(function() {
var thisval = $(this).val();
$("#belongcompanyList>div").show().children("div p").show();
$("#belongcompanyList p").show();
if (thisval.length > 0) {
$('#belongcompanyList').css('display','block');
$("#belongcompanyList>div>div>p").hide().filter(":contains('" + thisval + "')").show();
var p_list = $("#belongcompanyList>div>div.PList");
for (var i = 0; i < p_list.length; i++) {
if ($(p_list[i]).children("p:visible").length == "0") {
$(p_list[i]).parent("div").hide();
}
}
}
}).keyup(function() {
$(this).triggerHandler("blur");
}).focus(function() {
$(this).triggerHandler("blur");
}).change(function() {
$(this).triggerHandler("blur");
});
$("#belongcompanyList").on("click", ".billIdClick", function() {
var custom_name = $(this).html();
$("#belongcompanyid").val(custom_name);
$('#belongcompanyList').hide();
$(".custom-search").removeClass("open");
});
// json数据
{"result_msg":"成功","data_list":[{"company_id":1,"crm_company_id":177857,"company_name":"华为技术有限公司","py":"H"},{"company_id":3,"crm_company_id":152,"company_name":"北京市北京饭店","py":"B"},{"company_id":4,"crm_company_id":185139,"company_name":"商路延","py":"S"},{"company_id":5,"crm_company_id":18552,"company_name":"首约","py":"S"},{"company_id":1251,"crm_company_id":337837,"company_name":"河北马利食品有限公司","py":"H"},{"company_id":1252,"crm_company_id":300148,"company_name":"苏州绿城玫瑰园房地产开发有限公司","py":"S"},{"company_id":1253,"crm_company_id":300965,"company_name":"常州安必克阀门有限公司","py":"C"},{"company_id":1254,"crm_company_id":301268,"company_name":"北京京环华胜信息科技有限公司","py":"B"},{"company_id":1256,"crm_company_id":301065,"company_name":"隆基绿能科技股份有限公司","py":"L"},{"company_id":1527,"crm_company_id":311033,"company_name":"**科协青少年科技中心","py":"Z"},{"company_id":1528,"crm_company_id":311195,"company_name":"友利银行(**)有限公司上海吴中路支行bc","py":"Y"},{"company_id":1529,"crm_company_id":3112844,"company_name":"湖北视觉时代文化传媒有限公司","py":"H"}],"result_code":0}
new Array(1,2,3,4,5).slice(1,5) => 2,3,4,5
// 反转数组 类似reverse
var arr = new Array(1,2,3,4,5,6)
[...arr].map(arr.pop,arr)
new Array(1,2,3,4,5).some(item => {
return item > 4
})
// true
//由小到大
new Array(22,555,444,1111,478).sort((a, b) => {
return a - b
})
// splice与slice区别
array.slice(start,end) 1.可以从数组中提取指定元素 2.该方法不会改变元素数组,而是将截取的元素封装到一个新数组返回 3.类似于substring
var arr = [3,4,5,6,7]
arr.slice(1,-2) => 4,5 -2代指倒数第二个,从0算起
array.splice(start[, deleteCount[, item1[, item2[, ...]]]])
// 第一参数截取初始位置
// 第二参数截取元素个数
// 在删除位置参数的元素
1.可用于删除数组 2.影响原数组,返回删除的元素
var arr = [3,4,5,6]
arr.splice(0,1,34,56)
console.log(arr) //=> 34,56,4,5,6
arr.splice(2,0,55)
console.log(arr) //=> 3,4,55,5,6
'cat'.charAt(1) //=>a
'cat'.charCodeAt(1) //=>97
'cat'.includes('t') //=> true
首个
/最后
被发现的给定值的索引值,如果没有找到则返回-1。'catccc'.indexOf('c') //=> 0
'cataaa'.indexOf('b') //=>-1
'cataaa'.lastIndexOf('a') //=>5
repeat 返回指定重复次数的由元素组成的字符串对象
'a'.repeat(4) //=>'aaaa'
'AA'.toLowerCase() //=>'aa'
'aa'.toUpperCase() //=>'AA'
替换
'ccbb aa'.replace(/aa/,'bb') //=> 'ccbb bb'
null与undefinded不能转换
实行的是浅拷贝
const source1 = {a: 1, b: 2}
const source2 = {b: 3, c: 2}
Object.assign(source1, source2) //=> {a: 1, b: 3, c: 2}
//特殊情况
Object.assign({a: 1}, undefined) === {a: 1} //=> true null也一致
Object.assign([1], [4]) //=>[4]
//浅拷贝
const obj1 = {a: {b: 1}};
const obj2 = Object.assign({}, obj1);
obj1.a.b = 2
obj2.a.b //=> 2
//创建一个可写的,可枚举的,可配置的属性p
//第一参数原型对象,第二参数本身实例
const obj2 = Object.create({}, {
'p': {
value: 2, // 属性值
writable: true, // 是否可以重写值
enumerable: true, //是否可枚举
configurable: true //是否可以修改以上几项配置
},
'a': {
value: 3,
writable: true,
enumerable: true,
configurable: true
}
});
obj2 //=> {p: 2, a: 3}
// Object.defineProperty(obj, prop, descriptor)
/**
*参数obj表示的是需要定义属性的那个对象
*参数prop表示需要被定义或者修改的属性名
*参数descriptor就是我们定义的那个属性prop的描述
*
* 要求就是你要给dreamapple添加一个fullName属性
* dreamapple的firstName或者lastName发生变化的时候,fullName也要随之变化;而且当我们设置了fullName的值的时候,
* 那么相应的它的firstName和lastName也随之发生变化; 那么我们应该怎么做呢?
**/
var dream = {
firstName: 'dream',
lastName: 'apple'
}
Object.defineProperty(dream,'fullName',{
enumerable: true, //是否可枚举
get () {
return this.firstName +' '+ this.lastName
},
set (fullName) {
const name = fullName.trim().split(' ')
this.firstName = name[0]
this.lastName = name[1]
}
})
dream.firstName = 'lala'
dream.lastName = 'haha'
console.log(dream.fullName)
// dream.fullName = 'apple aaaaaadd'
// console.log(dream.firstName,dream.lastName)
[key, value] 数组
。//类似for..in 不兼容
const obj = { foo: 'bar', baz: 42 }
Object.entries(obj) //=>[ ["foo", "bar"], ["baz", 42] ]
Object.is(NaN,NaN) //=>true
Object.is('1',1) //=>false
let arr = ["a", "b", "c"];
let obj = { foo: "bar", baz: 42 };
Object.keys(arr) // ['0', '1', '2']
Object.keys(obj) // ["foo","baz"]
let arr = ["a", "b", "c"];
let obj = { foo: "bar", baz: 42 };
Object.keys(arr) // ['a', 'b', 'c']
Object.keys(obj) // ["bar","42 "]
Number('10a') //=>NaN
isNaN(undefined) //=> true
isNaN(1) //=> false
isNaN == isNaN //=> false
取整,第二个参数为进制(没写的话默认十进制)
parseInt(2.45678); //2
parseInt(10,8) // 8
取浮点数
parseFloat("010.01aa") //=> 10.01
保留小数位
圆周率数值
向下取整
向上取整
两个参数;次方
Math.pow(2,3) //8 2的3次方
平方根
Math.sqrt(9) //=> 3
Math.sqrt(-9) //=> NaN
取绝对值
取最大值
取最小值
四舍五入
取0-1之间的随机数
// 取0-10之间的随机数
Math.round(Math.random()*10)
Number.MAX_SAFE_DIGITS = Number.MAX_SAFE_INTEGER.toString().length-2 //14
Number.prototype.digits = function(){
let result = (this.valueOf().toString().split('.')[1] || '').length
return result > Number.MAX_SAFE_DIGITS ? Number.MAX_SAFE_DIGITS : result
}
Number.prototype.add = function(i=0){
if (typeof i !== 'number') {
throw new Error('请输入正确的数字');
}
const v = this.valueOf();
const thisDigits = this.digits();
const iDigits = i.digits();
console.log(thisDigits,iDigits)
const baseNum = Math.pow(10, Math.max(thisDigits, iDigits));
const result = (v * baseNum + i * baseNum) / baseNum;
if(result>0){ return result > Number.MAX_SAFE_INTEGER ? Number.MAX_SAFE_INTEGER : result }
else{ return result < Number.MIN_SAFE_INTEGER ? Number.MIN_SAFE_INTEGER : result }
}
Number.prototype.minus = function(i=0){
if (typeof i !== 'number') {
throw new Error('请输入正确的数字');
}
const v = this.valueOf();
const thisDigits = this.digits();
const iDigits = i.digits();
const baseNum = Math.pow(10, Math.max(thisDigits, iDigits));
const result = (v * baseNum - i * baseNum) / baseNum;
if(result>0){ return result > Number.MAX_SAFE_INTEGER ? Number.MAX_SAFE_INTEGER : result }
else{ return result < Number.MIN_SAFE_INTEGER ? Number.MIN_SAFE_INTEGER : result }
}
console.log((0.001).add(0.2))
API设计上简单,语法简单,学习成本低
构建方面不包含路由和ajax功能,使用vuex, vue-router
指令(dom)和组件(视图,数据,逻辑)处理清晰
性能好,容易优化
基于依赖追踪的观察系统,并且异步队列更新
独立触发
v-model 实时渲染
适用于:模板和渲染函数的弹性选择
简单的语法及项目搭建
更快的渲染速度和更小的体积
利用jsx创建虚拟dom
是一种在内存中描述dom数状态的数据结构
函数式的方法描述视图
使用虚拟dom作为模板
程序片段
不好控制dom
服务端渲染:react的虚拟dom的生成可以在任何支持js的环境生成的,所以可以在node环境生成,直接转为string,然后插入到html文件中输出浏览器便可
适用于:大型应用和更好的可测试性;同时适用于web端和原生app;更大的生态圈
React伟大之处就在于,提出了Virtual Dom这种新颖的思路,并且这种思路衍生出了React Native,有可能会统一Web/Native开发。在性能方面,由于运用了Virtual Dom技术,Reactjs只在调用setState的时候会更新dom,而且还是先更新Virtual Dom,然后和实际Dom比较,最后再更新实际Dom。这个过程比起Angularjs的bind方式来说,一是更新dom的次数少,二是更新dom的内容少,速度肯定快
ReactJS更关注UI的组件化,和数据的单向更新,提出了FLUX架构的新概念,现在React可以直接用Js ES6语法了,然后通过webpack编译成浏览器兼容的ES5,开发效率上有些优势. React Native生成的App不是运行在WebView上,而是系统原生的UI,React通过jsx生成系统原生的UI,iOS和Android的React UI组件还是比较相似的,大量代码可以复用
维护UI的状态,Angular 里面使用的是 $scope,在 React 里面使用的是 this.setState。 而 React 的好处在于,它更简单直观。所有的状态改变都只有唯一一个入口 this.setState(),同构的JavaScript 单页面JS应用程序的最大缺陷在于对搜索引擎的索引有很大限制。React对此有了解决方案。
React可以在服务器上预渲染应用再发送到客户端。它可以从预渲染的静态内容中恢复一样的记录到动态应用程序中。 因为搜索引擎的爬虫程序依赖的是服务端响应而不是JavaScript的执行,预渲染你的应用有助于搜索引擎优化。
虚拟dom实现快速渲染
轻量级响应式组件
服务端渲染易于集成路由工具,打包工具及状态管理工具
//判定方法
function run(input) {
if (typeof input !== 'string') return false;
return input.split('').reverse().join('') === input;
}
.wraper {
position: relative;
.box {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
}
.wraper {
.box {
display: flex;
justify-content:center;
align-items: center;
height: 100px;
}
}
.wraper {
display: table;
.box {
display: table-cell;
vertical-align: middle;
}
}
Reflect.apply(target, thisArg, args)
Reflect.construct(target, args)
Reflect.get(target, name, receiver)
Reflect.set(target, name, value, receiver)
Reflect.defineProperty(target, name, desc)
Reflect.deleteProperty(target, name)
Reflect.has(target, name)
Reflect.ownKeys(target)
Reflect.isExtensible(target)
Reflect.preventExtensions(target)
Reflect.getOwnPropertyDescriptor(target, name)
Reflect.getPrototypeOf(target)
Reflect.setPrototypeOf(target, prototype)
var obj = new Proxy({}, {
get: function (target, key, receiver) {
console.log(`proxy get ${key}`)
return Reflect.get(target, key, receiver)
},
set: function (target, key, value, receiver) {
console.log(`proxy set ${key}`)
return Reflect.set(target, key, value, receiver)
}
})
实现Storage,使得该对象为单例,并对localStorage进行封装设置值setItem(key,value)和getItem(key)
var instance = null;
class Storage {
static getInstance() {
if (!instance) {
instance = new Storage();
}
return instance;
}
setItem = (key, value) => localStorage.setItem(key, value),
getItem = key => localStorage.getItem(key)
}
1.JSX做表达式判断时候,需要强转为boolean类型,如:
render() {
const b = 0;
return <div>
{
!!b && <div>这是一段文本</div>
}
</div>
}
//如果不使用 !!b 进行强转数据类型,会在页面里面输出 0。
2.尽量不要在 componentWillReviceProps 里使用 setState,如果一定要使用,那么需要判断结束条件,不然会出现无限重渲染,导致页面崩溃。
3.给组件添加ref时候,尽量不要使用匿名函数,因为当组件更新的时候,匿名函数会被当做新的prop处理
首先,js是单线程的,主要的任务是处理用户的交互,而用户的交互无非就是响应DOM的增删改,使用事件队列的形式,一次事件循环只处理一个事件响应,使得脚本执行相对连续,所以有了事件队列,用来储存待执行的事件,那么事件队列的事件从哪里被push进来的呢。那就是另外一个线程叫事件触发线程做的事情了,他的作用主要是在定时触发器线程、异步HTTP请求线程满足特定条件下的回调函数push到事件队列中,等待js引擎空闲的时候去执行,当然js引擎执行过程中有优先级之分,首先js引擎在一次事件循环中,会先执行js线程的主任务,然后会去查找是否有微任务microtask(promise),如果有那就优先执行微任务,如果没有,在去查找宏任务macrotask(setTimeout、setInterval)进行执行。
事件流分为两种,捕获事件流和冒泡事件流。
捕获事件流从根节点开始执行,一直往子节点查找执行,直到查找执行到目标节点。
冒泡事件流从目标节点开始执行,一直往父节点冒泡查找执行,直到查到到根节点。
事件流分为三个阶段,一个是捕获节点,一个是处于目标节点阶段,一个是冒泡阶段。
首先说说为什么要使用Virturl DOM,因为操作真实DOM的耗费的性能代价太高,所以react内部使用js实现了一套dom结构,在每次操作在和真实dom之前,使用实现好的diff算法,对虚拟dom进行比较,递归找出有变化的dom节点,然后对其进行更新操作。为了实现虚拟DOM,我们需要把每一种节点类型抽象成对象,每一种节点类型有自己的属性,也就是prop,每次进行diff的时候,react会先比较该节点类型,假如节点类型不一样,那么react会直接删除该节点,然后直接创建新的节点插入到其中,假如节点类型一样,那么会比较prop是否有更新,假如有prop不一样,那么react会判定该节点有更新,那么重渲染该节点,然后在对其子节点进行比较,一层一层往下,直到没有子节点。
function MyPromise(executor){
var that = this
this.status = 'pending' // 当前状态
this.data = undefined
this.onResolvedCallback = [] // Promise resolve时的回调函数集,因为在Promise结束之前有可能有多个回调添加到它上面
this.onRejectedCallback = [] // Promise reject时的回调函数集,因为在Promise结束之前有可能有多个回调添加到它上面
// 更改状态 => 绑定数据 => 执行回调函数集
function resolve(value){
if(that.status === 'pending'){
that.status = 'resolved'
that.data = value
for(var i = 0; i < that.onResolvedCallback.length; ++i){
that.onResolvedCallback[i](value)
}
}
}
function reject(reason){
if(that.status === 'pending'){
that.status = 'rejected'
that.data = reason
for(var i = 0; i < that.onResolvedCallback.length; ++i){
that.onRejectedCallback[i](reason)
}
}
}
try{
executor(resolve, reject) // resolve, reject两个函数可以在外部传入的函数(executor)中调用
} catch(e) { // 考虑到执行过程可能有错
reject(e)
}
}
// 标准是没有catch方法的,实现了then,就实现了catch
// then/catch 均要返回一个新的Promise实例
MyPromise.prototype.then = function(onResolved, onRejected){
var that = this
var promise2
// 值穿透
onResolved = typeof onResolved === 'function' ? onResolved : function(v){ return v }
onRejected = typeof onRejected === 'function' ? onRejected : function(r){ return r }
if(that.status === 'resolved'){
return promise2 = new MyPromise(function(resolve, reject){
try{
var x = onResolved(that.data)
if(x instanceof MyPromise){ // 如果onResolved的返回值是一个Promise对象,直接取它的结果做为promise2的结果
x.then(resolve, reject)
}
resolve(x) // 否则,以它的返回值做为promise2的结果
} catch(e) {
reject(e) // 如果出错,以捕获到的错误做为promise2的结果
}
})
}
if(that.status === 'rejected'){
return promise2 = new MyPromise(function(resolve, reject){
try{
var x = onRejected(that.data)
if(x instanceof MyPromise){
x.then(resolve, reject)
}
} catch(e) {
reject(e)
}
})
}
if(that.status === 'pending'){
return promise2 = new MyPromise(function(resolve, reject){
self.onResolvedCallback.push(function(reason){
try{
var x = onResolved(that.data)
if(x instanceof MyPromise){
x.then(resolve, reject)
}
} catch(e) {
reject(e)
}
})
self.onRejectedCallback.push(function(value){
try{
var x = onRejected(that.data)
if(x instanceof MyPromise){
x.then(resolve, reject)
}
} catch(e) {
reject(e)
}
})
})
}
}
MyPromise.prototype.catch = function(onRejected){
return this.then(null, onRejected)
}
// 以下是简单的测试样例:
new MyPromise(resolve => resolve(8)).then(value => {
console.log(value)
})
css在加载过程中不会影响到DOM树的生成,但是会影响到Render树的生成,进而影响到layout,所以一般来说,style的link标签需要尽量放在head里面,因为在解析DOM树的时候是自上而下的,而css样式又是通过异步加载的,这样的话,解析DOM树下的body节点和加载css样式能尽可能的并行,加快Render树的生成的速度。
js脚本应该放在底部,原因在于js线程与GUI渲染线程是互斥的关系,如果js放在首部,当下载执行js的时候,会影响渲染行程绘制页面,js的作用主要是处理交互,而交互必须得先让页面呈现才能进行,所以为了保证用户体验,尽量让页面先绘制出来。
浏览器缓存机制有两种,一种为强缓存,一种为协商缓存。
对于强缓存,浏览器在第一次请求的时候,会直接下载资源,然后缓存在本地,第二次请求的时候,直接使用缓存。
对于协商缓存,第一次请求缓存且保存缓存标识与时间,重复请求向服务器发送缓存标识和最后缓存时间,服务端进行校验,如果失效则使用缓存。
强缓存方案
Exprires:服务端的响应头,第一次请求的时候,告诉客户端,该资源什么时候会过期。Exprires的缺陷是必须保证服务端时间和客户端时间严格同步。
Cache-control:max-age,表示该资源多少时间后过期,解决了客户端和服务端时间必须同步的问题,
协商缓存方案
If-None-Match/ETag:缓存标识,对比缓存时使用它来标识一个缓存,第一次请求的时候,服务端会返回该标识给客户端,客户端在第二次请求的时候会带上该标识与服务端进行对比并返回If-None-Match标识是否表示匹配。
Last-modified/If-Modified-Since:第一次请求的时候服务端返回Last-modified表明请求的资源上次的修改时间,第二次请求的时候客户端带上请求头If-Modified-Since,表示资源上次的修改时间,服务端拿到这两个字段进行对比。
共同点:都是有效的图形工具,对于数据较小的情况下,都很又高的性能,它们都使用 JavaScript 和 HTML;它们都遵守万维网联合会 (W3C) 标准。
svg优点:
矢量图,不依赖于像素,无限放大后不会失真。
以dom的形式表示,事件绑定由浏览器直接分发到节点上。
svg缺点:
dom形式,涉及到动画时候需要更新dom,性能较低。
canvas优点:
定制型更强,可以绘制绘制自己想要的东西。
非dom结构形式,用JavaScript进行绘制,涉及到动画性能较高。
canvas缺点:
事件分发由canvas处理,绘制的内容的事件需要自己做处理。
依赖于像素,无法高效保真,画布较大时候性能较低
1、输入地址
2、浏览器查找域名的 IP 地址(域名解析)
3、浏览器向 web 服务器发送一个 HTTP 请求
4、服务器的永久重定向响应
5、浏览器跟踪重定向地址
6、服务器处理请求
7、服务器返回一个 HTTP 响应
8、浏览器显示 HTML
9、浏览器发送请求获取嵌入在 HTML 中的资源(如CSS、JS、图片、音频、视频等)
const obj = {
selector: {
to: {
toutiao: "FE Coder"
}
},
target: [1, 2, {
name: 'byted'
}]
};
get(obj, 'selector.to.toutiao', 'target[0]', 'target[2].name')
//结果:FE Coder 1 byted
思路一:
function get(data, ...args) {
const reg = /\[[0-9]+\]/gi;
return args.map((item) => {
const paths = item.split('.');
let res = data;
paths.map((path) => {
if (reg.test(path)) {
const match = path.match(reg)[0];
console.log(match)
// 将target[0]里的target储存到cmd里
const cmd = path.replace(match, '');
// 获取数组索引
console.log(cmd)
const arrIndex = match.replace(/[\[\]]/gi, '');
console.log(cmd, arrIndex)
res = res[cmd][arrIndex];
} else {
res = res[path];
}
});
return res;
});
}
思路二:
function get(data, ...args) {
const res = JSON.stringify(data);
return args.map(item => {
return (new Function(`try {return ${res}.${item} } catch(e) {}`))()
})
}
js创建对象的安全模式
var Person = function (name) {
if(this instanceof Person){
this.name = name;
}else{
return new Person(name)
}
}
var jack = Person('Jack')
console.log(jack) //Person {name: "Jack"}
console.log(jack.name)//jack
2.雪碧图
3.base64
4.懒加载
5.webapck图片优化
image-webpack-loader插件及逆行质量的压缩
{
test: /\.(png|jpg|gif|svg)$/,
use: [
'file-loader',
{
loader: 'image-webpack-loader',
options: {
bypassOnDebug: true,
mozjpeg: {
progressive: true,
quality: 65
},
optipng: {
enabled: false,
},
pngquant: {
quality: '65-90',
speed: 4
},
gifsicle: {
interlaced: false,
},
// the webp option will enable WEBP
webp: {
enabled: false,
},
limit: 1,
name: '[name].[ext]?[hash]'
}
}]
}
合成雪碧图
const SpritesmithPlugin = require('webpack-spritesmith')
new SpritesmithPlugin({
src: {
cwd: path.resolve(__dirname, 'src/asserts'),
glob: '*.png'
},
target: {
image: path.resolve(__dirname, 'src/spritesmith-generated/sprite.png'),
css: path.resolve(__dirname, 'src/spritesmith-generated/sprite.css')
},
apiOptions: {
cssImageRef: "src/sprite.png"
}
})
//生成sprite.css文件
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
<base href="/">
// 指定一个基础路径,所有的路径都是以这个为基准
// viewport表示视图的大小,适配移动端第一步,viewport
// width 设置layout viewport 的宽度,为一个正整数,或字符串"width-device"
// initial-scale 设置页面的初始缩放值,为一个数字,可以带小数
// maximum-scale 允许用户的最大缩放值,为一个数字,可以带小数
// minimum-scale 允许用户的最小缩放值,为一个数字,可以带小数
// user-scalable 是否允许用户进行缩放,值为‘no’或‘yes’, no 代表不允许,yes代表允许
让浏览器以标准模式渲染
让浏览器知道元素的合法性
####块级元素 行内元素 自闭合元素
块级元素
行内元素
自闭合元素
property是DOM中的属性,是javascript的对象
attribute是HTML构造树上的特性,值只能是字符串
h5兼容 IE8/IE7/IE6支持通过document.createElement方法产生的标签处理兼容
如何区分:DOCTYPE声明\新增的结构元素\功能元素
mkdir vue_style
cd vue_style
npm init -y //初始化package.json
//生成如下目录
├── src //源目录(输入目录)
│ ├── index.js
│ ├── app.vue
+ |── index.html
├── package.json
|── webpack.config.js //webpack配置文件
npm install --save-dev vue
//基于vue的那么vue必不可少...不多介绍
npm install --save-dev webpack
//基于webpack的那么webpack也必不可少...不多介绍
npm install --save-dev webpack-cli
//webpack version 4+ 需要下载webpack-cli(一些指令下文可能涉及到)
npm install --save-dev path
//path 模块提供了一些工具函数,用于处理文件与目录的路径。
npm install --save-dev html-webpack-plugin
//简化了HTML文件的创建 Plugin that simplifies creation of HTML files to serve your bundles
` npm install --save-dev clean-webpack-plugin
//用于构建时清理构建文件夹下的内容 A webpack plugin to remove/clean your build folder(s) before building
npm install --save-dev vue-loader
//Vue.js组件加载器(插件)
npm install --save-dev vue-template-compiler
//对于模板的函数编译 与vue-loader 配合使用
npm install --save-dev webpack-dev-server
//热更新需要搭建服务模块
npm install --save-dev style-loader css-loader
//css样式处理器
import Vue from 'vue' // 引入vue模块
import App from './app.vue' //引入文件(组件) app
new Vue({ //vue写法 新建一个实例
el:"#app", //元素
template:'<App/>', // 模板使用标签<app/>
components:{App} // 组件app
})
<template>
<div id="app">
<p class="test">hello world!!</p>
<p class="test">{{msg}}</p>
</div>
</template>
<script>
import Vue from 'vue'
export default {
name:'app',
data(){
return {
msg:"hello vue !!"
}
},
}
</script>
<style >
.test{
color:#020202;
font-size:18px;
}
</style>
const path = require('path'); //path 模块提供了一些工具函数,用于处理文件与目录的路径。
const HtmlWebpackPlugin = require('html-webpack-plugin'); //构建html文件
const CleanWebpackPlugin = require('clean-webpack-plugin'); // 清理构建目录下的文件
const webpack = require('webpack'); //webpack打包工具
const VueLoaderPlugin = require('vue-loader/lib/plugin'); // vue-loader 编译vue文件
const compiler = require('vue-template-compiler') // 模板函数编译 与vue-loader配合使用
module.exports = {
entry: { //入口
"app": "./src/index.js"
},
module: { //处理项目中的不同类型的模块。
rules: [ // rules 各种规则(数组类型) 每个规则可以分为三部分 - 条件(condition),结果(result)和嵌套规则(nested rule)
{
test: /\.css/,
use: ['style-loader', 'css-loader'] // style-loader 和css-loader 编译css处理
},
{
test: /\.vue$/,
loader: 'vue-loader' //vue-loader 编译vue模块
}
]
},
devtool: 'inline-source-map', //生曾map 映射对应代码 方便错误查询
devServer: {
contentBase: './dist', // 告诉服务从哪提供代码内容(静态文件这么使用)
hot: true //hot模式开启
},
plugins: [
new CleanWebpackPlugin(['dist']), // 告诉清理插件的目录
new HtmlWebpackPlugin({ // 构建html
filename: 'index.html', //文件名
title: 'my-vue-cli', //title
template: './index.html', //参照模板样式
}),
new webpack.HotModuleReplacementPlugin(), //热模块替换开启
new VueLoaderPlugin() //vue-loader插件开启
],
output: { //出口
filename: 'index.js', //文件名
path: path.resolve(__dirname, 'dist'), //路径
publicPath: "" //srcript 引入路径
},
resolve: {
//引入路径是不用写对应的后缀名
extensions: ['.js', '.vue', '.json'],
alias: {
//正在使用的是vue的运行时版本,而此版本中的编译器时不可用的,我们需要把它切换成运行时 + 编译的版本
'vue$': 'vue/dist/vue.esm.js',
//用@直接指引到src目录下
'@': path.resolve(__dirname, './src'),
}
},
};
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"watch": "webpack --watch",
"dev": "webpack-dev-server --open --hot",
"build": "webpack"
},
npm run dev 运行于8080/可看到预期效果.
npm run build 打包编译同样可以看到效果
###vscode中格式化与vue中ESlint冲突
//在setting.json中设置如下
{
"workbench.colorTheme": "Quiet Light",
"window.zoomLevel": -1,
"editor.fontSize": 20,
"[html]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"java.configuration.checkProjectSettingsExclusions": false,
"editor.suggestSelection": "first",
"vsintellicode.modify.editor.suggestSelection": "automaticallyOverrodeDefaultValue",
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"vetur.validation.template": false, //重要
"vetur.format.defaultFormatter.js": "vscode-typescript", //重要
"javascript.format.insertSpaceBeforeFunctionParenthesis": true, //重要
"editor.formatOnType": true, //重要
"editor.formatOnSave": true, //重要
"editor.tabSize": 2
}
返回跳转或打开到当前页面的那个页面的URI。
如果用户直接打开了这个页面(不是通过页面跳转,而是通过地址栏或者书签等打开的),则该属性为空字符串。由于该属性只是返回一个字符串,所以不能够通过该属性引用页面的 DOM。
function base64EncodeUnicode(str) {//加密
return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) {
return String.fromCharCode('0x' + p1);
}));
}
function base64DecodeUnicode(str) {//解码
return decodeURIComponent(atob(str).split('').map(function(c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
}).join(''));
}
for(var i =0;i< data_list.length;i++) {
var dataList = data_list[i].data
dataList.sort(function (a, b) {
var t1 = a.xxx* 1;
var t2 = b.sss* 1;
if (t1 > t2) return 1;
else if (t1 < t2) return -1;
else return 0;
})
}
object.keys() 把对象转换成数组进行遍历,返回一个给定对象的自身可枚举属性组成的数组
var data={a:1,b:2,c:9,d:4,e:5};
console.log(data);//{a: 1, b: 2, c: 9, d: 4, e: 5}
console.log(typeof Object.keys(data));//["a", "b", "c", "d", "e"]
Object.keys(data).map((key,item)=>{
console.log(key,data[key]);//key=>属性名 data[key]=>属性值
});
set方法 可以去重
let set = new Set();
let a = NaN;
let b = NaN;
set.add(a);
set.add(b);
set // Set {NaN}
//=>NaN可以相等,需要去除一个NaN
封装bind方法
function bind(fn, context){
return function (){
return fn.apply(context, arguments);
}
}
什么情况下会触发重排?
(1)页面渲染初始化时;(这个无法避免)
(2)浏览器窗口改变尺寸;
(3)元素尺寸改变时;
(4)元素位置改变时;
(5)元素内容改变时;
(6)添加或删除可见的DOM 元素时。
重排优化有如下五种方法
(1)将多次改变样式属性的操作合并成一次操作,减少DOM访问。
(2)如果要批量添加DOM,可以先让元素脱离文档流,操作完后再带入文档流,这样只会触发一次重排。(fragment元素的应用)
(3)将需要多次重排的元素,position属性设为absolute或fixed,这样此元素就脱离了文档流,它的变化不会影响到其他元素。例如有动画效果的元素就最好设置为绝对定位。
(4)由于display属性为none的元素不在渲染树中,对隐藏的元素操作不会引发其他元素的重排。如果要对一个元素进行复杂的操作时,可以先隐藏它,操作完成后再显示。这样只在隐藏和显示时触发两次重排。
(5)在内存中多次操作节点,完成后再添加到文档中去。例如要异步获取表格数据,渲染到页面。可以先取得数据后在内存中构建整个表格的html片段,再一次性添加到文档中去,而不是循环添加每一行。
getBoundingClientRect() 的用法
兼容性
ie9以下浏览器只支持 getBoundingClientRect 方法的 top 、bottom、right、left属性;
ie9 和其它浏览器支持 getBoundingClientRect 方法 有6个属性 top 、bottom、right、left、width和height
![Alt text](./1532930660184.png)
轻量、可靠的移动端 Vue 组件库:
Fundebug 创始人:https://kiwenlau.com/
live server的作用:
live-server可以帮助我们前端人员搭建临时的http服务器。它不需要安装任何插件,使用起来比较便捷。它可以自动打开项目;修改本地文件后,浏览器能够立即同步,自动加载,自动刷新。
在package中增加代码
"scripts": {
"server": "live-server ./ --port=8081"
}
live server的参数
live-server --port=8083 //更改端口号
* `--port=NUMBER` - 选择要使用的端口,默认值:PORT env var或8080
* `--host=ADDRESS` - 选择要绑定的主机地址,默认值:IP env var或0.0.0.0(“任意地址”)
* `--no-browser` - 禁止自动Web浏览器启动
* `--browser=BROWSER` - 指定浏览器使用,而不是系统默认
* `--quiet | -q` - 禁止记录
* `--verbose | -V` - 更多日志记录(记录所有请求,显示所有侦听的IPv4接口等)
* `--open=PATH` - 启动浏览器到PATH而不是服务器根目录
* `--watch=PATH` - 用逗号分隔的路径来专门监视更改(默认值:观看所有内容)
* `--ignore=PATH` - 要忽略的逗号分隔的路径字符串([anymatch](https://github.com/es128/anymatch) -compatible definition)
* `--ignorePattern=RGXP`-文件的正则表达式忽略(即`.*\.jade`)(**不推荐使用**赞成`--ignore`)
* `--middleware=PATH` - 导出.js文件的路径导出中间件功能添加; 可以是一个没有路径的名字,也不是引用`middleware`文件夹中捆绑的中间件的扩展名
* `--entry-file=PATH` - 提供这个文件(服务器的根相对),以取代丢失的文件(对单页面应用程序有用)
* `--mount=ROUTE:PATH` - 在定义的路线下提供路径内容(可能有多个定义)
* `--spa` - 将请求从/ abc转换为/#/ abc(适用于单页面应用程序)
* `--wait=MILLISECONDS` - (默认100ms)等待所有更改,然后重新加载
* `--htpasswd=PATH` - 启用期待位于PATH的htpasswd文件的http-auth
* `--cors` - 为任何来源启用CORS(反映请求源,支持凭证的请求)
* `--https=PATH` - 到HTTPS配置模块的路径
* `--proxy=ROUTE:URL` - 代理ROUTE到URL的所有请求
* `--help | -h` - 显示简短的使用提示和退出
* `--version | -v` - 显示版本和退出
node中的使用
var liveServer = require("live-server");
var params = {
port: 8181, // Set the server port. Defaults to 8080.
host: "0.0.0.0", // Set the address to bind to. Defaults to 0.0.0.0 or process.env.IP.
root: "/public", // Set root directory that's being served. Defaults to cwd.
open: false, // When false, it won't load your browser by default.
ignore: 'scss,my/templates', // comma-separated string for paths to ignore
file: "index.html", // When set, serve this file for every 404 (useful for single-page applications)
wait: 1000, // Waits for all changes, before reloading. Defaults to 0 sec.
mount: [['/components', './node_modules']], // Mount a directory to a route.
logLevel: 2, // 0 = errors only, 1 = some, 2 = lots
middleware: [function(req, res, next) { next(); }] // Takes an array of Connect-compatible middleware that are injected into the server middleware stack
};
liveServer.start(params);
var data = {
"reduce_list": [{
"reduce_id": 168,
"settlement_id": 26,
"settlement_code": "JSD-1003201811120001",
"buss_contract_id": 4968,
"buss_contract_code": "BZ-1003201811060014",
"buss_order_id": 5776,
"buss_order_code": "BZ-10032018110600140004",
"reduce_item": 2,
"reduce_amount": 4900,
"reduce_explain": "北风卷地白草折",
"reduce_type": 3,
"bill_type": 3,
"bill_code": "ZD-1003201811060014-0005"
},{
"reduce_id": 168,
"settlement_id": 26,
"settlement_code": "JSD-1003201811120001",
"buss_contract_id": 4968,
"buss_contract_code": "BZ-1003201811060014",
"buss_order_id": 5776,
"buss_order_code": "BZ-10032018110600140004",
"reduce_item": 2,
"reduce_amount": 4900,
"reduce_explain": "北风卷地白草折",
"reduce_type": 3,
"bill_type": 3,
"bill_code": "ZD-1003201811060014-0006"
},{
"reduce_id": 168,
"settlement_id": 26,
"settlement_code": "JSD-1003201811120001",
"buss_contract_id": 4968,
"buss_contract_code": "BZ-1003201811060014",
"buss_order_id": 5776,
"buss_order_code": "BZ-10032018110600140004",
"reduce_item": 2,
"reduce_amount": 4900,
"reduce_explain": "北风卷地白草折",
"reduce_type": 3,
"bill_type": 3,
"bill_code": "ZD-1003201811060014-0006"
},{
"reduce_id": 168,
"settlement_id": 26,
"settlement_code": "JSD-1003201811120001",
"buss_contract_id": 4968,
"buss_contract_code": "BZ-1003201811060014",
"buss_order_id": 5776,
"buss_order_code": "BZ-10032018110600140004",
"reduce_item": 2,
"reduce_amount": 4900,
"reduce_explain": "北风卷地白草折",
"reduce_type": 3,
"bill_type": 3,
"bill_code": "ZD-1003201811060014-0006"
} ,{
"reduce_id": 168,
"settlement_id": 26,
"settlement_code": "JSD-1003201811120001",
"buss_contract_id": 4968,
"buss_contract_code": "BZ-1003201811060014",
"buss_order_id": 5776,
"buss_order_code": "BZ-10032018110600140004",
"reduce_item": 2,
"reduce_amount": 4900,
"reduce_explain": "北风卷地白草折",
"reduce_type": 3,
"bill_type": 3,
"bill_code": "ZD-1003201811060014-0007"
}, {
"reduce_id": 165,
"settlement_id": 26,
"settlement_code": "JSD-1003201811120001",
"buss_contract_id": 4968,
"buss_contract_code": "BZ-1003201811060014",
"buss_order_id": 5776,
"buss_order_code": "BZ-10032018110600140004",
"reduce_item": 5,
"reduce_amount": 4900,
"reduce_explain": "北风卷地白草折",
"reduce_type": 1,
"bill_type": 3,
"bill_code": "ZD-1003201811060014-0007"
}]
}
//根据bill_code进行分组
/*
* data:分组数据
* group:按某字段分组
*/
function groupArray(data,group){
var map = {}
var reduceArray = []
for (var i = 0; i < data.length; i++) {
var dataList = data[i];
console.log(!map[group]);
if (!map[]) {
reduceArray.push({
id: group,
data: [dataList]
});
map[group] = dataList
} else {
for (var j = 0; j < reduceArray.length; j++) {
var dj = reduceArray[j]
if (dj.id === group) {
dj.data.push(dataList)
break;
}
}
}
}
return reduceArray;
}
var reduceArray = groupArray(data.reduce_list,dataList.bill_code);
console.log(reduceArray);
实例2:按某相同字段相加
const arr = [{
id: 1,
num: 10
},
{
id: 1,
num: 100
},
{
id: 1,
num: 10
},
{
id: 2,
num: 10
},
{
id: 1,
num: 100
},
{
id: 2,
num: 100
},
{
id: 10,
num: 10
},
{
id: 10,
num: 10
}
]
let a = arr.reduce((h,n)=>{
if(h.length === 0){
h.push(n);
return h;
}
for(let item of h){
if(item.id === n.id){
item.num += n.num;
return h;
}
}
return h.concat([n])
},[])
console.log(a)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.