小程序组件间通信与事件实际应用

小程序从1.6.3版本后开始支持组件化编程,开发可以自定义许多可复用的组件。在页面中使用一个或多个组件后,就存在一个数据传递问题,这其实就是通信。小程序的通信有3种方式:

  1. WXML数据绑定:用于父组件向子组件的指定属性设置数据,仅能设置 JSON 兼容数据(自基础库版本 2.0.9 开始,还可以在数据中包含函数)。
  2. 事件:用于子组件向父组件传递数据,可以传递任意数据。
  3. 如果以上两种方式不足以满足需要,父组件还可以通过 this.selectComponent 方法获取子组件实例对象,这样就可以直接访问组件的任意数据和方法。

第一种很简单,这里主要记录第二种的使用。

看下面两张图片,在首页,由多个组件组成,点击更多跳转对应的页面。

首页1
首页2

在搜索页面,同样需要用到这些组件

搜索页

可是在做首页的时候,这里的更多已经在组件里定义好了,跳转到新的页面。而搜索这里需求却又不是跳转新页面,应是当前顶部对应的菜单。两个页面在这里就矛盾了,而且从体验上来说,搜索这里肯定不能有页面的切换的。难道要把所有组件重新复制一个出来吗?这里就可以用到事件了。

在搜索页面调用组件时,我们绑定一个自定义事件more,并且传入一个属性isSearch

<component-name bind:more="doMore" isSearch="1"/>

搜索页面里定义这个doMore方法。组件更多按钮的点击事件内判断,如果是搜索页面这里点击更多,就触发这个事件:

if(this.data.isSearch == 1) {
    this.triggerEvent('more');
    return false;
}

// 非搜索页面正常跳转...

这样,在搜索页只需要在doMore方法里面切换顶部菜单显示就可以了。

ERROR 1170 (42000): BLOB/TEXT column 'content' used in key specification without a key length

这个错误出现在给表建索引时包含了TEXTBLOB类型字段,这里的content就是一个TEXT字段。为什么这些类型的字段建立索引会出错呢?这些类型不能建立索引吗?

其实,是可以建立索引的。但是MySQL只能对TEXTBLOBN个字符建立索引。根据MySQL官网文档描述,可以知道,MySQL对于字符串类型都只能对前N个加索引,在对VARCHARCHAR等加索引时,没有出现这个错误,是因为VARCHARCHAR已经指定了长度,所以在建立索引时不是必须指定长度的,而TEXTBLOB则是必须得。

另外,根据Column Prefix Key Parts部分描述,还可以看到,对于长度是有限制的。单位为bytes,在InnoDB表里长度限制为767BMyISAM表里长度限制为1000BInnoDB有个配置innodb_large_prefix开启后,长度限制增加到3072B。这个选项在MySQL 5.7里面默认开启,在8.0里面已经移除。

腾讯地图在zui(bootstrap)的modal中不能显示报错:Uncaught far <= 0

在使用腾讯地图过程中,遇到一个十分奇怪的问题.在页面中可以正常渲染地图,但是放在弹层modal中,却无法正常显示,地图SDK直接无法正常工作,在控制台出现错误:


经过一番测试发现,影响地图的是display:none.只要渲染地图的div或其父级以上层级存在display:none,均无法工作

无法显示示例

不知道SDK内部是作了怎样的一种考虑,由于业务必须使用弹层,而弹层也是要隐藏的,这就造成了矛盾.对此解决办法只有改变一下角度,自己实现一个弹层,这个弹层的隐藏不再由display来控制,而是定位,把它放在屏幕外边以实现隐藏.

elasticsearch基于脚本的排序

elasticsearch排序一般是按照相关性分数(relevance score)排序,或者mapping中其他字段.除此之外,elasticsearch还可以自己编写脚本来对结果排序.基本用法如下:

'sort' => [
    '_script' => [
        'script' => [
            'lang' => 'painless',
            'source' => "排序算法代码",
            'params' => [
                // 传入source中的参数
            ],
        ],
        'order' => 'asc/desc'
    ]
],

lang指定脚本的语言, painlesselasticsearch的默认脚本语言.source是写代码的地方.paramssource中需要传入的参数.painless语法在这里

Uncaught SyntaxError: Bad control character in string literal in JSON at position

在后台模板页面中,有一段JSON字符串数据需要前端jsJSON解析,前端在做JSON.parse时,出现错误:

Uncaught SyntaxError: Bad control character in string literal in JSON at position 90
at JSON.parse (<anonymous>)
...

这个功能在某些参数值传入时会出现,其他的又不会,对比两边数据后发现,出错的数据里面有个字段包含了换行符(\r\n)导致,如果去掉换行符就可以正常解析了,但是不可能全部去掉换行符,一是麻烦,二是这会改变原文的段落结构,三是不符合现实需求.解决方法其实也很简单,在调用JSON.parse之前,我们先对数据进行JSON.stringify,这样就不会解析出错了.

最后有一点需要注意,JSON.stringify不要使用'"把后台的模板变量包裹起来.

Phalcon的volt视图页面中使用vue

phalconPHP的一个mvc框架,volt是什么?voltphalcon的视图模板引擎.volt页面中能混用vuejs吗?可以的.为什么要混用呢?像这样一个页面:

页面中的关联题库表格使用vuev-for来渲染,题目抽取与得分设置使用计算属性是十分方便的,但是有一点问题:volt使用双大括号{{}}来输出变量值到模板页面,vue也一样,就会冲突.那么怎么解决冲突呢?

首先,在下载vue的时候,我们可以看到vue有很多版本,比如: unpkg或者cdnjs都有提供global,runtime,esm等等版本.因为不会编译,所以选择global版.接下来就是页面引入vue

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.2.45/vue.global.min.js"></script>

使用vue,主要是加入参数delimiters替换{{}}:

<script>
    const {createApp} = Vue

    const app = createApp({
        delimiters: ['{!', '!}']
    }).mount('#app')
</script>

其他就可以正常使用啦.

解决SimpleAjaxUpload特殊样式中hover冲突造成按钮不显示问题

SimpleAjaxUploader是一个很棒的上传插件,使用十分方便。但是,在有鼠标移入移出效果中使用该插件时就会出现问题,如下面这个页面有这样一个方框,鼠标移入后显示蒙层和两个按钮:

在没有加入SimpleAjaxUploader插件前效果是OK的,当页面引入js插件后并初始化后,就出问题了,看下图:

可以看到,鼠标移入方框后,显示还是正常的,但是当移到上传图片按钮上时,背景突然就没了,按钮也不显示了。这是为什么呢?通过观察页面的HTML结构,比对移入移出时的变化发现造成
这一结果的原因是:上传插件在body中插入了divinput然后绝对定位到了按钮的位置,这样当我们眼睛看着是输入移到了上传图片按钮上,实际是移到了插入的divinput上,而插入的
divinput并不是外面大方框的子元素,所以,方框的hover样式不再生效,我们自己的蒙层也就隐藏了。

那么应该如何解决呢?现在应该很简单了,只要让divinput插入到我们自己的方框里面作为其子元素存在并且给父级元素加上position: relative就可以了。为了不影响其他地方其他的样式使用,
我们需要给它新增一个参数,默认为body,在需要的地方传入自己的元素。具体修改步骤:

  1. 在SimpleAjaxUploader.js的687行添加一个参数:
container: 'body'
  1. 在SimpleAjaxUploader.js的2079行,这里原来是默认插入到body中,替换为:
document.querySelector(self._opts.container).appendChild(div);

改好之后再页面中检测一下,已经不在受影响了。

点击这里试试吧

超大视频文件分片上传

普通上传

在使用ajax文件上传,一般分3个步骤:

  1. HTML

HTML中有一个input用于选择文件:

<input type="file" id="selectFile" />

可以通过accept属性用于限制选择视频文件还是图片以及视频和图片具体是哪种类型.

