前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >为 Typecho 主题开启 Ajax 评论真正实现全站无刷

为 Typecho 主题开启 Ajax 评论真正实现全站无刷

作者头像
Innei
发布2021-12-28 14:28:57
发布2021-12-28 14:28:57
1K00
代码可运行
举报
文章被收录于专栏:静之森静之森
运行总次数:0
代码可运行

既然做了,就要做得绝。既然开了 Pjax,那就要真正实现全站无刷。

前言

在实现评论 Ajax 之前,我在网上也找了几篇教程学习了一下,大部分都是用 jQuery 实现的,但是并不是每个主题都会引入 jQuery 的,其次为了实现 Ajax 而引入 jQuery 并不值得去这么做。所以我选择用原生的方式去实现。

实现过程

首先,我们要知道表单提交的时候,浏览器发起了什么请求,请求报文有哪些。在评论时,浏览器会发起 POST 请求,请求体中的数据有评论者的信息(name, url, mail, text),注意需要判断用户是否登陆,如果登陆,就只有 text.

可以用 dom 元素的 value 属性获取用户表单的数据,然后发起 ajax 请求。请求地址这可以从表单上的 action 属性获取。当前我们还需要将响应报文中的 dom 元素提取需要的部分,进行替换。还可以加点过度动画等等,需要注意的是别忘了重载某些方法,和阻止默认提交事件。

下面贴上完整代码

js

代码语言:javascript
代码运行次数:0
复制
1class Comment {
2
3    static comment_init() {
4      const commentsReply = document.querySelectorAll('span.comment_reply > a')
5      const replyForm = document.querySelector('.reply')
6      const isComment = document.querySelector('.post-form.is-comment')
7      for (let el of commentsReply) {
8        el.addEventListener('click', e => {
9          // 给恢复按钮绑定事件 获取parent-id
10          const href = e.target.getAttribute('href')
11          window.parentId = href.match(/replyTo=(\d+)/)[1]
12          // 弹出回复框
13          replyForm.removeAttribute('style')
14          if (isComment.classList.contains('active')) isComment.classList.remove('active');
15          setTimeout(() => {
16            document.getElementById('cancel-comment-reply-link').addEventListener('click', () => {
17              replyForm.style.display = 'none';
18            })
19          })
20        })
21      }
22    }
23  }
24
25  Comment.comment_init()
26
27  // ajax 提交评论实现方法
28
29  // 阻止默认事件
30  const form = document.getElementById('comment-form')
31  form.addEventListener('submit', function (e) {
32    e.preventDefault();
33    post_by_ajax(e, '#comment-form')
34  });
35
36  const reply_form = document.querySelector('.reply_form')
37  reply_form.addEventListener('submit', function (e) {
38    e.preventDefault();
39    post_by_ajax(e, '.reply_form', true)
40  });
41
42
43  // ajax 提交
44  function post_by_ajax(e, sel, reply = false) {
45    const isComment = document.querySelector('.post-form.is-comment')
46    const commentForm = document.querySelector(sel)
47    const post_url = e.target.getAttribute('action')
48    const cookie = document.cookie
49    const referer = window.location.href
50    const domParser = new DOMParser()
51    const dom = str => domParser.parseFromString(str, 'text/html')
52
53    // 如果是管理员登陆
54    if (!document.querySelector('#comment-form #author')) {
55      const text = commentForm.querySelector('#text').value
56      let data = null
57
58      if (reply) {
59        data = {
60          text, parent: window.parentId
61        }
62      } else {
63        data = {
64          text
65        }
66      }
67      ks.ajax({
68        url: post_url,
69        method: 'POST',
70        data,
71        success(res) {
72          const responseDOM = dom(res.responseText)
73
74          try {
75            isComment.classList.contains('active') ? isComment.classList.remove('active') : false
76            const needPartten = responseDOM.querySelector('.comment-list').innerHTML
77            needPartten === document.querySelector('.comment-list').innerHTML ? ks.notice("请等待审核哦 φ(>ω<*) ", {
78              color: "green",
79              time: 1000
80            }) : (document.querySelector('.comment-list').innerHTML = needPartten, ks.notice("评论成功了 (〃'▽'〃)", {
81              color: "green",
82              time: 1000
83            }), (reply ? false : window.scrollSmoothTo(document.body.scrollHeight || document.documentElement.scrollHeight)))
84
85          } catch (e) {
86            ks.notice(responseDOM.querySelector('.container').innerText, {
87              color: "red",
88              time: 1500
89            })
90          }
91          Comment.comment_init()
92        },
93        failed(res) {
94          console.log(res)
95          ks.notice("(;´д`)ゞ 失败了", {
96            color: 'red',
97            time: 1500
98          })
99        }
100      })
101    } else {
102      const author = commentForm.querySelector('#author').value
103      const mail = commentForm.querySelector('#mail').value
104      const url = commentForm.querySelector('#url').value
105      const text = commentForm.querySelector('#text').value
106
107      if (reply) {
108        data = {
109          author, mail, url, text, parent: window.parentId
110        }
111      } else {
112        data = {
113          author, mail, url, text,
114        }
115      }
116
117      ks.ajax({
118        method: "POST",
119        url: post_url,
120        data,
121        success(res) {
122          const responseDOM = dom(res.responseText)
123          isComment.classList.contains('active') ? isComment.classList.remove('active') : false
124          try {
125            const needPartten = responseDOM.querySelector('.comment-list').innerHTML
126            needPartten === document.querySelector('.comment-list').innerHTML ? ks.notice("请等待审核哦 φ(>ω<*) ", {
127              color: "green",
128              time: 1000
129            }) : (document.querySelector('.comment-list').innerHTML = needPartten, ks.notice("评论成功了 (〃'▽'〃)", {
130              color: "green",
131              time: 1000
132            }), (reply ? false : window.scrollSmoothTo(document.body.scrollHeight || document.documentElement.scrollHeight)))
133            Comment.comment_init()
134          } catch (e) {
135            ks.notice(responseDOM.querySelector('.container').innerText, {
136              color: "red",
137              time: 1500
138            })
139          }
140
141        }
142        ,
143        failed(res) {
144          console.log(res)
145          ks.notice("(;´д`)ゞ 失败了", {
146            color: 'red',
147            time: 1500
148          })
149        }
150      })
151
152    }
153    return false
154  }

COPY

后续说明

在完成 Ajax 请求后,我做了两件事。

第一,判断是否评论成功,如果失败则弹出信息框,说明原因。成功则重载方法,并用平滑移动等方法跳转到新评论的地方。

第二,评论成功后,收回评论框。

由于在项目中使用了 Kico Style ,所以 Ajax 请求由 ks.ajax() 实现,原生方法亦可。

使用以上实现方法的主题:

Paul

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-06-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 实现过程
  • 后续说明
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档