所有由普若木特发布的文章

javascript数组降维

网上有不少提供数组降维的方法,但是一般是二维数组,并且对多维数组的处理不好。降维自然会想到用concat方法,如果只是全部循环用push的话,那样写起来更麻烦,必要时该用concat的就用concat。

function dist(arr) {
        var res = [];
        for (var i = 0; i < arr.length; i++) {
            if (Object.prototype.toString.call(arr[i]) === '[object Array]') {
                res = res.concat(dist(arr[i]));
            } else {
                res.push(arr[i]);
            }
        }
        return res;
    }
var re = dist([1, 2, [3, 4, [5, 6, [7, 8]]]]);
    console.log('re', re); //输出[1,2,3,4,5,6,7,8]

Javascript原生函数作为构造函数

关于数组(array)、对象(object)、函数(function)和正则表达式,我们通常喜欢以常量的形式来创建它们。实际上,使用常量和使用构造函数的效果是一样的(创建的值都是通过封装对象来包装)。
如前所述,应该尽量避免使用构造函数,除非十分必要,因为它们经常会产生意想不到的结果。
3.4.1 Array(..)
var a = new Array( 1, 2, 3 );
a; // [1, 2, 3]
var b = [1, 2, 3];
b; // [1, 2, 3]
构造函数Array(..) 不要求必须带new 关键字。不带时,它会被自动补上。
因此Array(1,2,3) 和new Array(1,2,3) 的效果是一样的。

Array 构造函数只带一个数字参数的时候,该参数会被作为数组的预设长度(length),而非只充当数组中的一个元素。
这实非明智之举:一是容易忘记,二是容易出错。
更为关键的是,数组并没有预设长度这个概念。这样创建出来的只是一个空数组,只不过它的length 属性被设置成了指定的值。
如若一个数组没有任何单元,但它的length 属性中却显示有单元数量,这样奇特的数据结构会导致一些怪异的行为。而这一切都归咎于已被废止的旧特性(类似arguments 这样的类数组)。
3.4.2 Object(..)、Function(..) 和RegExp(..)
同样,除非万不得已,否则尽量不要使用Object(..)/Function(..)/RegExp(..):
var c = new Object();
c.foo = “bar”;
c; // { foo: “bar” }
var d = { foo: “bar” };
d; // { foo: “bar” }
var e = new Function( “a”, “return a * 2;” );
var f = function(a) { return a * 2; }
function g(a) { return a * 2; }
var h = new RegExp( “^a*b+”, “g” );
var i = /^a*b+/g;
在实际情况中没有必要使用new Object() 来创建对象,因为这样就无法像常量形式那样一次设定多个属性,而必须逐一设定。

构造函数Function 只在极少数情况下很有用,比如动态定义函数参数和函数体的时候。不要把Function(..) 当作eval(..) 的替代品,你基本上不会通过这种方式来定义函数。

强烈建议使用常量形式(如/^a*b+/g)来定义正则表达式,这样不仅语法简单,执行效率也更高,因为JavaScript 引擎在代码执行前会对它们进行预编译和缓存。与前面的构造函数不同,RegExp(..) 有时还是很有用的,比如动态定义正则表达式时:
var name = “Kyle”;
var namePattern = new RegExp( “\\b(?:” + name + “)+\\b”, “ig” );
var matches = someText.match( namePattern );
上述情况在JavaScript 编程中时有发生,这时new RegExp(“pattern”,”flags”) 就能派上用场。
3.4.3 Date(..) 和Error(..)
相较于其他原生构造函数,Date(..) 和Error(..) 的用处要大很多,因为没有对应的常量形式来作为它们的替代。
创建日期对象必须使用new Date()。Date(..) 可以带参数,用来指定日期和时间,而不带参数的话则使用当前的日期和时间。
Date(..) 主要用来获得当前的Unix 时间戳(从1970 年1 月1 日开始计算,以秒为单位)。该值可以通过日期对象中的getTime() 来获得。
从ES5 开始引入了一个更简单的方法,即静态函数Date.now()。
如果调用Date() 时不带new 关键字,则会得到当前日期的字符串值。其具体格式规范没有规定,浏览器使用”Fri Jul 18 2014 00:31:02 GMT-0500 (CDT)”这样的格式来显示。

