分类目录归档:技术

小程序的 marker 无法触发 bindmarkertap 事件应该如何处理

TL;DR

如果想要 marker 可以响应 bindmarkertap 事件,需要设定 markerID,这一点文档中并没有标注。

具体情况

在开发美食地图时,出现了一个问题,marker 的点击总是不会触发 bindmarkertap 事件。

我的代码是这样写的

    store.get().then(res => {
      this.setData({
        stores: res.data,
        windowHeight: app.globalData.windowHeight,
      }, () => {
        wx.hideLoading();
        wx.showToast({
          title: '双指缩放可以调整地图可视区域,查看更多美食',
          icon: 'none'
        })
      })
    })
Code language: JavaScript (javascript)

在地图中去调用 stores. marker

在地图上的确可以出现图标,但是无法点击 maker 并触发事件。

通过复制官方的 marker 的数据进行调试后发现,当 maker 有 id 时,marker 就可以触发事件,因此,怀疑是 ID 的问题。

在美食地图小程序中,我使用的是腾讯云提供的小程序·云开发,其使用的是 MongoDB 作为后台的 Database ,默认的主键为 _id,所以,我自己写了代码来转换 _id

      data.map(item => {
        item.id = item._id
      });
Code language: JavaScript (javascript)

对应的 commit :https://github.com/CloudKits/miniprogram-foodmap/commit/5abcad1f756e03a388bb33dd1c699d3cae9ea0c4#diff-f5ea41cdd371d7b65bfdf8d32188e37d

实现密码生成器的思路

在项目中有这样一个需求:需要生成一组随机密码,确保安全性。因此,我去翻了一个项目的代码。这里是具体的代码

function GeneratePassword() {
    if (parseInt(navigator.appVersion) <= 3) {
        alert("Sorry this only works in 4.0+ browsers");
        return true;
    }
    var length=8;
    var sPassword = "";
    length = document.aForm.charLen.options[document.aForm.charLen.selectedIndex].value;
    var noPunction = (document.aForm.punc.checked);
    var randomLength = (document.aForm.rLen.checked);
    if (randomLength) {
        length = Math.random();
        length = parseInt(length * 100);
        length = (length % 7) + 6
    }
    for (i=0; i < length; i++) {
        numI = getRandomNum();
        if (noPunction) { while (checkPunc(numI)) { numI = getRandomNum(); } }
        sPassword = sPassword + String.fromCharCode(numI);
    }
    document.aForm.passField.value = sPassword
    return true;
}
function getRandomNum() {
    // between 0 - 1
    var rndNum = Math.random()
    // rndNum from 0 - 1000
    rndNum = parseInt(rndNum * 1000);
    // rndNum from 33 - 127
    rndNum = (rndNum % 94) + 33;
    return rndNum;
}
function checkPunc(num) {
    if ((num >=33) && (num <=47)) { return true; }
    if ((num >=58) && (num <=64)) { return true; }
    if ((num >=91) && (num <=96)) { return true; }
    if ((num >=123) && (num <=126)) { return true; }
    return false;
}

Code language: JavaScript (javascript)

上完代码,接下来来分析一下这段代码

首先,这段代码中有三个函数,其关系如下图所示

image
密码生成器各函数关系图

其中 getRandomNum 生成了一个范围在 33 – 127 的数字。这里是由于在后续生成随机字符串时,用的是 String.fromCharCode,当数字在 33~127 之间时,能够确保生成的数字在输入时比较简单。

image 1
String.fromCharCode 的测试结果

checkPunc 则是检测输出的文字是否可以直接发音,这涉及到记忆的难度的问题,在一个长的字符串中,记忆 ABCD 肯定比记忆逗号、破折号、句号等符号要简单一些,毕竟字母肯定要好记忆点,可以自编语句来实现。

接下来我们来看最核心的 GeneratorPassword 函数:如果将其中的 Dom 操作都忽略掉,并设置一个值。并进行配置后,代码如下:

function GeneratePassword() {
    // 检测浏览器支持
    if (parseInt(navigator.appVersion) <= 3) {
        alert("Sorry this only works in 4.0+ browsers");
        return true;
    }
    var length=8;
    var sPassword = "";
    length = 10 // 此处代码原为使用 dom 函数获取表单数据的代码,来实现自定义长度的功能。
    var noPunction = false// 此处代码原为获取表单数据的代码,控制是否检测密码的可读性
    var randomLength = false // 此处代码原为获取表单数据的代码,控制是否使用随机长度。
    // 如果使用随机长度的密码,则进入循环
    if (randomLength) {
        length = Math.random();
        length = parseInt(length * 100); // 生成 0 ~ 100 之间的数字
        length = (length % 7) + 6 // 对生成的长度取余,则最短为6,最长为12
    }
    // 根据长度进行循环
    for (i=0; i < length; i++) {
        numI = getRandomNum();  // 获取一个随机数
        if (noPunction) { while (checkPunc(numI)) { numI = getRandomNum(); } } // 如果需要判断发音,进行发音判断,判断失败就重新生成,直到成功。
        sPassword = sPassword + String.fromCharCode(numI); // 将生成的字符串加入到原有的字符串最后
    }
    // 设置代码到 Dom 元素中
    return true;
}
Code language: JavaScript (javascript)

