href='javascript:'在firefox与chrome中的不同表现

在前端开发中,我们经常会使用<a>标签来实现页面跳转,而href属性是<a>标签中最重要的属性之一。href除了可以指定跳转的链接外,还可以指定一些特殊值,比如href="javascript:"。这样能执行一段js代码,比如alert('hello')。现在就遇到了一个问题,在chrome中,href="javascript:"可以执行js代码,但是在firefox中虽然也执行了,但是结果却不是我们想要的。比如这样一段代码:

<a href="javascript:layer.msg('请下载APP')">我要报名</a>

在firefox中执行结果:

firefox中的结果

在chrome中执行结果:

chrome中的结果

firefox中执行了js代码,但是最后整个HTML页面内容变成了一个3。数字3是哪里来的呢?而chrome中执行了js代码,并且页面内容也正常显示。要解决这个问题,最简单的办法就是使用onclick属性,而不是href属性。

<a href="#" onclick="layer.msg('请下载APP');return false;">我要报名</a>

在firefox中执行结果:

firefox中的结果

经过测试发现,在firefox中,href="javascript:"后面的代码如果有返回值,不论这个值是布尔值,数字,或者字符串,那么firefox就会把整个HTML页面内容变成返回值。

firefox中的结果

而在chrome中,href="javascript:"后面的代码如果有返回值,如果是数字,布尔值,那么chrome会忽略返回值,如果是字符串,那么chrome也会把字符串显示在页面中。

MDN有这么一段话:

JavaScript URLs, URLs prefixed with the javascript: scheme, are used as fake navigation targets that execute JavaScript when the browser attempts to navigate. If the URL evaluates to a string, it is treated as HTML and rendered by the browser.

最后一句说了,如果URL解析后是一个字符串,那么浏览器会把它当作HTML来渲染。但明显firefox执行了更严格的规则,所有的返回值都会被当作HTML来渲染。

用Multi-stage builds给你的docker镜像瘦身

为什么别人的docker镜像很小?为什么我们的docker镜像很大?因为我们的Dockerfile编写姿势不对。比如这样一个Dockerfile:

FROM centos:7

#init
WORKDIR /home
RUN mkdir ffmpeg_sources ffmpeg_build
RUN yum -y update && yum install -y \
  autoconf \
  automake \
  bzip2 \
  bzip2-devel \
  cmake \
  freetype-devel \
  gcc \
  gcc-c++ \
  git \
  libtool \
  make \
  pkgconfig \
  zlib-devel \
  openssl \
  openssl-devel \
  python3

#ffmpeg extensions
#NASM
WORKDIR /home/ffmpeg_sources
RUN curl -O -L https://www.nasm.us/pub/nasm/releasebuilds/2.15.05/nasm-2.15.05.tar.bz2 && tar xjvf nasm-2.15.05.tar.bz2
WORKDIR nasm-2.15.05
RUN ./autogen.sh && ./configure --prefix="/home/ffmpeg_build" --bindir="/usr/local/bin" && make && make install

#Yasm
WORKDIR /home/ffmpeg_sources
COPY ./lib/yasm-1.3.0.tar.gz .
RUN tar xzvf yasm-1.3.0.tar.gz
WORKDIR yasm-1.3.0
RUN ./configure --prefix="/home/ffmpeg_build" --bindir="/usr/local/bin"
RUN make && make install

#libx264
WORKDIR /home/ffmpeg_sources
COPY ./lib/x264 ./x264
WORKDIR x264
ENV PKG_CONFIG_PATH="/home/ffmpeg_build/lib/pkgconfig"
RUN ./configure --prefix="/home/ffmpeg_build" --bindir="/usr/local/bin" --enable-static
RUN make && make install

#libx265
WORKDIR /home/ffmpeg_sources
COPY lib/x265_git ./x265_git
RUN cd ./x265_git/build/linux && cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX="/home/ffmpeg_build" -DENABLE_SHARED:bool=off ../../source && make && make install

#libfdk_aac
WORKDIR /home/ffmpeg_sources
COPY lib/fdk-aac ./fdk-aac
WORKDIR fdk-aac
RUN autoreconf -fiv
RUN ./configure --prefix="/home/ffmpeg_build"
RUN make && make install