构造函数Error(..)(与前面的Array() 类似)带不带new 关键字都可。
创建错误对象(error object)主要是为了获得当前运行栈的上下文(大部分JavaScript 引擎通过只读属性.stack 来访问)。栈上下文信息包括函数调用栈信息和产生错误的代码行号,以便于调试(debug)。
除Error(..) 之外, 还有一些针对特定错误类型的原生构造函数, 如EvalError(..)、 RangeError(..)、 ReferenceError(..)、 SyntaxError(..)、TypeError(..) 和URIError(..)。这些构造函数很少被直接使用,它们在程序发生异常(比如试图使用未声明的变量产生ReferenceError 错误)时会被自动调用。
3.4.4 Symbol(..)
ES6 中新加入了一个基本数据类型 ——符号(Symbol)。符号是具有唯一性的特殊值(并非绝对),用它来命名对象属性不容易导致重名。该类型的引入主要源于ES6 的一些特殊构造,此外符号也可以自行定义。
符号可以用作属性名,但无论是在代码还是开发控制台中都无法查看和访问它的值,只会显示为诸如Symbol(Symbol.create) 这样的值。
ES6 中有一些预定义符号,以Symbol 的静态属性形式出现,如Symbol.create、Symbol.
iterator 等,可以这样来使用:obj[Symbol.iterator] = function(){ /*..*/ };
我们可以使用Symbol(..) 原生构造函数来自定义符号。但它比较特殊,不能带new 关键字,否则会出错:
var mysym = Symbol( “my own symbol” );
mysym; // Symbol(my own symbol)
mysym.toString(); // “Symbol(my own symbol)”
typeof mysym; // “symbol”

var a = { };
a[mysym] = “foobar”;

Object.getOwnPropertySymbols( a );
// [ Symbol(my own symbol) ]
虽然符号实际上并非私有属性(通过Object.getOwnPropertySymbols(..) 便可以公开获得
对象中的所有符号),但它却主要用于私有或特殊属性。很多开发人员喜欢用它来替代有下划线(_)前缀的属性,而下划线前缀通常用于命名私有或特殊属性。
符号并非对象,而是一种简单标量基本类型。
摘自:《你不知道的javascript》中卷

用在线IDE写vue代码

上周末无意中发现了一个新的在线IDE,网址glitch.comglitch.com,个人感觉很不错,于是顺便关注了下其它的在线IDE,比如codesandbox.io也不错,没有细看,可能自己已经先入为主的喜欢上glitch了吧。
下面主要说说glitch,打开官网后可以新建一个工程,一般会让你选择网站型项目还是node型项目,试了试node型项目的功能强大些,推荐一律用这种类型。这里有一个server.js,

app.get('/', (request, response) => {
  response.sendFile(`${__dirname}/${dist}/index.html`);
});

这里就是默认把index.html作为首页来当项目的入口
写过vue,并且运行过npm run build的都知道,vue打完包的入口就是index.html,所以这里根据自己项目的打包后的情况修改一下就行了。
有的同学肯会问,这个glitch还能运行node命令不成?目前我没有发现它有这个功能,那怎么实现打包呢?在package.json里面设置,

"scripts": {
    "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
    "start": "npm run build && node server.js",
    "lint": "eslint --ext .js,.vue src",
    "build": "node build/build.js"
  },

我们要用的就是package.json的start命令,因为我发现glitch查看自己项目的时候会自动运行package.json里面的start命令,来让该项目能够跑起来,所以我们可以在start里面先打包(npm run build)再启动node服务器(node server.js),你的项目就是在这个node服务器下面运行的,它就这样跑起来了。
说没了就是运行webpack和node,重点是配置后webpack

既然是node项目,一定是要安装插件的喽。
glitch安装node插件超级爽
点击package.json然后简单操作一下就行了

今天发现glitch项目貌似有大小限制,128M,我是在导入工程时看到的提示,还没有在官方那确认。
目前我搞了一个vuecli建的空项目,大家可以直接remix然后使用,地址 https://vuecli.glitch.me。我还特意试了试vue.glitch.me,这个域名被用了,是一个哥们写的todolist项目,还没写完。

nodejs express获取请求参数(get,post)

如果访问的接口地址成http://127.0.0.1/index?id=1,我们怎么获取index,怎么获取id=1呢?
我们为了得到index,我们可以通过使用req.params得到,通过这种方法我们就可以很好的处理Node中的路由处理问题,同时利用这点可以非常方便的实现MVC模式;
通过使用req.query.id就可以获得获取客户端get方式传递过来的值,类似于PHP的get方法;
如果在请求时post了title=daozhao,我们怎么获取title=daozhao呢?
可以通过req.body.id获取获取客户端post过来的数据,类似于PHP的post方法;

