既然做了,就要做得绝。既然开了 Pjax,那就要真正实现全站无刷。
在实现评论 Ajax 之前,我在网上也找了几篇教程学习了一下,大部分都是用 jQuery 实现的,但是并不是每个主题都会引入 jQuery 的,其次为了实现 Ajax 而引入 jQuery 并不值得去这么做。所以我选择用原生的方式去实现。
首先,我们要知道表单提交的时候,浏览器发起了什么请求,请求报文有哪些。在评论时,浏览器会发起 POST 请求,请求体中的数据有评论者的信息(name, url, mail, text),注意需要判断用户是否登陆,如果登陆,就只有 text
.
可以用 dom 元素的 value
属性获取用户表单的数据,然后发起 ajax 请求。请求地址这可以从表单上的 action
属性获取。当前我们还需要将响应报文中的 dom 元素提取需要的部分,进行替换。还可以加点过度动画等等,需要注意的是别忘了重载某些方法,和阻止默认提交事件。
下面贴上完整代码
js
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()
实现,原生方法亦可。
使用以上实现方法的主题: