# 起因
由于文章的编辑是使用 title
和 content
两个响应式变量双向绑定着编辑区的输入框
变量:
1
let
1
<input id="input-title" placeholder="请输入标题" v-model="title" />
使用 articleId
作为当前浏览的文章,当监听到 articleId 的变化,则会通过网络请求更新 title
和 content
:
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
方法会向服务器发送修改请求,于是本该在内容被编辑时触发的请求却在切换文章时由于填充 title
和 content
时被触发,导致文章的修改时间被切换时覆盖。
# 解决方法
添加一个变量作为锁,锁住 saveArticle
的触发,并在触发后解锁,保证正常的编辑能够正常触发 saveArticle
,在监听 articleId
的变化时 (组件通过监听 articleId
变化来确定当前浏览的文章更改 ),将锁开启,并在触发 title
和 content
之后将锁解锁,即可。
# 实现
定义锁
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)
})
}
}
)
在 监听到 title
和 content
的变化时,根据锁的状态,拦截启动 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 // 触发后解锁,则不会影响正常使用
}
})