var express        =         require("express");  
var bodyParser     =         require("body-parser");  
var app            =         express();  
  
// need it...  
app.use(bodyParser.urlencoded({ extended: false }));  
  
app.post('/login',function(req,res){  
  var user_name=req.body.user;  
  var password=req.body.password;  
  console.log("User name = "+user_name+", password is "+password);  
  res.end("yes");  
});  

转载自https://www.cnblogs.com/lgp2000/p/5596328.html

道招网正式开启https

之前我只是对微信小程序好奇,搞了个子域名 https://w.daozhao.com,现在发现越来越多的场景需要https,加上现在的主机貌似只支持一个域名用ssl证书,单独买个多域名ssl证书比较贵,暂时没有必要,经过考虑,觉得主站www.daozhao.com使用ssl证书开启https时代,子域名就暂时不用证书了,也可能会逐步关闭,毕竟知道的人又不多,用的人更好。
现在我顺便记录下自己http转到https的过程吧。
一、搞到ssl证书

我是在西部数码买的证书,基本不要钱,懒得在网上找。
在主机上配置好证书,不支持的可能等换主机了

在确定网站可以使用https访问后进行下一步
二、进入管理界面,设置-常规修改“WordPress地址”(URL)和“站点地址(URL)”,改为https开头的
三、保险起见,修改数据库,主要是修改里面的保存文章的那张表wp_posts,还有保存缩略图的那张表wp_postmeta
执行sql语句

update wp_posts set post_content = replace(post_content, 'http://www.daozhao.com','https://www.daozhao.com');
update wp_postmeta set meta_value = replace(meta_value, 'http://www.daozhao.com','https://www.daozhao.com');

四、登录和后台强制开启ssl,修改根目录的WP-config.php文件,直接在文件末尾加入以下两行代码

/* 强制后台和登录使用 SSL */
define('FORCE_SSL_LOGIN', true);
define('FORCE_SSL_ADMIN', true);

五、让原来的页面直接跳转至https页面
修改根目录的.htaccess文件

# BEGIN WordPress

RewriteEngine On
RewriteCond %{HTTPS} !^on$ [NC]
RewriteRule (.*) https://%{SERVER_NAME}%{REQUEST_URI} [L,R=301]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

# END WordPress

前端模拟后端接口进行调试之easy-mock篇

之前写过一个方便大家本地调试的博客《前端模拟后端接口进行调试之NODE+MYSQL篇》,主要是方便没有网的筒子开发?没网?原始社会?是的,我现在待的单位就不能连外网。。。
今天给大家推荐一个联网的同志们可以用的,超级方便,还支持函数来显示不同的数据,官方称其为响应式数据?它就是easy-mock
还是用上一篇文章的数据,看看如何用easy-mock来实现,分页也同样很轻松。


{
"responseCode": "001",
"responseMsg": "",

"data": {
"all": [{
"title": "firsttitle",
"id": "1"
}, {
"title": "这是标题",
"id": "2"
}, {
"title": "一篇文章",
"id": "3"
}, {
"title": "又一篇文章",
"id": "4"
}, {
"title": "第五篇文章",
"id": "5"
}, {
"title": "第六篇文章",
"id": "6"
}, {
"title": "第七篇文章",
"id": "7"
}, {
"title": "第八篇文章",
"id": "8"
}, {
"title": "第九篇文章",
"id": "9"
}, {
"title": "第十篇文章",
"id": "10"
}, {
"title": "dafd文章",
"id": "11"
}, {
"title": "dafd文章",
"id": "12"
}, {
"title": "dafd文章",
"id": "13"
}, {
"title": "dafd文章",
"id": "14"
}],
list: function({
_req
}) {
if (_req.query.index) {
return this.all.slice((_req.query.index - 1) * 5, _req.query.index * 5)
} else {
return []
}
}
}
}

简单说明一下,这里我讲所用的数据存放在all这个数组里面,在使用接口返回数据的时候用list字段,这里才是当前页面需要返回的数据,是不是很方便?快来试一下吧。
更多方法可以查看官网的文档哦

wordpress的restfulAPI接口返回数据的几点分析与处理