#libmp3lame
WORKDIR /home/ffmpeg_sources
COPY lib/lame-3.100.tar.gz ./
RUN tar xzvf lame-3.100.tar.gz
WORKDIR lame-3.100
RUN ./configure --prefix="/home/ffmpeg_build" --bindir="/usr/local/bin" --enable-nasm
RUN make && make install

#libopus
WORKDIR /home/ffmpeg_sources
COPY lib/opus-1.3.1.tar.gz ./opus-1.3.1.tar.gz
RUN tar xzvf opus-1.3.1.tar.gz
WORKDIR opus-1.3.1
RUN ./configure --prefix="/home/ffmpeg_build"  --disable-shared
RUN make && make install

#libvpx
WORKDIR /home/ffmpeg_sources
COPY lib/libvpx ./libvpx
WORKDIR libvpx
RUN ./configure --prefix="/home/ffmpeg_build" --disable-examples --disable-unit-tests --enable-vp9-highbitdepth --as=yasm
RUN make && make install

#ffmpeg
WORKDIR /home/ffmpeg_sources
COPY lib/ffmpeg-snapshot.tar.bz2 .
RUN tar xjvf ffmpeg-snapshot.tar.bz2
WORKDIR ffmpeg
ENV PATH="/usr/local/bin:$PATH" PKG_CONFIG_PATH="/home/ffmpeg_build/lib/pkgconfig"
RUN ./configure \
  --prefix="/home/ffmpeg_build" \
  --pkg-config-flags="--static" \
  --extra-cflags="-I/home/ffmpeg_build/include" \
  --extra-ldflags="-L/home/ffmpeg_build/lib" \
  --extra-libs=-lpthread \
  --extra-libs=-lm \
  --bindir="/usr/local/bin" \
  --enable-gpl \
  --enable-libfdk_aac \
  --enable-libfreetype \
  --enable-libmp3lame \
  --enable-libopus \
  --enable-libvpx \
  --enable-libx264 \
  --enable-libx265 \
  --enable-nonfree \
  --enable-openssl
RUN make && make install

