Jack Huang's Blog


  • 首页

  • 标签

  • 归档

  • 搜索

Vue2修改对象的属性值视图不更新解决方法

发表于 2022-09-09 | 更新于 2023-01-31

在使用vuejs开发过程中,有时候出现修改对象属性后,视图并没有更新的问题。下面分析其产生原因并给出解决方法。

产生原因

Vue2使用双向数据绑定,当你把一个普通的 JavaScript 对象传入 Vue2 实例作为 data 选项,Vue2 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。

这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在属性被访问和修改时通知变更。

每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据属性记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。

因此,vue2 无法检测 property 的添加或移除。由于 Vue2 会在初始化实例时对 property 执行 getter/setter转化,所以 property 必须在 data 对象上存在才能让 Vue 将它转换为响应式的。对于已经创建的实例,Vue允许动态添加根级别的响应式 property。

解决方法

  • Vue.set()

Vue.set(object,key,value)方法一次只能添加一个属性,例如:

1
this.$set(this.message,'b',"我手一杯 品尝你的美");
  • Object.assign或_.extend()

Object.assign或_.extend()可以往数据对象上添加多个属性,但是需要创建同时包含原属性、新属性的对象,从而有效触发watch()方法。例如:

1
this.message = Object.assign({},this.message,{b:'我手一杯 品尝你的美',c:'留下唇印的嘴'})

参考链接

  1. vue修改对象属性,视图不更新this.$set和Vue.nextTick([callback,context]),by 青争小台.
  2. vue响应式数据-修改对象的属性值,视图不更新,by codeantenna.
  3. Vue3的响应式原理?一篇文章,八张图,三心为你解密~,by Sunshine_Lin.
  4. Vue3响应式原理解析,by liy1wen.

MySQL断电崩溃数据恢复方法

发表于 2022-09-08 | 更新于 2023-07-07

服务器使用wamp提供web服务,因断电导致mysql无法启动。下面记录恢复mysql的方法流程。

服务器配置

  • wampserver 3.2.0
  • apache 2.4.41
  • php 7.3.12
  • mysql 8.0.18

mysql数据库恢复过程

故障表现

mysql后台服务无法启动。查找mysql.log日志文件发现innodb数据库引擎报如下错误,说明mysql表空间损坏,线程在数据页中读取不到需要的 page 和数据,因此判断mysql的innodb奔溃了。

1
[ERROR] InnoDB: Database page corruption on disk or a failed file read of page [page id: space=86, page number=4]. You may have to recover from a backup.

修复方法

启动mysql后台服务

首先使用mysql的Forcing InnoDB Recovery特性,启动mysql后台服务。打开my.ini配置文件,设置如下:

1
innodb_force_recovery=1

再重启mysql后台服务成功。

innodb_force_recovery 可以设置为 1-6,大的值包含前面所有小于它的值的影响。

1
2
3
4
5
6
7
8
9
10
11
1 (SRV_FORCE_IGNORE_CORRUPT): 忽略检查到的 corrupt 页。尽管检测到了损坏的 page 仍强制服务运行。一般设置为该值即可,然后 dump 出库表进行重建。

2 (SRV_FORCE_NO_BACKGROUND): 阻止主线程的运行,如主线程需要执行 full purge 操作,会导致 crash。 阻止 master thread 和任何 purge thread 运行。若 crash 发生在 purge 环节则使用该值。

3 (SRV_FORCE_NO_TRX_UNDO): 不执行事务回滚操作。

4 (SRV_FORCE_NO_IBUF_MERGE): 不执行插入缓冲的合并操作。如果可能导致崩溃则不要做这些操作。不要进行统计操作。该值可能永久损坏数据文件。若使用了该值,则将来要删除和重建辅助索引。

5 (SRV_FORCE_NO_UNDO_LOG_SCAN): 不查看重做日志,InnoDB 存储引擎会将未提交的事务视为已提交。此时 InnoDB 甚至把未完成的事务按照提交处理。该值可能永久性的损坏数据文件。

6 (SRV_FORCE_NO_LOG_REDO): 不执行前滚的操作。恢复时不做 redo log roll-forward。使数据库页处于废止状态,继而可能引起 B 树或者其他数据库结构更多的损坏。

注意:

1
2
3
4
5
6
7
8
9
为了安全,当设置参数值大于 0 后,可以对表进行 select, create, drop 操作,但 insert, update 或者 delete 这类操作是不允许的。MySQL 5.6.15 以后,当 innodb_force_recovery 的值大于等于 4 的时候,InnoDB 表处于只读模式。

在值小于等于 3 时可以通过 select 来 dump 表,可以 drop 或者 create 表。MySQL 5.6.27 后大于 3 的值也支持 DROP TABLE;

如果事先知道哪个表导致了崩溃则可 drop 掉这个表。如果碰到了由失败的大规模导入或大量 ALTER TABLE 操作引起的 runaway rollback,则可 kill 掉 mysqld 线程然后设置 innodb_force_recovery = 3 使数据库重启后不进行 rollback。然后删除导致 runaway rollback 的表;