想让wordpress作为后端提供数据,必不可少的就是调用xxx.com/wp-json/wp/v2/posts这个接口了,(具体内容请参考官方文档)该接口返回一个文章列表,数组中的每条文章返回了该文章的详细信息,其中自然办好文章的分类categories和标签tags了,做过项目的都知道,这类数据一般也不推荐直接返回文字信息,一般都是返回码值,根据映射关系找到对应的文字。
接口数据
从图中可以看到:分类categories和标签tags返回的都是数组,里面的数字代表了对应内容的id,需要根据id在调用相应的查询接口获得文字信息。
分类信息和标签信息里面相对麻烦点的是分类信息,因为分类信息可能有父子级的关系,而标签则不存在,是扁平化返回。下面说说我是怎么处理分类的,最实际的应用场景就是博客上方的导航菜单。
首先我们肯定是调用接口xxx.com/wp-json/wp/v2/categories获取博客里面的所有分类categories信息,这里最好将每页返回的数据条数设置大一点,方便一致性返回全部分类信息,看下接口返回格式

截图屏幕有限,具体的大家自行调用,我说一下吧,分类信息全是扁平化返回,用一个数据返回,比如你有2个大分类,里面各有3个消费,则接口换返回里面有2+2*3=8个对象的数组,唯一的区别是父分类的parent字段为0,子分类的parent字段则是对应的父分类的id。估计后端同事都喜欢这么干,确实很方便。但是前端的同志就苦逼了。扁平化数组?循环?该怎么样渲染更方便?
本例中有五个大的分类,id分别是39、54、477、600、1020其中54、600、1020有子分类,进行处理后返回一个大的对象,每个大类有children字段,其为数组,里面是一堆他的子分类。

图中id为127的就是54这个大分类的子分类。处理代码如下:

function postsHandle(data) {
    let categoriesObj = {};
    let categoriesMap = {};
    if (data && data.length) {
        data.map((item, index) => {
            categoriesMap[item.id] = {
                name: item.name,
                slug: item.slug
            };
            if (item.parent != '0') { //子分类
                if (!categoriesObj[item.parent]) { //其父分类不存在
                    categoriesObj[item.parent] = {
                        id: item.id,
                        item: '',
                        children: [{
                            id: item.id,
                            item
                        }]
                    };
                } else {
                    categoriesObj[item.parent].children.push({
                        id: item.id,
                        item
                    })
                }
            } else {
                if (categoriesObj[item.id]) { //已由分类创建
                    categoriesObj[item.id].id = item.id;
                    categoriesObj[item.id].item = item;
                } else {
                    categoriesObj[item.id] = {
                        id: item.id,
                        item,
                        children: []
                    };
                }
            }
        })

    }
    return {
        categoriesObj,
        categoriesMap
    }
}

categoriesObj就是上面所说的大分类,大家可能发现还有个categoriesMap,什么鬼?这个是我用来记录分类id和展示名称及路径

手疼,今天先写这么多。
可以让大家看看昨天做的效果,没有美化,另外wordpress的restfulAPI返回数据很慢(我在本地连接本地数据库也是很慢),为了大家感受到这种慢,我做的菜单导航设置了边框,哈哈。
网址: http://vue.w.daozhao.com/,切记不要用https访问,否则会跨域,那样你就只能看到框框了。

前端框架vue+wordpress做后端

目前正在利用闲暇时捯饬一下自己的博客,毕竟这么久没有维护了,wordpress是可以用restful API来获取数据的,决定前端用vue实现,目前正在尝试中,今天做了其中很小的一部分,就是博客目录,样式暂时没写,直接照抄原来的主题样式,后期在优化。

前端vue

欢迎大家一起。
github地址:https://github.com/shadowprompt/wordpress-vue

前端模拟后端接口进行调试之node+mysql篇

有时前端在开发过程中肯定是会跟后端联调的,但是如果此时后端可能没有开发好,或者因为其它优先级高的事情无法联调,又或者是前端需要确保当前项目无明显bug后着手开发其他项目。这个时候如果能模拟后端接口数据,就能做到自己调试,等到真正和后端联调时就很轻松了。
既然这篇是node+mysql篇当然本机上要按照好node和mysql(本例中是用的pc上安装wampserver的方案)。
第一步,用node安装express、body-parser和mysql

npm install express body-parser –save

npm install mysql –save-d

用node实现接口
api.js

var path = require('path');
var express = require('express');
var bodyParser = require('body-parser');
var mysql = require("mysql");

var app = express();

//mysql的连接池
var pool = mysql.createPool({
    host: 'localhost',
    port: 3306,
    database: 'test',
    user: 'root',
    password: ''
})