其代码逻辑图如下

未命名表单 1
密码生成器的代码逻辑图

第三方服务前端数据安全校验

坐在腾大写博客,听到了身边的人在讨论前端数据安全校验的方案。

他们需要提供 H5 的SDK ,既然运行在前端,那么应用的 Secret 和 Key 就有可能暴露在浏览器里,如何确保 Secret 和 Key 的安全呢?

一个比较主流的方案就是使用白名单限制。每一个应用绑定特定的几个域名,只有白名单里的域名可以请求服务。

我还想到了另外一个案例。我自己比较喜欢使用 Algolia 提供的搜索服务,在 Algolia 中,区分 Master Key 和 Search Only Key。Search Only Key 只能用于数据查询,而 Master Key 可以用来添加数据。

如果是这样的话,或许可以比较好的处理。

如何保持对技术的敏感性?

我有个习惯:做 Side Project
我还有个习惯:每次做 Side Project,使用不同的技术。
举个例子:
我经常会做和 web 相关的项目,第一个项目我使用 Laravel (Php)开发;第二个项目我就考虑使用 Rails (Ruby)开发;第三个项目就用 Django(python) 开发。
这样、只要 Side Project 不死,我就需要经常维护,对我来说,就是保持自己一直掌握这些技能,不会丢掉技能。

Typecho 的所有挂载点

admin/write-post.php:58:                    content($post); ?>
admin/write-post.php:97:                        option($post); ?>
admin/write-post.php:140:                            advanceOption($post); ?>
admin/write-post.php:171:Typecho_Plugin::factory('admin/write-post.php')->trigger($plugged)->richEditor($post);
admin/write-post.php:178:Typecho_Plugin::factory('admin/write-post.php')->bottom($post);
admin/theme-editor.php:60:Typecho_Plugin::factory('admin/theme-editor.php')->bottom($files);
admin/editor-js.php:224:    markdownEditor($content); ?>
admin/menu.php:7:        navBar(); ?>
admin/header.php:15:$header = Typecho_Plugin::factory('admin/header.php')->header($header);
admin/footer.php:6:Typecho_Plugin::factory('admin/footer.php')->end();
admin/profile.php:58:Typecho_Plugin::factory('admin/profile.php')->bottom();
admin/common.php:18:Typecho_Plugin::factory('admin/common.php')->begin();
admin/write-page.php:53:                    content($page); ?>
admin/write-page.php:86:                        option($page); ?>
admin/write-page.php:112:                            advanceOption($page); ?>
admin/write-page.php:142:Typecho_Plugin::factory('admin/write-page.php')->trigger($plugged)->richEditor($page);
admin/write-page.php:149:Typecho_Plugin::factory('admin/write-page.php')->bottom($page);
admin/write-js.php:2:write(); ?>
index.php:20:Typecho_Plugin::factory('index.php')->begin();
index.php:26:Typecho_Plugin::factory('index.php')->end();
var/Widget/Upload.php:90:        $result = Typecho_Plugin::factory('Widget_Upload')->trigger($hasUploaded)->uploadHandle($file);
var/Widget/Upload.php:162:        $result = Typecho_Plugin::factory('Widget_Upload')->trigger($hasModified)->modifyHandle($content, $file);
var/Widget/Upload.php:227:        $result = Typecho_Plugin::factory('Widget_Upload')->trigger($hasDeleted)->deleteHandle($content);
var/Widget/Upload.php:245:        $result = Typecho_Plugin::factory('Widget_Upload')->trigger($hasPlugged)->attachmentHandle($content);
var/Widget/Upload.php:264:        $result = Typecho_Plugin::factory('Widget_Upload')->trigger($hasPlugged)->attachmentDataHandle($content);

WordPress 换域名代码


UPDATE wp_options SET option_value = replace(option_value, 'www.olddomain.com','www.newdomain.com') ;
UPDATE wp_posts SET post_content = replace(post_content, 'www.olddomain.com','www.newdomain.com') ;
UPDATE wp_comments SET comment_content = replace(comment_content, 'www.olddomain.com', 'www.newdomain.com') ;
 UPDATE wp_comments SET comment_author_url = replace(comment_author_url, 'www.olddomain.com', 'www.newdomain.com') ;