1). 添加编辑文章路由
打开 src/router/routes.js 文件,在数组的最后面,添加编辑文章路由 Edit:
src/router/routes.js
1 // Edit
2 {
3 path: '/articles/:articleId/edit',
4 name: 'Edit',
5 component: () => import('@/views/articles/Create'),
6 meta: { auth: true }
7 },
我们这里使用了跟 Create 一样的组件页面,但将其路径指向一个新的地址,并命名为 Edit。
2). 添加编辑入口
1、打开 src/views/articles/Content.vue 文件,复制以下代码替换原 <script>:
src/views/articles/Content.vue
1 <script>
2 import SimpleMDE from 'simplemde'
3 import hljs from 'highlight.js'
4 import emoji from 'node-emoji'
5 import { mapState } from 'vuex'
6
7 export default {
8 name: 'Content',
9 data() {
10 return {
11 title: '', // 文章标题
12 content: '', // 文章内容
13 date: '', // 文章创建时间
14 uid: 1 // 用户 ID
15 }
16 },
17 computed: {
18 ...mapState([// 将仓库的以下状态混入到计算属性之中
19 'auth',
20 'user'
21 ])
22 },
23 created() {
24 const articleId = this.$route.params.articleId
25 const article = this.$store.getters.getArticleById(articleId)
27 if (article) {
28 let { uid, title, content, date } = article
30 this.uid = uid
31 this.title = title
32 this.content = SimpleMDE.prototype.markdown(emoji.emojify(content, name => name))
33 this.date = date
35 this.$nextTick(() => {
36 this.$el.querySelectorAll('pre code').forEach((el) => {
37 hljs.highlightBlock(el)
38 })
39 })
40 }
41
42 this.articleId = articleId
43 },
44 methods: {
45 editArticle() {
46 this.$router.push({ name: 'Edit', params: { articleId: this.articleId } })
47 },
48 deleteArticle() {
49
50 }
51 }
52 }
53 </script>
2、查找 <div class="markdown-body",在其后面添加『编辑删除图标』:
1 <div class="markdown-body" v-html="content"></div> 2 3 <!-- 编辑删除图标 --> 4 <div v-if="auth && uid === 1" class="panel-footer operate"> 5 <div class="actions"> 6 <a @click="deleteArticle" class="admin" href="javascript:;"><i class="fa fa-trash-o"></i></a> 7 <a @click="editArticle" class="admin" href="javascript:;"><i class="fa fa-pencil-square-o"></i></a> 8 </div> 9 </div>
我们先判断用户是否已登录,已登录且当前用户 ID 为 1 时,渲染编辑删除图标。
3). 添加编辑文章逻辑
打开 src/store/actions.js 文件,复制以下代码替换原 post 事件:
src/store/actions.js
1 export const post = ({ commit, state }, { article, articleId }) => {
2 let articles = state.articles
3
4 if (!Array.isArray(articles)) articles = []
5
6 if (article) {
7 const uid = 1
8 const { title, content } = article
9 const date = new Date()
10
11 if (articleId === undefined) {
12 const lastArticle = articles[articles.length - 1]
13
14 if (lastArticle) {
15 articleId = parseInt(lastArticle.articleId) + 1
16 } else {
17 articleId = articles.length + 1
18 }
19
20 articles.push({
21 uid,
22 articleId,
23 title,
24 content,
25 date
26 })
27 }else { // 如果有传 articleId
28 // 遍历所有文章
29 for (let article of articles) {
30 // 找到与 articleId 对应的文章
31 if (parseInt(article.articleId) === parseInt(articleId)) {
32 // 更新文章的标题
33 article.title = title
34 // 更新文章的内容
35 article.content = content
36 break
37 }
38 }
39 }
40 commit('UPDATE_ARTICLES', articles)
41 router.push({ name: 'Content', params: { articleId, showMsg: true } })
42 }
43 }
4). 修改创作文章页面
1、打开 src/views/articles/Create.vue 文件,复制以下代码替换原 <script>:
src/views/articles/Create.vue
1 <script>
2 import SimpleMDE from 'simplemde'
3 import hljs from 'highlight.js'
4 import ls from '@/utils/localStorage'
5
6 window.hljs = hljs
7
8 export default {
9 name: 'Create',
10 data() {
11 return {
12 articleId: undefined // 文章 ID
13 }
14 },
15 beforeRouteEnter(to, from, next) {
16 next(vm => {
17 // 确认渲染组件的对应路由时,设置 articleId
18 vm.setArticleId(vm.$route.params.articleId)
19 })
20 },
21 // 在离开该组件的对应路由前
22 beforeRouteLeave(to, from, next) {
23 // 清空自动保存的文章数据
24 this.clearData()
25 next()
26 },
27 watch: {
28 // 监听路由参数的变化
29 '$route'(to) {
30 // 清空自动保存的文章数据
31 this.clearData()
32 // 设置 articleId
33 this.setArticleId(to.params.articleId)
34 }
35 },
36 methods: {
37 // 填充文章数据
38 fillContent(articleId) {
39 // 编辑器
40 const simplemde = this.simplemde
41 // 自动保存的标题
42 const smde_title = ls.getItem('smde_title')
43
44 // 有 articleId 时
45 if (articleId !== undefined) {
46 // 获取对应文章
47 const article = this.$store.getters.getArticleById(articleId)
48
49 if (article) {
50 // 获取文章的标题和内容
51 const { title, content } = article
52
53 // 有自动保存的标题时,使用自动保存的标题,否则使用文章的标题
54 this.title = smde_title || title
55 // 有自动保存的内容时,使用自动保存的内容,否则使用文章的内容
56 this.content = simplemde.value() || content
57 // 设置编辑器的内容
58 simplemde.value(this.content)
59 }
60 } else { // 没有 articleId 时,使用自动保存的标题和内容
61 this.title = smde_title
62 this.content = simplemde.value()
63 }
64 },
65 post() {
66 if (title !== '' && content.trim() !== '') {
67 // 在分发 post 事件时,附带 articleId 参数
68 this.$store.dispatch('post', { article, articleId: this.articleId })
69 }
70 },
71 // 设置 articleId
72 setArticleId(articleId) {
73 // 获取 localStorage 保存的 articleId,临时用它来判断是否还处于当前编辑页面
74 const localArticleId = ls.getItem('articleId')
75
76 // 手动在两个不同的编辑页面之间跳转时(如 /articles/1/edit 和 /articles/2/edit)时
77 if (articleId !== undefined && !(articleId === localArticleId)) {
78 // 清空自动保存的文章数据
79 this.clearData()
80 }
81
82 // 设置当前实例的 articleId
83 this.articleId = articleId
84 // 填充文章数据
85 this.fillContent(articleId)
86 // 在 localStorage 保存一个 articleId
87 ls.setItem('articleId', articleId)
88 }
89 }
90 </script>
上面代码的核心就是利用路由参数的 articleId,获取对应的文章数据,来填充编辑页面。在不同的编辑页面之间跳转(如 /articles/1/edit 和 /articles/2/edit)时,因为我们会优先填充自动保存的数据,所以需要先调用 clearData 清空它们。
涉及的新知识点:
1 beforeRouteLeave(to, from, next) {
2 this.clearData()
3 next()
4 }
beforeRouteLeave 是组件内的守卫,在离开该组件的对应路由时调用,此时可以访问 this,需要使用 next() 确认导航。
监听 '$route':
1 watch: {
2 '$route'(to) {
3 this.clearData()
4 this.setArticleId(to.params.articleId)
5 }
6 }
我们可以通过监听 '$route' 来得知路由参数的变化,我们通常会在两个路由都渲染相同的组件时监听 '$route',这是因为 Vue 会复用组件实例,以导致组件内的部分钩子不再被调用。举例来说,我们的『编辑文章』和 『创作文章』都使用 Create.vue 组件,当我们从『编辑文章』导航到『创作文章』时(在编辑文章页面点击创作文章按钮),beforeRouteEnter 就不会被调用,所以我们需要监听 '$route',以响应路由参数的变化。
2、查找 <h2 class="text-center">,作如下修改:
1 <!-- 修改 -->
2 <h2 class="text-center">创作文章</h2>
3 <!-- 为 -->
4 <h2 class="text-center">{{ articleId ? '编辑文章' : '创作文章' }}</h2>
来源:https://www.cnblogs.com/yangguoe/p/9318320.html