app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

var perPage = 10; //默认每页条数

app.get('/api/page/:index', function(req, res) {
    res.header("Access-Control-Allow-Origin", "*");//避免跨域
    res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
    res.header("Access-Control-Allow-Headers", "X-Requested-With");
    res.header('Access-Control-Allow-Headers', 'Content-Type');
    var index = req.params.index;
    console.log('当前请求第' + index + '页数据');
    pool.getConnection(function(err, connection){
        if(err){
            console.log('连接mysql数据库失败');
        }else{
            var dataBack = {
                responseCode: '001',
                responseMsg: '',
                res:{
                    count: 0,
                    data: []
                }
            }
            //查询总数
            connection.query('SELECT COUNT(*) FROM posts', null, function(err, result){
                dataBack.res.count = result[0]['COUNT(*)'];
            });
            //查询分页数据
            connection.query('SELECT * FROM posts limit ' + perPage*(index-1) +' ,' + perPage, null, function(err, result){
                if(err){
                    console.log('查询数据失败');
                }else{
                    dataBack.res.data = result;
                    res.send(dataBack);
                    connection.release();
                }
            })
        }
    })

});


app.get('*', function(req, res) {
    res.send({
        responseCode: '002',
        responseMsg: '请访问/api/page/:id获取数据'
    });
});

app.listen(8911, 'localhost', function(err) {
    if (err) {
        console.log(err);
        return;
    }

    console.log('Listening at http://localhost:8911');
});

简单说明一下:
1、这里是用来自己调试用的,所以对请求头和请求源的设置都比较宽松
2、这里是在mysql里面新建了一个test数据库里面的posts表
表内数据如下
mysql数据

-- phpMyAdmin SQL Dump
-- version 4.6.4
-- https://www.phpmyadmin.net/
--
-- Host: 127.0.0.1
-- Generation Time: 2017-12-02 01:55:09
-- 服务器版本: 5.7.14
-- PHP Version: 5.6.25

SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";


/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;

--
-- Database: `test`
--

-- --------------------------------------------------------

--
-- 表的结构 `posts`
--

CREATE TABLE `posts` (
  `title` char(20) CHARACTER SET utf8 NOT NULL,
  `id` int(20) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

--
-- 转存表中的数据 `posts`
--

INSERT INTO `posts` (`title`, `id`) VALUES
('first title', 1),
('这是标题', 2),
('一篇文章', 3),
('又一篇文章', 4),
('第五篇文章', 5),
('第六篇文章', 6),
('第七篇文章', 7),
('第八篇文章', 8),
('第九篇文章', 9),
('第十篇文章', 10),
('dafd文章', 11),
('dafd文章', 12),
('dafd文章', 13),
('dafd文章', 14),
('dafd文章', 15);

--
-- Indexes for dumped tables
--

--
-- Indexes for table `posts`
--
ALTER TABLE `posts`
  ADD PRIMARY KEY (`id`);

--
-- 在导出的表使用AUTO_INCREMENT
--

--
-- 使用表AUTO_INCREMENT `posts`
--
ALTER TABLE `posts`
  MODIFY `id` int(20) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=16;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;

3、这里的接口除了返回请求页面的条数还额外返回了数据库总数,如果需要前端去重的时候需要用到总数。
4、接口采用的是restful api
5、每页返回条数也可一次通过前端传值来控制

前端请求结果
接口返回结果
我用的chrome插件JSON Viewer来查看json,是不是很爽,传送门=》 商店地址
接口返回结果

VSC:Cannot connect to the target: connect ECONNREFUSED 127.0.0.1:9222

最近想试试微软的编程IDE visual studio code,江湖简称VSC,按F5可以进行debug,之前用了一直还没有报错,后来随便弄了一下chrome,在用vsc的调试模式就报错了,提示内容是“Cannot connect to the target: connect ECONNREFUSED 127.0.0.1:9222”,在百度搜一下,出现这个问题的同学还是不少啊,但是一些问答社区好像并没有给出解决方案,可能是同志们找到了解决方法,但是没有公开吧。于是我在Google上搜了一下,找到了解决方案,里面好像vsc的开发人员进行了解答。

杀掉所有chrome进程,就可以了,此时再按F5就能进入调试模式了,并且访问http://127.0.0.1:9222/json就会看到页面返回一堆json

官方也在努力同chrome团队解决这个问题。

原文地址点此访问