# 起因

由于文章的编辑是使用 titlecontent 两个响应式变量双向绑定着编辑区的输入框

变量:

1
let [title, content] = [ref(''), ref('')]

1
<input id="input-title" placeholder="请输入标题" v-model="title" />

使用 articleId 作为当前浏览的文章,当监听到 articleId 的变化,则会通过网络请求更新 titlecontent

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

// 监视articleId如有变化,重新渲染文章列表
watch(
() => props.articleId,
(articleId, prevArticleId) => {
if (articleId == prevArticleId) {
console.error('错误,watch新旧值相等了!')
} else {
// 使用axios 获取文章信息
axios.get(`${server_url}/article/${props.articleId}`).then((results) => {
// 将查询到的文章信息赋给title 和 content 两个响应性变量
title.value = results.data[0].title
content.value = results.data[0].content
initEditor(results.data[0].content)
})
}
}
)

所以当每次切换文章时,重新为编辑器填充的值就会触发 watch ,从而使得 saveArticle 方法被触发:

1
2
3
4
// 监听tite 和 content
watch([title, content], ([newTitle, newContent]) => {
saveArticle(props.articleId, title.value, content.value)
})

又因为 saveArticle 方法会向服务器发送修改请求,于是本该在内容被编辑时触发的请求却在切换文章时由于填充 titlecontent 时被触发,导致文章的修改时间被切换时覆盖。

# 解决方法

添加一个变量作为锁,锁住 saveArticle 的触发,并在触发后解锁,保证正常的编辑能够正常触发 saveArticle ,在监听 articleId 的变化时 (组件通过监听 articleId 变化来确定当前浏览的文章更改 ),将锁开启,并在触发 titlecontent 之后将锁解锁,即可。

# 实现

定义锁

1
let contentUpdateLock = false

在 监听到 articleId 改变时 启动锁:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 监视articleId如有变化,重新渲染文章列表
watch(
() => props.articleId,
(articleId, prevArticleId) => {
if (articleId == prevArticleId) {
console.error('错误,watch新旧值相等了!')
} else {
// 使用axios 获取文章信息
axios.get(`${server_url}/article/${props.articleId}`).then((results) => {
// 将查询到的文章信息赋给title 和 content 两个响应性变量

// 由articleId变化而产生的刷新,锁住
contentUpdateLock = true

title.value = results.data[0].title
content.value = results.data[0].content
initEditor(results.data[0].content)
})
}
}
)

在 监听到 titlecontent 的变化时,根据锁的状态,拦截启动 saveArticle 函数,并且锁启动一次后自动销毁,这样就不会影响正常的编辑(监听 articleId 变化 => 锁激活 => 监听 title 和 content 变化 => 锁拦截调用 saveArticle => 锁自动销毁),而正常进行编辑时,只会 触发 title 和 content 的监听,不会改变 articleId,锁不会被激活,不会阻塞正常编辑的调用。

代码如下:

1
2
3
4
5
6
7
8
9
// 监听 title 和 content
watch([title, content], ([newTitle, newContent]) => {
// 如果被锁住,不可以触发储存方法
if (!contentUpdateLock) {
saveArticle(props.articleId, title.value, content.value)
} else {
contentUpdateLock = false // 触发后解锁,则不会影响正常使用
}
})