如果表内的数据损坏导致不能 dump 整个表内容。那么附带 order by primary_key desc 从句的查询或许能够 dump 出损坏部分之后的部分数据;

若使用更高的 innodb_force_recovery 值,那么一些损坏的数据结构可能引起复杂的查询无法运行。此时可能只能运行最基本的 select * from table 语句。

修复备份mysql数据库

使用如下命名自动修复数据库:

1
mysqlcheck -u root -p --all-databases --auto-repair

修复完成后,使用如下命令备份重要数据库的数据:

1
2
3
4
5
6
7
8
9
10
# 备份全部数据库(包含存储过程、自定义函数及事件) 
mysqldump -uroot -p --single-transaction -R -E --all-databases > /tmp/all_database.sql

# 备份指定数据库
mysqldump -uroot -p --single-transaction -R -E --databases db1 > /tmp/db1.sql
mysqldump -uroot -p --single-transaction -R -E --databases db1 db2 > /tmp/db1_db2.sql

# 备份部分表
mysqldump -uroot -pxxxxxx --single-transaction db1 tb1 > /tmp/tb1.sql
mysqldump -uroot -pxxxxxx --single-transaction db1 tb1 tb2 tb3 > /tmp/tb.sql

注意:一定要先修复再备份,防止备份数据时因页表错误丢失数据。

完成修复备份后,注释my.ini中innodb_force_recovery,再重启mysql数据库后台服务,如果成功,则修复完成。如果未成功,则准备利用备份数据重建数据库。

wamp备份修复

当mysql遭遇严重错误,修复备份后仍然不能启动,可考虑重装wamp。具体操作如下:

  • 备份整个wamp文件夹,以便保留mysql数据库文件、apache、php关键配置文件等。
  • 重装wamp后,重建mysql数据库,重设apache、php关键配置,参考之前备份的wamp文件夹
  • apache主要配置httpd.conf和httpd-vhost.conf,设置documentroot和vhost
  • php主要配置php.ini文件
1
2
3
4
5
# 针对mysql 8.0.18,使用如下命令修改root密码
ALTER USER 'root'@'localhost' IDENTIFIED BY '123456'

# 通过增加参数 --default-character-set = utf8 解决乱码问题
mysql -u root -p < path_to_import_file --default-character-set = utf8

重装后配置遇到的问题请参考:

  • 关于Apache本地能访问外网不能访问的问题
  • php中的时区设置和php.ini中配置时区的方法
  • 设置修改 Apache 文件根目录 (Document Root)

参考链接

  1. mysql InnoDB crash and recover,by Fisher.
  2. 利用 Forcing InnoDB Recovery 特性解决 MySQL 重启失败的问题,by GlonHo.
  3. INFORMATION_SCHEMA获取元数据,by 十五十六.
  4. MySQLDump的备份小技巧,by MySQL技术.
  5. MYSQL 自带4个默认数据库,by bolang100.
  6. wamp设置mysql8.0.18初始密码问题,by PHPer.
  7. MySQL字符集和排序规则,by 流逝的傷.
  8. 关于Apache本地能访问外网不能访问的问题,by programminghunter.
  9. php中的时区设置和php.ini中配置时区的方法,by quyu.
  10. 设置修改 Apache 文件根目录 (Document Root),by needrunning.
  11. windows 下自动备份mysql数据库,删除以前的数据库文件,by 森林屿麓.
  12. windows下mysql自动备份脚本,by 雪竹子.

Vuejs生成Doc文档示例

发表于 2022-08-27 | 更新于 2023-04-17

文档生成

请参考使用vue+docxtemplater导出word。

文档预览

请参考docx-preview实现移动端word文件预览。

PDF预览

使用docx-preview的文档预览方案不够完善,显示不够完美,因此采用后端使用docxtemplater文档生成,再使用libreoffice-convert转换成pdf,再下载到前端使用pdfjs预览pdf的方案。

开发环境

  • nodejs: v12.18.4
  • express: “^4.18.2”
  • docxtemplater: “^3.36.1”
  • libreoffice-convert: “^1.4.1”
  • spark-md5: “^3.0.2”
  • pdfjs: 2.16.105

注意:在使用libreoffice-convert将docx转换成pdf之前,需要安装libre office软件,使用默认配置安装。

参考链接

  1. 使用vue+docxtemplater导出word,by 实迷途其未远.
  2. 详细|vue中使用PDF.js预览文件实践,by 灵扁扁.
  3. docx-preview实现移动端word文件预览,by LXLong.
  4. vue项目,npm install方式使用pdfjs,by 下一秒.
  5. Vue 实现 PDF 文件在线预览 - 手把手教你写 Vue PDF 预览功能,by 蒋川.
  6. PDF.js访问远程服务器报file origin does not match viewer’s,by 心灵的学霸.
  7. 深入理解xhr responseType blob arrayBuffer document text json使用,by 柚子=_=.
  8. 【实战分享】js生成word(docx),以及将word转成pdf解决方案分享,by 前端开发小陈.
  9. libreoffice-convert not working in nodejs,by stackoverflow.