#clean
WORKDIR /home
RUN rm -rf /home/*

RUN pip3 install supervisor

COPY supervisord.conf /etc/

WORKDIR /home
CMD ["/bin/bash"]

虽然,最后做了清理工作,删除了home目录里的所有不需要的内容,但是最后编译的镜像依然很大

v1

但我们如果把它分开:

FROM centos:7

#init
WORKDIR /home
RUN mkdir ffmpeg_sources ffmpeg_build
RUN yum -y update && yum install -y \
  autoconf \
  automake \
  bzip2 \
  bzip2-devel \
  cmake \
  freetype-devel \
  gcc \
  gcc-c++ \
  git \
  libtool \
  make \
  pkgconfig \
  zlib-devel \
  openssl \
  openssl-devel

#ffmpeg extensions
#NASM
WORKDIR /home/ffmpeg_sources
RUN curl -O -L https://www.nasm.us/pub/nasm/releasebuilds/2.15.05/nasm-2.15.05.tar.bz2 && tar xjvf nasm-2.15.05.tar.bz2
WORKDIR nasm-2.15.05
RUN ./autogen.sh && ./configure --prefix="/home/ffmpeg_build" --bindir="/usr/local/bin" && make && make install

#Yasm
WORKDIR /home/ffmpeg_sources
COPY ./lib/yasm-1.3.0.tar.gz .
RUN tar xzvf yasm-1.3.0.tar.gz
WORKDIR yasm-1.3.0
RUN ./configure --prefix="/home/ffmpeg_build" --bindir="/usr/local/bin"
RUN make && make install

#libx264
WORKDIR /home/ffmpeg_sources
COPY ./lib/x264 ./x264
WORKDIR x264
ENV PKG_CONFIG_PATH="/home/ffmpeg_build/lib/pkgconfig"
RUN ./configure --prefix="/home/ffmpeg_build" --bindir="/usr/local/bin" --enable-static
RUN make && make install

#libx265
WORKDIR /home/ffmpeg_sources
COPY lib/x265_git ./x265_git
RUN cd ./x265_git/build/linux && cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX="/home/ffmpeg_build" -DENABLE_SHARED:bool=off ../../source && make && make install

#libfdk_aac
WORKDIR /home/ffmpeg_sources
COPY lib/fdk-aac ./fdk-aac
WORKDIR fdk-aac
RUN autoreconf -fiv
RUN ./configure --prefix="/home/ffmpeg_build"
RUN make && make install

#libmp3lame
WORKDIR /home/ffmpeg_sources
COPY lib/lame-3.100.tar.gz ./
RUN tar xzvf lame-3.100.tar.gz
WORKDIR lame-3.100
RUN ./configure --prefix="/home/ffmpeg_build" --bindir="/usr/local/bin" --enable-nasm
RUN make && make install

#libopus
WORKDIR /home/ffmpeg_sources
COPY lib/opus-1.3.1.tar.gz ./opus-1.3.1.tar.gz
RUN tar xzvf opus-1.3.1.tar.gz
WORKDIR opus-1.3.1
RUN ./configure --prefix="/home/ffmpeg_build"  --disable-shared
RUN make && make install

#libvpx
WORKDIR /home/ffmpeg_sources
COPY lib/libvpx ./libvpx
WORKDIR libvpx
RUN ./configure --prefix="/home/ffmpeg_build" --disable-examples --disable-unit-tests --enable-vp9-highbitdepth --as=yasm
RUN make && make install

#ffmpeg
WORKDIR /home/ffmpeg_sources
COPY lib/ffmpeg-snapshot.tar.bz2 .
RUN tar xjvf ffmpeg-snapshot.tar.bz2
WORKDIR ffmpeg
ENV PATH="/usr/local/bin:$PATH" PKG_CONFIG_PATH="/home/ffmpeg_build/lib/pkgconfig"
RUN ./configure \
  --prefix="/home/ffmpeg_build" \
  --pkg-config-flags="--static" \
  --extra-cflags="-I/home/ffmpeg_build/include" \
  --extra-ldflags="-L/home/ffmpeg_build/lib" \
  --extra-libs=-lpthread \
  --extra-libs=-lm \
  --bindir="/usr/local/bin" \
  --enable-gpl \
  --enable-libfdk_aac \
  --enable-libfreetype \
  --enable-libmp3lame \
  --enable-libopus \
  --enable-libvpx \
  --enable-libx264 \
  --enable-libx265 \
  --enable-nonfree \
  --enable-openssl
RUN make && make install

FROM centos:7

RUN yum update -y && yum install -y python3
RUN pip3 install supervisor

COPY supervisord.conf /etc/
COPY --from=0 /usr/local/bin/ffmpeg /usr/local/bin

CMD ["/bin/bash"]

这样得到的镜像大大缩小了:

v2

ffmpeg安装记录

  • ffmpeg简介

FFmpeg is the leading multimedia framework, able to decode, encode, transcode, mux, demux, stream, filter and play pretty much anything that humans and machines have created. It supports the most obscure ancient formats up to the cutting edge. No matter if they were designed by some standards committee, the community or a corporation. It is also highly portable: FFmpeg compiles, runs, and passes our testing infrastructure FATE across Linux, Mac OS X, Microsoft Windows, the BSDs, Solaris, etc. under a wide variety of build environments, machine architectures, and configurations.

FFmpeg是领先的多媒体框架,能够解码、编码、转码、复用、解复用、流式传输、过滤和播放几乎人类和机器所创建的任何内容。它支持从最古老的晦涩格式到最前沿的格式。无论这些格式是由标准委员会、社区还是公司设计的。它还具有高度可移植性:FFmpeg可以在Linux、Mac OS X、Microsoft Windows、BSDs、Solaris等各种构建环境、机器架构和配置下编译运行,并通过我们的测试基础设施FATE。

  • 下载及安装
git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg
cd ffmpeg

./configure \
 --enable-gpl \
 --enable-version3 \
 --enable-nonfree \
 --enable-shared \
 --enable-libfdk-aac \
 --enable-libfreetype \
 --enable-libmp3lame \
 --enable-libqrencode \
 --enable-libwebp \
 --enable-libx264 \
 --enable-libx265 \
 --enable-openssl
 make
 make install

在安装过程中可能会遇到一些错误,以下是一些常见错误及其解决方法:

  1. 如果出现错误:nasm/yasm not found or too old. Use --disable-x86asm for a crippled build.,可以使用yum安装yasm: yum install yasm

  2. 如果出现错误:ERROR: libfdk_aac not found,可以使用以下命令解决:

git clone --depth 1 https://github.com/mstorsjo/fdk-aac
cd fdk-aac
//里面有个autogen.sh,也可以直接运行./autogen.sh
autoreconf -fiv
./configure --prefix="$HOME/ffmpeg_build" --disable-shared
make
make install
  1. 如果出现错误:ERROR: freetype2 not found using pkg-config,可以使用yum安装freetype-devel: yum install freetype-devel

  2. 如果出现错误:ERROR: libmp3lame >= 3.98.3 not found,可以从https://sourceforge.net/projects/lame/files/latest/download下载并解压,进入目录运行命令:

./configure
make
make install
  1. 如果出现错误:ERROR: libqrencode not found using pkg-config,可以从libqrencode最新release下载地址:https://fukuchi.org/works/qrencode/。下载后解压安装:
tar xzf qrencode-4.1.1.tar.gz
cd qrencode-4.1.1/
./configure
make
make install
  1. 如果出现错误:ERROR: libwebp >= 0.2.0 not found using pkg-config,可以运行命令:
yum install -y libwebp libwebp-devel
  1. 如果出现错误:ERROR: x264 not found using pkg-config,可以运行以下命令解决:
git clone --branch stable --depth 1 https://code.videolan.org/videolan/x264.git
cd x264
./configure --enable-shared --enable-static
make
make install

7.1 运行上面命令后,出现问题,需要nasm

Found no assembler
Minimum version is nasm-2.13
If you really want to compile without asm, configure with –disable-asm.

运行命令:

yum install nasm

nasm安装完后继续安装x264

  1. 如果出现错误:ERROR: x265 not found using pkg-config,可以从x265 release版本下载地址:http://ftp.videolan.org/pub/videolan/x265下载最新版本x265安装。
wget http://ftp.videolan.org/pub/videolan/x265/x265_3.2.tar.gz
tar xzf x265_3.2.tar.gz
cd x265_3.2/build/linux
./make-Makefiles.bash
make
make install
  1. 如果出现错误:ERROR: openssl not found,可以运行命令:
yum install openssl openssl-devel
  1. 所有问题解决安装完成后运行ffmpegffmpeg -version出现错误:ffmpeg: error while loading shared libraries: libavdevice.so.60: cannot open shared object file: No such file or directory
export LD_LIBRARY_PATH=/usr/local/lib:/usr/local/lib64/:/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH

如何使用PHP闭包生成Excel单元格坐标

在处理 Excel 数据时,有时需要根据行号和列号生成对应的单元格坐标。为了实现这一功能,我们可以使用 PHP 闭包来轻松地生成 Excel 单元格坐标。本文将介绍如何使用 PHP 闭包生成 Excel 单元格坐标,以及如何在实际开发中应用这一技巧。

背景知识

在 Excel 中,单元格坐标由列字母和行数字组成,例如 A1、B2 等。在 PHP 中,我们可以使用字符串拼接来构建这样的坐标。然而,在实际开发中,如果我们需要根据行号和列号动态生成坐标,这种方法会变得繁琐且容易出错。例如,当我们需要将一批学生数据导出到 Excel 时,我们可能需要根据行号和列号生成单元格坐标。

$active->setCellValueExplicit('A1', '姓名', DataType::TYPE_STRING2);
$active->setCellValueExplicit('B1', '年龄', DataType::TYPE_STRING2);
$active->setCellValueExplicit('C1', '性别', DataType::TYPE_STRING2);
$active->setCellValueExplicit('D1', '学校', DataType::TYPE_STRING2);

$row = 2;
foreach($data as $item) {
    $active->setCellValueExplicit('A' . $row, $item['name'], DataType::TYPE_STRING2);
    $active->setCellValueExplicit('B' . $row, $item['age'], DataType::TYPE_STRING2);
    $active->setCellValueExplicit('C' . $row, $item['gender'], DataType::TYPE_STRING2);
    $active->setCellValueExplicit('D' . $row, $item['school'], DataType::TYPE_STRING2);
    $row++;
}

我们这样写好了,但第二天需求又变了,我们需要在姓名后加一个生日,第三天,产品说需要在学校前面加一个班级。每次我们都需要自己去改 A、B、C、D。

解决方案

使用 PHP 闭包可以解决这个问题。闭包是一种能够捕获外部变量并在其内部使用的函数。我们可以创建一个闭包函数,该函数接受行号和列号作为参数,并根据这些参数生成相应的单元格坐标。

示例代码

以下是一个使用 PHP 闭包生成 Excel 单元格坐标的示例:

function generateCellCoordinateClosure() {
    $alpha = array_map('chr', range(65, 90));
    $columnIndex = 0;
    return function($row) use($alpha, &$columnIndex) {
        return sprintf('%s%d', $alpha[$columnIndex++], $row);
    };
}

$row = 2;
foreach($data as $item) {
    $alpha = $generateCellCoordinateClosure();
    $active->setCellValueExplicit($alpha($row), $item['name'], DataType::TYPE_STRING2);
    $active->setCellValueExplicit($alpha($row), $item['age'], DataType::TYPE_STRING2);
    $active->setCellValueExplicit($alpha($row), $item['gender'], DataType::TYPE_STRING2);
    $active->setCellValueExplicit($alpha($row), $item['school'], DataType::TYPE_STRING2);
    $row++;
}

在这个示例中,我们定义了一个名为 generateCellCoordinateClosure 的函数,该函数返回一个闭包函数。这个闭包函数接受一个行号作为参数,并使用 $columnIndex 变量生成相应的单元格坐标。最后,我们每调用一次就生成该行下一列的单元格坐标。

总结

使用 PHP 闭包生成 Excel 单元格坐标是一种简单而有效的方法。通过定义一个接受列索引作为参数的函数,我们可以轻松地生成任意列的单元格坐标。这种方法不仅使代码更加简洁,而且减少了出错的可能性。

使用PHP根据html内容生成word文件

引言:

在现代Web开发中,富文本编辑器是一种常见的工具,它允许用户轻松地编写和格式化文本。当需要将这些富文本内容保存为Word文件时,可以使用PHP进行处理。本文将介绍两种实现此目的的方法:无需任何依赖库和使用PHPWord库。

方法一:无任何依赖库

使用纯PHP代码,无需引入任何第三方库,可以直接将富文本内容嵌入到HTML模板中,并将其保存为Word文件。代码示例如下:

$word = <<<EOT
<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-html40">
<head><meta charset="UTF-8" /></head>
<body>
$content
</body>
</html>
EOT;

file_put_contents($file, $word);

这种方法的优点是无需依赖任何第三方库,可以根据需要自定义排版。缺点是需要手动处理样式和布局。

方法二:使用PHPWord库

PHPWord是一个开源的PHP库,可以方便地生成多种文件格式,包括Word、HTML、PDF、RTF和ODT。使用Composer进行安装,然后利用库中提供的功能轻松地将富文本内容转换为Word文件。代码示例如下:

use PhpOffice\PhpWord\Element\Section;
use PhpOffice\PhpWord\IOFactory;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Shared\Html;

$word = new PhpWord();
$section = $word->addSection();
Html::addHtml($section, $content);
$writer = IOFactory::createWriter($word);
$writer->save($file);

结论:

本文介绍了两种使用PHP将富文本内容转换为Word文件的方法。无论是选择手动编写HTML模板,还是使用PHPWord库,都能够满足开发者的需求。在实际应用中,可以根据项目需求和个人喜好来选择合适的方法。

canvas对视频截图报错:Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement'

  • 需求

页面加载完成后,视频如果没有封面图,使用canvas对视频截图作为封面图,并且通过接口传回保存。

  • 实现

canvas对视频截图,十分简单,只需几行代码。

  1. 获取页面中的video
let video = document.getElementById('video');
  1. 创建canvas并设置画布长和宽
let canvas = document.createElement('canvas');
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
  1. 绘制
let ctx = canvas.getContext('2d');
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
  1. 获取图片数据
let dataURI = canvas.toDataURL('image/jpeg');

这里会得到图片的base64数据。但就在这里出现了错误:

Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.

这是因为video的资源地址与当前页面是跨域状态,只需要在video中添加属性:

crossorigin="anonymous"

小程序页面部分下拉刷新解决方案

小程序要下拉刷新,有两种方式:

  1. 整个页面刷新
  2. 局部刷新
  • 整个页面刷新

整体刷新首先需要再页面配置文件(json)中添加配置:

"enablePullDownRefresh": true

添加配置后页面可以下拉,然后再js文件onPullDownRefresh中编写下拉刷新逻辑代码。注:处理完后需调用wx.stopPullDownRefresh()结束下拉刷新,否则真机上页面下拉后不会回到原来的位置。

  • 局部刷新

对于有些页面,如下图:

局部刷新列表

顶部是切换的导航条剩下的是列表,刷新的时候不需要带着导航一起下拉刷新。小程序提供了一个组件:scroll-view。我们只需要使用scroll-view将列表数据包裹起来就可以了。

  • refresher-enabled="true"开启下拉刷新
  • refresher-triggered="{{refresherTrigger}}"控制下拉刷新显示,在数据请求结束后应将refresherTrigger设置为false
  • bindrefresherrefresh="pullDownRefresh"在js文件pullDownRefresh函数中处理下拉刷新逻辑

对于局部刷新,当页面数据较少的时候,我们会遇到一个问题:

阅读全文

使用promise封装小程序网络请求

请求接口数据:

module.exports = {
  request: (params = {url, data}) => {
    wx.showLoading({
      title: '加载中...',
      mask: true
    });

    return new Promise((resolve, reject) => {
      wx.request({
        url: BaseUrl + params.url,
        data: params.data || {},
        header: {
            'Content-Type': 'application/x-www-form-urlencoded',
            // 如果有接口鉴权
            'SIGN': getSign(params.data),
            'APPKEY': ''
        },
        method: 'post',
        success: (resp) => {
          // 根据实际业务调用resolve或者reject
        },
        fail: (err) => {
          console.log(err);
          reject(err)
        },
        complete: () => {
          wx.hideLoading();
        }
      })
    })
  },
}

项目中会有很多接口,我们可以根据功能模块,再独立封装。比如登录,可以新增一个login.js:

const {request} = require('request.js');

module.exports = {
  login: () => {
    // ...
  },

  logout: () => {
    // ...
  }
}

文件上传:


module.exports = {
  upload: ({count = 9, mediaType = ['image', 'video'], sizeType = ['original', 'compressed']} = {}) => {
    return new Promise((topResolve, topReject) => {
      wx.chooseMedia({
        count: count,
        mediaType: mediaType,
        sizeType: sizeType,
        success(res) {
          const {tempFiles} = res
          const all = [];
          for(let i in tempFiles) {
            all.push(new Promise((resolve, reject) => {
                var upTask = wx.uploadFile({
                  url: BaseUrl + 'upload api'
                  filePath: tempFiles[i].tempFilePath,
                  name: '',
                  formData: {},
                  success: (result) => {
                    resolve(JSON.parse(result.data));
                  },
                  fail: (err) => {
                    reject(err);
                  }
                });
              })
            )
          }
          
          Promise.all(all).then(results => {
            topResolve(results);
          }).catch(err => {
            console.log(err);
            topReject(err)
          })
        }
      })
    })
  }
}

小程序页面间事件通信

小程序从版本2.7.3开始支持页面间通信事件。页面之间可以通过传递参数,本地缓存等方法实现数据通信,为什么还要事件通信呢?试想一下这么一个场景,从A页面跳转到了B页面:

wx.navigateTo({
    url: '/pages/B/B'
})

在B页面做了某项操作后返回A页面,因为B页面的操作,数据已经有了新的变化,但是,我们通过wx.navigateBack({delta:1})返回上一级,并不会刷新页面数据。

如果没有事件通信,那么我们只能在返回上一级之前,在本地缓存设置一个变量并赋予一个值,然后再A页面onShow里面判断是否存在这个变量和值是否正确:

onShow(){
    const key = wx.getStorageSync('***');
    if(key && key === '***') {
        // 刷新页面数据
    }
}

这样做能够实现需求,但是有坏处:

  1. onShow在很多场景都会触发,导致过多无意义的缓存数据读取判断
  2. 本地缓存数据过多
  3. 管理不方便

有事件通信后,我们可以在A页面跳转时注册事件

wx.navigateTo({
    url: '/pages/B/B',
    events: {
        refreshEvent: () => {
            // 刷新数据
        }
    }
})

在B页面触发事件

// 首先获取eventChannel
const chan = this.getOpenerEventChannel();
// 触发事件
chan.emit('refreshEvent');
// 如果需要传参数
chan.emit('refreshEvent', {key: val});
wx.navigateBack({delta: 1})

也可以将触发事件逻辑放在wx.navigateBacksuccess回调函数中。这样,就轻松实现回退页面并刷新数据了。最后,需要注意的是:
页面间通信仅支持wx.navigateTo跳转的页面中使用,其他几种跳转页面的方式不支持

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

小程序从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方法里面切换顶部菜单显示就可以了。