PHP 如何向前端主动怎么发起众筹操作

(python培训)
(慕课分享学院)
第三方登录:frontopen主题V1.5.04.15版本已发布 推荐更新!
frontopen “讨论区” 正式上线
鸣谢主题捐赠者:感叹帝,Calon YE,孙玉龙,魂客,创想,孜夕寒
顾余笑,小菜,晨风,菠菜,*忠杰,浪子,99开发赞助,IT江湖,小熊
如果发现更新最新版出现缩略图无法显示,请先装回v1.4.03.02版本
关于新人怎么学好php?
关于新人怎么学好php?
围观2714次
编辑日期: 字体:
从自己向别人问怎么学PHP开始,到后来不少人又来问怎么学PHP,不管是新手,还是老
鸟,似乎总是感觉摸不出一条清晰的脉络来,不过,既然学会了PHP,那么我走的这条路或
多或少的有一定借鉴性。
PHP的背景恐怕就不用赘言了,我相信大家选择一种语言,并不是看它的背景和悠久历史,更重要的是看它的实用性,华而不实的语言哪怕是再辉煌的历史,也毕将步向没落,可喜的是PHP经受住了考验,也因此,它确实是一种值得学习的语言。
一直是听从别人的经验长大的,也因此在前辈们的经验里让少走了许多的弯路,更快的步入了正规,在此向那些我至尽不知道其名字的前辈们道声谢谢,在的眼里,帮助不分大小,只要是帮助,总会让的心里暖融融的,我想,前辈们帮助我,并不是为了得到我的一句谢谢,更多的是出于一种责任感和对的期望,所以我想,只有学好PHP,才能对得起前辈们的汗水。
正如我所说的,也终于感觉到了一种责任感,不知道自己的经验到底能帮助新手多少,但是明白,现在到了履行责任的时候了,我有必要把自己的经验告诉给所有希望学好PHP的人,只有这样才能让中国的PHP不断的进步,不断的发展,在世界上占据一席之地。
学习PHP的这段期间,感觉国内的PHP环境越来越成熟,规范也在逐渐的健全,PHPCHINA的成立,标志着与官方直接挂钩的PHP机构在中国正式落户了,在此献上迟到的掌声!
好的,切入正题:
我想在讲述自己的学习方式前,对那些期望能从我的文章中获得有用信息的人说一句心里话:
的文章不会对您的学习起到实质性的作用,您能否成功,还得靠自己的,坚持,坚持,再坚持,就是步入成功的不二法门。
我先把我自己学习PHP的过程做一下概括:
(1)熟悉HTML/CSS/JS等网页基本元素,完成阶段可自行制作完整的网页,对元素属性达到熟悉程度
(2)理解动态语言的概念,运做机制,熟悉PHP语法
(3)学习如何将PHP与HTML结合起来完成简单动态页面
(4)接触MYSQL,开始设计数据库程序
(5)不断巩固,摸透大部分PHP常用函数,并可理解OOP,MYSQL优化,以及模板
(6)完成一个功能齐全的动态站点
我的这套线路可能跟许多学习PHP的爱好者不谋而合,这也算是一个循序渐进的学习过程,不过新手不要看到上面的概括就以为学习蛮简单的,在此不得不对您稍微泼一下冷水,任何东西其实都不简单,即使是小吃部的烧饼也不是一下子就会做成的。
我先解释一下我的学习思路。
首先,理解网站这一概念之后不难看出,任何网站都是由网页组成的,也就是说想完成网站,必须先学会做网页,因此必须要掌握了HTML,才能为今后制作网站打下基础。
在学习HTML中我想边学边做是最有效的方式,当然这一方式对于学习PHP同样是最有效的。
HTML中的任何元素都要亲自实践,只有明白了什么元素会起到什么效果之后,你才会记忆深刻,而一味的啃书,绝对是不行的,我想大部分新手之所以觉得概念难学,大部分是一个字“懒”,懒是阻止进步的最大敌人,所以克服掉懒的习惯,才能更快的学好一样东西。
也许您在学习PHP的时候只想尽快的开发一个网站,也就会想我做网站,干嘛要学什么网页这些小儿科?不难看出,眼高手低的新手不在少数,这种思想无疑于建造空中楼阁,你不建地基,何来的房顶呢?
OK,掌握静态网页的制作技术是学习开发网站的先决条件,这一点就讲到这里,因为这篇文章不是教程文章,也就不对技术进行深入的刨析了。
我假设你目前已经可以完成一个静态页面了,当然,做的好看难看是另外一说,的第一个网页也没好看到哪去,但是“孩子”再丑,咱们做“爹妈”的也不能嫌弃不是?这毕竟是咱的成果。
那么咱们就开始学习动态语言的概念吧,刚一接触动态语言,可能很多人都会蒙了,怎么这乱七八糟的东西,在网页里显示的时候却是另外一码事?其实这并不算乱七八糟,你写的HTML代码不也一样是一堆堆的字符吗?毕竟,代码并不是作为直接输出的,而是经过处理的,说白了,HTML是经过HTML解析器,而PHP当然也就通过PHP解析器了,跟学习HTML一样的道理,想让任何的解析器完成操作,就必须使用它们专用的语法结构,所以PHP长相奇怪也就不足为奇了。
对于PHP的理解是新手最难迈过的一道门槛,不过你应该感到幸运的是PHP已经最大极限的为了新手而努力了,如果你学过其他的语言,也许会觉得PHP的确相当的简单,但是如果你之前什么都没学过,那么阿弥陀佛,硬着头皮琢磨吧。
书过三遍自然熟,这个简单的道理告诉我们,即使你理解不了PHP,但是也必须先跟它混个脸熟,看,一遍遍的看,看的同时一边琢磨,一边按照它所教的打代码,即使你搞不清楚那些代码到底是干嘛的,但是起码你应该找找感觉。
在一段挣扎之后,聪明的你,显然已经逐渐的开悟了,慢慢的理解了编程的概念,那么祝贺你,你已经迈出了成功的第一步。
搞清楚HTML和PHP的概念,那么PHP和HTML混合编程应该不成问题,在这期间,你完全可以让PHP给你算算一加一等于几,然后在浏览器输出,不要觉得幼稚,这的确是跟阿波罗登月一样,你打的是一小段代码,但是对于你的编程之路,可是迈出了一大步啊!兴奋吧?但是不得不再给你泼点冷水,您还是菜鸟一个。
高兴一段时间就必须继续努力了,接下来就是学习数据库了,MYSQL可算是PHP的黄金搭档了,不过,虽然话是这么说,你也可能恨不得把MYSQL给生吞活剥了,因为这一行一列的东东简直让自己头晕目眩。
头晕归头晕,目眩归目眩,你不可能吃饭的时候咬了自己一下舌头就从此不吃饭了不是?放下畏惧,继续努力,咱们是来征服它的,而不是被它征服的,振奋起来吧同志。
在一番搏斗之后,你终于理解了数据库的概念,而且让你兴奋不已的是你终于可以通过PHP来连接数据库了,这期间你是怎么学会的,我们不去考证了,但是事实证明,你已经可以了。
学会了PHP和数据库的你,无疑是左手拿着MOTOLOLA右手拿着NOKIA,要多潇洒,有多潇洒,哈哈,终于学会了,但是可能这个时候,又会有人不经意的拍拍肩膀对你说:哥们,别高兴的太早,你还是菜鸟,离学会还差着一大截呢!
等到你发奋努力的学会了用PHP成功的插入,删除,更新数据的时候,显然,你已经距离成功指日可待了。
这个时候的你也许是这种状态:
你会HTML吗?会,我能编好几个大表格排板的网页啦!
你会PHP吗?会,我会把一加一的运算写在函数里,然后调用啦!
你会MYSQL吗?会,我会把我的信息在数据库里插入删除啦
那,接下来你该怎么做呢?我觉得,小试一下身手,大概是没问题了,那么交给你个任务,做个留言本吧,这和HELLO WORLD有一比啊!^_^,同是新手面临的第一道关。
花了一段时间,你终于学会把表单的数据插入数据库,然后显示出来了,应该说一个程序的雏形已经诞生了。
但是,你可能瞅瞅东,看看西,人家这个编论坛,那个CMS,还有那啥CRM,我啥时候写一个呢?
不要急,可以说你的马步已经扎的差不多了,接下来就要开始练把势的时候了,如果有条件的话,用笔或者打印一个简易的PHP手册在身上,时不时的摸出来看看,记得,去WC也不能放过(^2^)。
再有条件的话,买本书看看吧,《PHP+MYSQL WEB开发(第三版)》号称圣经级,(也许是个不错的选择(声明:作者没给我啥好处费,我也不是书托,隔着大老远,我连他老兄的面都没见过的说-_-)
巩固了自己的知识,熟悉了PHP和MYSQL开发的要领之后,再回头看你写的那个留言本,你也许会怀疑那真的是你写的吗?当然,如果屋里还有鬼的话,也许是它写的-_-
这个时候,你的留言本应该加入注册以及分页功能了,而如果你更强的话,UI(用户界面)也可以加强,完成之后,感觉是不是特有成就感?不管怎么样,咱好歹是写了一个动态网站程序了,放在自己的网站上耍耍吧,让好朋友来看看,嘿,看咱写的多棒,然后再在网上宣传一下。
几天之后你再打开留言本,哎?哇,一下弹出N多页面!很明显,你的留言本并没有做好安全防范,被人用JS代码小小的耍了一下,我很同情你这个时候的感受,但是没有别的办法了,继续努力吧!
你发奋努力,熟悉了安全方面的问题,然后又设计了一些程序,感觉还不错。
那么接下来,这就算学会啦?NO,NO,NO,还早呢,你至尽还没碰过OOP之类的吧?模板呢?
恩,学!加紧学呀学,学会了这些之后,你又学会了生成静态网页,现在你应该接触一下XML了,恩,XML也了解了,那么AJAX你也得接触接触吧?AJAX完了….然后…
总而言之,你绝对不会发现你全部都学会了,一些真正的强人总会搞出新玩意来丢给你,你不学就落后了,也印证了前人的经验,果然是学无止境啊!
我想通过我的一番YY,你也应该大致熟悉了一些学习过程,也许我的过程和你的有些出路,但是不管怎么样是殊途同归,我写这么多,也只是给大家一个借鉴的机会,至于好与不好,不敢打包票^0^
看完之后你发现,罗嗦这么多,对我一点用处没有啊,我知道该怎么学,但是我想如何才能更快的学,一周速成,啊不,24小时速成那种,你有没?
我…….我没有,但是2分钟之内把你扁进医院里,我倒是有把握-_-
学东西,永远不要妄想有速成这一说,告诉你了一个方式,但是缺少努力这一环节,那也是白搭。
但是有一点我可以给你保证的就是,你学会了PHP,那么学其他的语言,肯定速成,反过来也一样,如果你之前学过其他的语言,那么学PHP肯定快。
不过语法好学,但是怎么用语法来实现每个人都有每个人的方式,几乎是各有千秋。然而借鉴别人成功的代码,绝对是有益无害,因此,多看那些经过千锤百炼凝出来的经典代码,是进阶的最好方法。
讲了这么多,无非是想说:学习PHP不仅要掌握方法,更多的是付出汗水,我不希望看到中途放弃的人,相信自己,相信自己的选择,更要相信自己的能力,如果自己想放弃,暴力一点的话,就自己抽自己一个嘴巴,然后大吼:别人可以,我为什么就不可以?(是不是有点阎罗教练的味道,的确是电影看多了,抽嘴巴是会痛的,各位其实明白这个道理了就行了)
另外要叮嘱各位的是,抵御诱惑,ASP/PHP/JSP/.NET的对比也许会让你无所适从,你也许学了一半PHP,又开始打C#的主意,或者有人说JAVA很强,这个时候的你绝对不能动摇,哪怕你真想学,也得学会了PHP。然后再学,见异思迁是最不可取的,狗熊掰玉米就是这个道理,如果经常中途放弃,只能是一无所获,还浪费了N多的时间和经历,得不偿失,最重要的是,你会被别人瞧不起,没有人会喜欢和见异思迁的人交朋友,因为这种人太不安分,太不可靠,因此,你必须要强迫自己完成自己的目标,哪怕可能会很难受,也得坚持,毅力就是这么锻炼出来的。
本文固定链接:
转载请注明:
作者:zhoumeng
这个作者貌似有点懒,什么都没有留下。
如果您觉得这篇文章有用处,请支持作者!鼓励作者写出更好更多的文章!
您可能还会对这些文章感兴趣![新手请教] PHP 如何向前端主动发起操作 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
已注册用户请 &
[新手请教] PHP 如何向前端主动发起操作
· 315 天前 · 2670 次点击
类似秒杀的一个活动,现在的问题是,当商品被抢走后,怎么向前端发起信息,让在线用户看到该商品被标记成已结束抢购?后台使用 php
新手求指导,请前辈详细说下思路,非常感谢
41 回复 &| &直到
20:02:44 +08:00
& &315 天前
1.前端主动校验2.socket
& &315 天前
没写过秒杀,瞎猜一下用库存行吗
& &315 天前
长连接 swoole webSocket
& &315 天前
server send event
& &315 天前
1 我看到的网站都是这样处理的, 不用告诉前端已经抢完了, 前端继续提交交易订单, 然后再订单提交的地方后端这个时候再查库存, 如果发现没有库存, 那么下单就失败并且提示用户秒杀的商品没有了!2 事实上的秒杀如果真的访问量非常大的话, 并不会去实时检查这个库存的, 太费资源, 步凑 1 中严格说来 涉及到事务锁操作
& &315 天前
@ 秒杀库存只有 1 件,我是想当商品被抢了之后,当前打开的用户会看到商品已经被抢的标记(结束了),对于您说的 1 我是有提示的,但是现在我不懂向前台发送操作,商品开始秒杀后,即时被抢了,已经打开的商品列表中商品的倒计时还是不停的倒计下去,我就想被抢了就停止倒计时并标记结束
& &315 天前
@ @ @ 好的,我搜索下
& &315 天前
感觉你思路走偏了一般处理逻辑是这样的:
1\所有用户进入页面,看到的都是倒计时,然后抢购开始
2\某一个用户抢购成功,其他用户(等待倒计时结束并停留在页面中的用户)还是在能够点击抢购,但是服务端返回已被购买,然后页面变成已结束
3\这时候如果新用户进入到当前页面,直接是结束状态
这样是不会涉及主动推送的,虽然你这样用户体验会好一些.而且这种我个人觉得轮询都够了,上 websocket 不是很有必要,比如在抢购开始后几秒检查一下状态
& &315 天前
@ 有个商品列表页的,这个列表页的商品会一直倒计时,如果商品被抢了,不提示就一直倒计时,这样给用户的感觉不好,看起来还在进行,点进去又结束,用户体验不好
& &315 天前
@ 你说的是商品详情页,是我没说清楚,我现在要解决的是列表页,就是有很多商品同时在倒计时状态,然后可能某一件被抢购了,就要标记那个商品结束了而不是继续倒计时
& &315 天前 via Android
需要前端主动 ajax 才行。现在可以考虑 Websocket,但是很少这么做的。
& &315 天前
@ 了解了下 SSE,应该能满足我的需求,谢谢您
& &315 天前
@ 我尝试了 AJAX,定时请求,但是消耗有点大,就又去掉了
& &315 天前
@ 因为是在商品列表页使用
& &315 天前
SSE 标准已经被边缘化了,而且 MS 系浏览器不支持(不打算支持)
& &315 天前
@ 嗯,搜索到的资料也不多,SSE 在单个商品页我还能处理,可是在商品列表页怎么处理我弄不明白,SSE 能传递参数吗?@
& &315 天前
websocket 轻松解决
& &315 天前
@ 因为 ws 还要 python,后台还要安装其他的,我还没搞明白,新手。。。
& &315 天前 via iPhone
1、Swoole 的 websocket,秒杀结束了就向所有的连接发送秒杀结束的请求,2、同一,断开连接(前端用 js 判断断开后小时结束秒杀)3、前端主动请求后端,不断请求,直到秒杀结束。(服务器消耗特别大)
& &315 天前
@ 您说的这个是不是比较适合商品详情页,如果列表页呢?有多个商品需要推送呢?
& &315 天前
用 nodejs 起一个 ws 服务,也就几十行代码php 与 nodejs 可以用 http 通讯,也可以用 socket
& &315 天前
@ 好的,我了解去
& &315 天前 via iPhone
@ 都可以的,后端可以返回数组。比如说列表里有 1、2、3、4 四个商品,2 被秒杀完了。你主动推送 2 被秒杀完的请求。比如 array ("2"=&"0"){这个具体内容你自己定义,这是个例子},前端就用 js 解析这个请求就可以了。
& &315 天前 via Android
@ 列表的话,永远只 ajax 一个,不是每个商品都 ajax 分开的。
& &315 天前 via Android
用 ajax 轮询呗,要注意的是必须搞几个和业务无关的独立的服务器来专门处理这种 ajax 轮询请求,秒杀这种瞬间流量大的请求一多会把业务服务器搞卡出翔。
& &315 天前
额,你的意思是你的秒杀是一个限时秒杀,在一定时间内被秒杀或者倒计时结束后没有被购买都算做结束?
这个要根据你列表的量级和同时秒杀数来看,我个人觉得就算是用 ajax 也不会有太大的问题,一请求到已经结束,当前这个 ajax 就不会再进行查询请求了,这个主要是要解决一个峰值的问题,不能让页面的所有用户同一时间全部进行查询,这个你自己考虑怎么解决,比如一定时间内的随机值.
建议你先进行下性能测试,ajax 完全能满足需求的话就直接 ajax,上 websocket 会多很多工作,比如其他同学说的另外开一个服务什么的,一旦多一个服务就要多保证一个服务的稳定,部署维护也是增加一定的负担,虽然代码没多少.如果 ajax 不能满足在走 websocket
& &315 天前
@ “一请求到已经结束,当前这个 ajax 就不会再进行查询请求了”这个跟您说的一样,目前是使用 ajax,结束了不会在让其请求,现在的问题就是峰值不好控制
& &315 天前
展示和提交的时候做好状态约定即可
& &315 天前
@ 是列表页哦?您是只用 ajax 直接轮询吗?
& &315 天前
@ 是的,这种方案是可以的,性能也还不错,简单,列表页的频率不需要那么频繁,点详情或者提交的时候再去查询一次,如果库存已经是 0,前端可以更新状态。
& &315 天前
如果你不想使用其他库比如 websocket 的话,我觉得 ajax 是一个比较好的方法。
& &315 天前 via Android
socket 推送消息,然后前端处理就行了
& &315 天前
秒杀不都是用队列吗?
& &315 天前
@ 那就要用户主动点击才行了对吗?你是不是这个意思?我是需要及时不点击也要更新状态
& &315 天前
@ 你可以定时请求啊
& &315 天前
@ 我现在就是这么做,但很明显一轮询就感觉服务器反应压力大了
& &315 天前
别 socket 了,直接就是下单的时候再去查询商品状态,前端页面展示的时候,如果当时没有秒杀完则 js 倒计时,如果秒杀结束则页面显示秒杀结束
& &315 天前
这样做简单粗暴短平快,不然你单为了一个消息通知耗费太多没用的时间就太不值当的了
& &315 天前
@ 我现在需要解决的不是商品详情页哦,是商品列表页,有众多商品需要判断呢
& &314 天前
放队列一个个来
& &314 天前 via Android
那就动态生成列表页啊。。。或者 ws 一把梭挺好的
& · & 3274 人在线 & 最高记录 3762 & · &
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.1 · 23ms · UTC 06:28 · PVG 14:28 · LAX 23:28 · JFK 02:28? Do have faith in what you're doing.前端与后台如何连接起来,就是html和php,怎么连接起来?_百度知道
前端与后台如何连接起来,就是html和php,怎么连接起来?
答题抽奖
首次认真答题后
即可获得3次抽奖机会,100%中奖。
jackzhag2015
来自电脑网络类芝麻团
jackzhag2015
采纳数:615
获赞数:282
参与团队:
只能够使用POST或者是GET来传输吧,PHP语言其实还是后端的,我们链接也只能够模拟表单,建议添加pjax插件,然后javascript模拟表单点击传输数据具体服务端PHP代码:&?php&if($_GET['virtual_get']){&&&&//Code&You&Want&To&Run}具体Javascript代码:var&FormElement&=&document.createElement('form');var&submit&=&document.createElement('input');FormElement.setAttribute('method','get');FormElement.setAttribute('action','?');submit.setAttribute('type','submit');FormElement.appendChild(submit);submit.click()
采纳数:174
获赞数:361
擅长:暂未定制
传统做法就是php嵌套html里面,具体菜鸟教程有简单实例。
为你推荐:
其他类似问题
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。个人网站留言页面(前端jQuery编写、后台php读写MySQL)
&更新时间:日 11:28:53 & 作者:康东扬
这篇文章主要为大家介绍了个人网站的留言页面,前端使用jQuery编写、后台利用php简单读写MySQL数据库,感兴趣的小伙伴们可以参考一下
首先,上个人网站的留言页面,大家可以看看效果:留言板
前端为了省事,使用jQuery编写,后台使用php简单读写MySQL数据库。
数据库设计和实现思路
数据库创建了一个表:comments,结构如下图:
全部评论(包括文章评论回复,留言板)都写在同一张表中,不同的评论区用字段belong区分
同一个评论区里,parent为0表示为评论,parent为某值时表示为哪个评论的回复,思路不复杂。
注意,这里并不讲CSS,大家根据自己的需要定制,现在开始封装:
我们根据自己的需要定下功能,首先我的网站并没有实现消息提醒,即时通讯的功能,所以评论回复并不会提示站长或者用户,只会对留言区产生效果,所以我们只要简单实现以下功能:
1、显示评论列表
2、能够提交评论
3、进行回复
我们将评论的功能封装成一个类,通过实例化就能创建不同的评论区,所以不难想到,
实例化的时候我们需要传入的参数可能有:评论区的id、获取评论的php地址,提交评论的php地址。
所以我们可以猜想实例化评论区的代码可能为:
var oCmt = new Comment({
parent: $('#box'),
//你想要将这个评论放到页面哪个元素中
getCmtUrl: './php/getcomment.php',
setCmtUrl: './php/comment.php'
当然,我是在Comment类上定义一个静态方法
Comment.allocate({
parent: $('#box'),
getCmtUrl: './php/getcomment.php',
setCmtUrl: './php/comment.php'
大同小异,只是初始化的地方不同而已
function Comment(options){
this.belong = options.
this.getCmtUrl = options.getCmtU
this.setCmtUrl = options.setCmtU
this.lists = [];
this.keys = {};
this.offset = 5;
var fn = Comment.
Comment.allocate = function(options){
var oCmt = new Comment(options);
if (oCmt.belong == undefined || !oCmt.getCmtUrl || !oCmt.setCmtUrl) {
oCmt.init(options);
里面的变量和方法我们慢慢解释,如果你不定义一个allocate方法,那么可以写成:
function Comment(options){
this.belong = options.
this.getCmtUrl = options.getCmtU
this.setCmtUrl = options.setCmtU
this.lists = [];
this.keys = {};
this.offset = 5;
if (this.belong == undefined || !this.getCmtUrl || !this.setCmtUrl) {
this.init(options)
var fn = Comment.
变量先不说,像我都是先写功能函数,然后需要添加属性变量再回头来添加,我们只需要看到构造函数最后执行了:
this.init(options)
从名字可以看出是初始化函数。
fn.init = function (options) {
//初始化node
this.initNode(options);
//将内容放进容器
this.parent.html(this.body);
//初始化事件
this.initEvent();
//获取列表
this.getList();
fn为Comment.prototype,只说一次,下面就不再说了。
初始化就是有4个工作要做,从代码注释可以看出,现在一个一个讲解
initNode函数
从名字可以看出主要初始化节点或者缓存dom
fn.initNode = function(options){
//init wrapper box
if (!!options.parent) {
this.parent = options.parent[0].nodeType == 1 ? options.parent : $('#' + options.parent);
if (!this.parent) {
this.parent = $('div');
$('body').append(this.parent);
//init content
this.body = (function(){
var strHTML = '&div class="m-comment"&' +
'&div class="cmt-form"&' +
'&textarea class="cmt-text" placeholder="欢迎建议,提问题,共同学习!"&&/textarea&' +
'&button class="u-button u-login-btn"&提交评论&/button&' +
'&/div&' +
'&div class="cmt-content"&' +
'&div class="u-loading1"&&/div&' +
'&div class="no-cmt"&暂时没有评论&/div&' +
'&ul class="cmt-list"&&/ul&' +
'&div class="f-clear"&' +
'&div class="pager-box"&&/div&' +
'&/div&' +
'&/div&' +
return $(strHTML);
//init other node
this.text = this.body.find('.cmt-text').eq(0);
this.cmtBtn = this.body.find('.u-button').eq(0);
this.noCmt = this.body.find('.no-cmt').eq(0);
this.cmtList = this.body.find('.cmt-list').eq(0);
this.loading = this.body.find('.u-loading1').eq(0);
this.pagerBox = this.body.find('.pager-box').eq(0);
代码中我们可以看出:
this.parent : 保存的是容器节点
this.body : 保存的是评论区的html
this.text : 保存的是评论的textarea元素
this.cmtBtn : 保存的是提交按钮
this.noCmt : 保存的是没有评论时的文字提醒
this.cmtList : 保存的是列表的容器
this.loading : 保存的是加载列表时的loading GIF图片
this.pagerBox : 需要分页时的分页器容器
js上没有难点,都是一些jQuery的方法
将内容放进容器中
this.parent.html(this.body)
这个没什么好讲的,很简单,这时我们的评论组件应该在页面显示了,只是现在没有加载评论列表,也不能评论,下面先讲加载评论列表
getList 函数
首先是初始化列表,清空,显示加载gif图,隐藏没有评论的提醒字样,做好准备就发起ajax请求。
思路是用php将该评论区的留言全部弄下来,在前端再来整理,ajax请求为:
fn.resetList = function(){
this.loading.css('display', 'block')
this.noCmt.css('display', 'none');
this.cmtList.html('');
fn.getList = function(){
var self =
this.resetList();
url: self.getCmtUrl,
type: 'get',
dataType: 'json',
data: { id: self.belong },
success: function(data){
if(!data){
alert('获取评论列表失败');
return !1;
//整理评论列表
self.initList(data);
self.loading.css('display', 'none');
//显示评论列表
if(self.lists.length == 0){
//暂时没有评论
self.noCmt.css('display', 'block');
//设置分页器
var total = Math.ceil(self.lists.length / self.offset);
self.pager = new Pager({
total: total,
parent: self.pagerBox[0],
onchange: self.doChangePage.bind(self),
prev: '&',
error: function(){
alert('获取评论列表失败');
get形式,然后传送id过去,得到了的数据希望是列表数组。
php的内容不讲,下面贴出sql语句:
$id = $_GET['id'];
$query = "select * from comments where belong=$id order by time";
$str = '[';
foreach ($result as $key =& $value) {
$id = $value['id'];
$username = $value['username'];
$time = $value['time'];
$content = $value['content'];
$parent = $value['parent'];
$str .= &&&end
"id" : "{$id}",
"parent" : "{$parent}",
"username" : "{$username.'",
"time" : "{$time}",
"content" : "{$content}",
"response" : []
$str = substr($str, 0, -1);
$str .= ']';
获得的是json字符串,jQuery的ajax可以将它转为json数据,获得的数据如下:
如果加载成功,那么我们得到的是一堆的数据,我们现在是在success回调函数里,数据需要整理,才能显示,因为现在所有的评论回复都属于同一层。
initList 函数
fn.initList = function (data) {
this.lists = []; //保存评论列表
this.keys = {}; //保存评论id和index对应表
var index = 0;
//遍历处理
for(var i = 0, len = data. i & i++){
var t = data[i],
id = t['id'];
if(t['parent'] == 0){
this.keys[id] = index++;
this.lists.push(t);
var parentId = t['parent'],
parentIndex = this.keys[parentId];
this.lists[parentIndex]['response'].push(t);
我的思路就是:this.lists放的都是评论(parent为0的留言),通过遍历获取的数据,如果parent为0,就push进this.lists;否则parent不为0表示这是个回复,就找到对应的评论,把该回复push进那条评论的response中。
但是还有个问题,就是因为id是不断增长的,可能中间有些评论被删除了,所以id和index并不一定匹配,所以借助this.keys保存id和index的对应关系。
遍历一遍就能将所有的数据整理好,并且全部存在了this.lists中,接下来剩下的事情就是将数据变成html放进页面就好了。
//显示评论列表
if(self.lists.length == 0){
//暂时没有评论
self.noCmt.css('display', 'block');
//设置分页器
var total = Math.ceil(self.lists.length / self.offset);
self.pager = new Pager({
total: total,
parent: self.pagerBox[0],
onchange: self.doChangePage.bind(self),
prev: '&',
这是刚才ajax,success回调函数的一部分,这是在整理完数据后,如果数据为空,那么就显示“暂时没有评论”。
否则,就设置分页器,分页器我直接用了之前封装的,如果有兴趣可以看看我之前的文章:
面向对象:分页器封装
简单说就是会执行一遍onchange函数,默认页数为1,保存在参数obj.index中
fn.doChangePage = function (obj) {
this.showList(obj.index);
showList函数
fn.showList = (function(){
/* 生成一条评论字符串 */
function oneLi(_obj){
var str1 = '';
//处理回复
for(var i = 0, len = _obj.response. i & i++){
var t = _obj.response[i];
t.content = t.content.replace(/\&lt\;/g, '&');
t.content = t.content.replace(/\&gt\;/g, '&');
str1 += '&li class="f-clear"&&table&&tbody&&tr&&td&' +
'&span class="username"&' + t.username + ':&/span&&/td&&td&' +
'&span class="child-content"&' + t.content + '&/span&&/td&&/tr&&/tbody&&/table&' +
//处理评论
var headImg = '';
if(_obj.username == "kang"){
headImg = 'kang_head.jpg';
var index = Math.floor(Math.random() * 6) + 1;
headImg = 'head' + index + '.jpg'
_obj.content = _obj.content.replace(/\&lt\;/g, '&');
_obj.content = _obj.content.replace(/\&gt\;/g, '&');
var str2 = '&li class="f-clear"&' +
'&div class="head g-col-1"&' +
'&img src="./img/head/' + headImg + '" width="100%"/&' +
'&/div&' +
'&div class="content g-col-19"&' +
'&div class="f-clear"&' +
'&span class="username f-float-left"&' + _obj.username + '&/span&' +
'&span class="time f-float-left"&' + _obj.time + '&/span&' +
'&/div&' +
'&span class="parent-content"&' + _obj.content + '&/span&' +
'&ul class="child-comment"&' + str1 + '&/ul&' +
'&/div&' +
'&div class="respone-box g-col-2 f-float-right"&' +
'&a href="javascript:void(0);" class="f-show response" data-id="' + _obj.id + '"&[回复]&/a&' +
'&/div&' +
return str2;
return function (page) {
var len = this.lists.length,
end = len - (page - 1) * this.offset,
start = end - this.offset & 0 ? 0 : end - this.offset,
current = this.lists.slice(start, end);
var cmtList = '';
for(var i = current.length - 1; i &= 0; i--){
var t = current[i],
index = this.keys[t['id']];
current[i]['index'] =
cmtList += oneLi(t);
this.cmtList.html(cmtList);
这个函数的参数为page,就是页数,我们根据页数,截取this.lists的数据,然后遍历生成html。
html模板我是用字符串连接起来的,看个人喜好。
生成后就 this.cmtList.html(cmtList);这样就显示列表了,效果图看最开始。
现在需要的功能还有评论回复,而init函数中也只剩下最后一个initEvent
initEvent 函数
fn.initEvent = function () {
//提交按钮点击
this.cmtBtn.on('click', this.addCmt.bind(this, this.cmtBtn, this.text, 0));
//点击回复,点击取消回复,点击回复中的提交评论按钮
this.cmtList.on('click', this.doClickResponse.bind(this));
上面截图来自我的个人网站,当我们点击回复时,我们希望能有地方写回复,可以提交,可以取消,由于这几个元素都是后来添加的,所以我们将行为都托管到评论列表这个元素。
下面先将提交评论事件函数。
addCmt 函数
fn.addCmt = function (_btn, _text, _parent) {
//防止多次点击
if(_btn.attr('data-disabled') == 'true') {
return !1;
//处理提交空白
var value = _text.val().replace(/^\s+|\s+$/g, '');
value = value.replace(/[\r\n]/g,'&br &');
if(!value){
alert('内容不能为空');
return !1;
//禁止点击
_btn.attr('data-disabled','true');
_btn.html('评论提交中...');
//提交处理
var self = this,
username = $.cookie('user');
if (!username) {
username = '游客';
email = $.cookie('email');
if (!email) {
email = '';
var now = new Date();
type: 'get',
dataType: 'json',
url: this.setCmtUrl,
belong: self.belong,
parent: _parent,
email: email,
username: username,
content: value
success: function(_data){
//解除禁止点击
_btn.attr('data-disabled', '');
_btn.html('提交评论');
if (!_data) {
alert('评论失败,请重新评论');
return !1;
if (_data['result'] == 1) {
//评论成功
alert('评论成功');
var id = _data['id'],
time = now.getFullYear() + '-' + (now.getMonth() + 1) + '-' + now.getDate() + ' ' +
now.getHours() + ':' + now.getMinutes() + ':' + now.getSeconds();
if (_parent == 0) {
var index = self.lists.
if (!self.pager) {
//设置分页器
self.noCmt.css('display', 'none');
var total = Math.ceil(self.lists.length / self.offset);
self.pager = new Pager({
total: total,
parent: self.pagerBox[0],
onchange: self.doChangePage.bind(self),
prev: '&',
self.keys[id] =
self.lists.push({
"username": username,
"time": time,
"content": value,
"response": []
self.showList(1);
self.pager._$setIndex(1);
var index = self.keys[_parent],
page = self.pager.__
self.lists[index]['response'].push({
"username": username,
"time": time,
"content": value
self.showList(page);
self.text.val('');
alert('评论失败,请重新评论');
error: function () {
alert('评论失败,请重新评论');
//解除禁止点击
_btn.attr('data-disabled', '');
_btn.html('提交评论');
参数有3个:_btn, _text, _parent 之所以要有这三个参数是因为评论或者回复这样才能使用同一个函数,从而不用分开写。
点击后就是常见的防止多次提交,检查一下cookie中有没有username、email等用户信息,没有就使用游客身份,然后处理一下内容,去去掉空白啊,\n换成 &br& 等等,检验过后发起ajax请求。
成功后把新的评论放到this.lists,然后执行this.showList(1)刷新显示
php部分仍然不讲,sql语句如下:
$parent = $_GET['parent'];
$belong = $_GET['belong'];
$content = htmlentities($_GET['content']);
$username = $_GET['username'];
$email = $_GET['email'];
$query = "insert into comments (parent,belong,content,time,username,email) value ($parent,$belong,'$content',NOW(),'$username','$email')";
doClickResponse 函数
fn.doClickResponse = function(_event){
var target = $(_event.target);
var id = target.attr('data-id');
if (target.hasClass('response') && target.attr('data-disabled') != 'true') {
//点击回复
var oDiv = document.createElement('div');
oDiv.className = 'cmt-form';
oDiv.innerHTML = '&textarea class="cmt-text" placeholder="欢迎建议,提问题,共同学习!"&&/textarea&' +
'&button class="u-button resBtn" data-id="' + id + '"&提交评论&/button&' +
'&a href="javascript:void(0);" class="cancel"&[取消回复]&/a&';
target.parent().parent().append(oDiv);
target.attr('data-disabled', 'true');
} else if (target.hasClass('cancel')) {
//点击取消回复
var ppNode = target.parent().parent(),
oRes = ppNode.find('.response').eq(0);
target.parent().remove();
oRes.attr('data-disabled', '');
} else if (target.hasClass('resBtn')) {
//点击评论
var oText = target.parent().find('.cmt-text').eq(0),
parent = target.attr('data-id');
this.addCmt(target, oText, parent);
//其他情况
return !1;
根据target.class来判断点击的是哪个按钮。
如果点击回复,生成html,放到这条评论的后面
var oDiv = document.createElement('div');
oDiv.className = 'cmt-form';
oDiv.innerHTML = '&textarea class="cmt-text" placeholder="欢迎建议,提问题,共同学习!"&&/textarea&' +
'&button class="u-button resBtn" data-id="' + id + '"&提交评论&/button&' +
'&a href="javascript:void(0);" class="cancel"&[取消回复]&/a&';
target.parent().parent().append(oDiv);
target.attr('data-disabled', 'true'); //阻止重复生成html
点击取消,就把刚才生成的remove掉
var ppNode = target.parent().parent(),
oRes = ppNode.find('.response').eq(0);
target.parent().remove();
oRes.attr('data-disabled', ''); //让回复按钮重新可以点击
点击提交,获取一下该获取的元素,直接调用addCmt函数
var oText = target.parent().find('.cmt-text').eq(0),
parent = target.attr('data-id');
this.addCmt(target, oText, parent);
注意: parent刚才生成html时我把它存在了提交按钮的data-id上了。
到此全部功能都实现了,希望对大家的学习有所启发。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具

我要回帖

更多关于 微信发起群聊 的文章

 

随机推荐