<input type="file" id="selectFile" accept=".mp4"/>
或
<input type="file" id="selectFile" accept="image/*"/>
  1. js监听事件
$('#selectFile').on('change', function() {
    let file = this.files[0];
});
  1. 上传
const fd = new FormData();
fd.append('file', file);
const xhr = new XMLHttpRequest();

xhr.open('POST', api);

// 上传进度
xhr.upload.addEventListener('progress', function (ev) {
    var progress = ((ev.loaded / ev.total) * 100).toFixed(2) + '%';
    
});

// 上传结果
xhr.onreadystatechange = () => {
    if(xhr.readyState === 4 && xhr.status === 200){
        
    }
}

xhr.send(fd);

但是对于视频,如一部电影,直接用上面的方式上传,有可能遇到的问题:

  • 超时
  • 超出大小限制

这时候就需要分片上传文件.

阅读全文

elasticsearch ERROR: [1] bootstrap checks failed

  • 问题

elasticsearch启动之后出现错误:

ERROR: [1] bootstrap checks failed. You must address the points described in the following [1] lines before starting Elasticsearch.
bootstrap check failure [1] of [1]: system call filters failed to install; check the logs and fix your configuration or disable system call filters at your own risk
ERROR: Elasticsearch did not exit normally - check the logs at /data/elasticsearch/elasticsearch-7.16.2/logs/elasticsearch.log

在错误中提到的日志文件elasticsearch.log中查看:

[2022-12-06T17:09:36,977][WARN ][o.e.b.JNANatives         ] [VM-16-8-centos] unable to install syscall filter:
java.lang.UnsupportedOperationException: seccomp unavailable: CONFIG_SECCOMP not compiled into kernel, CONFIG_SECCOMP and CONFIG_SECCOMP_FILTER are needed
        at org.elasticsearch.bootstrap.SystemCallFilter.linuxImpl(SystemCallFilter.java:347) ~[elasticsearch-7.16.2.jar:7.16.2]
        at org.elasticsearch.bootstrap.SystemCallFilter.init(SystemCallFilter.java:638) ~[elasticsearch-7.16.2.jar:7.16.2]
        at org.elasticsearch.bootstrap.JNANatives.tryInstallSystemCallFilter(JNANatives.java:255) [elasticsearch-7.16.2.jar:7.16.2]
        at org.elasticsearch.bootstrap.Natives.tryInstallSystemCallFilter(Natives.java:102) [elasticsearch-7.16.2.jar:7.16.2]
        at org.elasticsearch.bootstrap.Bootstrap.initializeNatives(Bootstrap.java:112) [elasticsearch-7.16.2.jar:7.16.2]
        at org.elasticsearch.bootstrap.Bootstrap.setup(Bootstrap.java:183) [elasticsearch-7.16.2.jar:7.16.2]
        at org.elasticsearch.bootstrap.Bootstrap.init(Bootstrap.java:434) [elasticsearch-7.16.2.jar:7.16.2]
        at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:166) [elasticsearch-7.16.2.jar:7.16.2]
        at org.elasticsearch.bootstrap.Elasticsearch.execute(Elasticsearch.java:157) [elasticsearch-7.16.2.jar:7.16.2]
        at org.elasticsearch.cli.EnvironmentAwareCommand.execute(EnvironmentAwareCommand.java:77) [elasticsearch-7.16.2.jar:7.16.2]
        at org.elasticsearch.cli.Command.mainWithoutErrorHandling(Command.java:112) [elasticsearch-cli-7.16.2.jar:7.16.2]
        at org.elasticsearch.cli.Command.main(Command.java:77) [elasticsearch-cli-7.16.2.jar:7.16.2]
        at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:122) [elasticsearch-7.16.2.jar:7.16.2]
        at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:80) [elasticsearch-7.16.2.jar:7.16.2]
  • 处理

elasticsearch配置文件,如:/etc/elasticsearch/elasticsearch.yml中添加一行配置:

bootstrap.system_call_filter: false

再次启动,elasticsearch正常运行。