Vuejs内联编辑简单示例

发表于 2022-08-27 | 更新于 2022-08-28

示例1

html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<template>
<div class="app-container">
<div v-for="field in fields" :key="field.id" class="editable-field">
<template v-if="editedFieldId === field.id">
<input type="text" v-model="field.value" :ref="`field${field.id}`" />
<button class="btn" @click.prevent="toggleEdit">
<template>Save</template>
</button>
</template>
<template v-else>
<span class="editable-text">
{{ field.value }}
</span>
<button class="btn" @click.prevent="toggleEdit(field.id)">Edit</button>
</template>
</div>
</div>
</template>

js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
export default {
name: "InlineEdit",
props: {},
data() {
return {
editedFieldId: null,
fields: [
{
id: 1,
value: "Editable field 1",
},
{
id: 2,
value: "Editable field 2",
},
],
};
},
created() { },
mounted() { },
methods: {
toggleEdit(id) {
if (id) {
this.editedFieldId = id;
this.$nextTick(() => {
if (this.$refs["field" + id]) {
this.$refs["field" + id][0].focus();
}
});
} else {
this.editedFieldId = null;
}
},
},
};

示例2

html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<template>
<div class="container">
<input
type="text"
v-if="edit"
:value="valueLocal"
@blur="onBlur($event)"
@keyup.enter="onKeyEnter($event)"

v-focus
/>
<span v-else @click="edit = true">
{{ valueLocal }}
</span>
</div>
</template>

js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<script>
export default {
name: "ClickToEdit",
props: ["value"],

data() {
return {
edit: false,
valueLocal: this.value,
};
},

watch: {
value: function () {
this.valueLocal = this.value;
},
},

directives: {
focus: {
inserted(el) {
el.focus();
},
},
},

methods:{
onBlur(ev){
this.valueLocal = ev.target.value;
this.edit = false;
this.$emit('input', this.valueLocal);
},
onKeyEnter(ev){
this.valueLocal = ev.target.value;
this.edit = false;
this.$emit('input', this.valueLocal);
}
}
};
</script>

参考链接

  1. Vue Inline edit,by yobyzal.
  2. Building a form with inline editing,by stackoverflow.
  3. Simple inline editable fields with Vue.js,by devrecipes.

遗传算法简介

发表于 2022-08-21

能够生存下来的往往不是最强大的物种,也不是最聪明的物种,而是最能适应环境的物种。

参考链接

  1. 一文读懂遗传算法工作原理(附Python实现),by 深度学习初学者.

写作技巧集锦

发表于 2022-08-13

删掉“我认为”、“我觉得”、“我相信”等

先写标题

写出音乐感

“triad”(三合音)

CTA = call to action

一寸相框

简单和清晰

不说副词

填满画布

参考链接

  1. 10个实用写作技巧,by happy xiao.

计算相机传感器分辨率和镜头焦距

发表于 2022-08-11

如何计算用于图像采集的正确镜头焦距和相机传感器分辨率?

介绍

首先,定义这些基本术语:

  • 视野 (FOV):相机需要获取的被检查区域
  • 最小特征:图像中要检测的最小特征的大小
  • 工作距离(WD):镜头前端到被检物体的距离

请参考以下图片:

相机成像示意图1

图1 相机成像示意图1

相机成像示意图2

图2 相机成像示意图2

参考连接

  1. Calculating Camera Sensor Resolution and Lens Focal Length,by ni.com.

QT5.12搭建Android开发环境

发表于 2022-07-27

参考链接

  1. Qt for Android环境搭建,by 我来乔23.
  2. 不会Java?没关系,用C/C++搞定安卓APP!Qt for Android开发!,by 嵌入式ARM.

VS2015默认保存文件为UTF8编码的方法

发表于 2022-07-27

Visual Studio(中文版)默认保存的文本文件是GB2312编码(代码页 936)的,默认的行尾(End of line)是CRLF的。在编译C/C++项目时会出现如下警告:

1
warning C4819: The file contains a character that cannot be represented in the current code page (936). Save the file in Unicode format to prevent data loss。

解决方法请参考Visual Studio 默认保存为 UTF8 编码。

参考链接

  1. Visual Studio 默认保存为 UTF8 编码,by 123si.

Web服务器端API响应体的设计

发表于 2022-07-22

后端返回给前端一般用JSON方式,其响应体内容可定义如下:

1
2
3
4
5
response={
code: 200,
message:'成功',
data: Object
}

code的设计可参考http请求返回的状态码。

参考链接

  1. 艺术~如何设计一套优秀的API响应体,by Listen-Y.
  2. API设计系列(二):如何设计一个标准的返回结构的API接口呢?,by 天蓝色.
上一页1…151617…54下一页

Jack Huang

535 日志
69 标签
© 2026 Jack Huang
由 Hexo 强力驱动
|
主题 — NexT.Muse