小功能:微博/文章点赞评论功能实现

1,812 阅读8分钟

日期:2021/10/25
作者:orange

一丶需求分析

1.完成静态页面
2.样式的编写和优化
3.添加页面动作(js)

二丶 项目设计

设计取决于你自己的想法和创意,做出什么样的网页都是看个人,每个人学的代码和网页呈现肯定都会有所偏差,有一些部分没有图片,比较简陋,仅供参考!!!

weibo.png

三丶项目编码

  • 从最简单的开始就是页面的呈现,这里就不细讲了。 注意点: html结构注意语义化,css注意减少重复代 码,使用相同类名进行编写会更好, 这里推荐flex布局和自适应布局(百分比/rem等/百分比最简单) 如果不了解flex布局或者自适应布局可以去查阅相关文档学习,flex布局属性介绍

  • 相关点赞和评论的功能实现我会单独写两篇文章,感兴趣可以看看,提提意见

四丶小模块源码

 html代码: 
 
 <header>
        <div class="logo">
            <!-- <img src="#" alt=""> -->
        </div>
        <div class="column">
            <ul>
                <li><a href="#">知识资产库</a></li>
                <li><a href="#">知识专题</a></li>
                <li><a href="#">知识地图</a></li>
                <li><a href="#">社区</a></li>
            </ul>
        </div>
        <form class="search">
            <input type="text" placeholder="请输入内容">
            <button>提交</button>
        </form>
        <div class="upload">
            上传知识
        </div>
        <div class="profile">
            <div class="ring">&#xe619</div>
                <div class="hp">
            </div>
        </div>
        </header>


<main>
    <div class="article">
        <section class="art-head">
            <div class="art-hp">
                <img src="./img/2.webp" alt="">
            </div>
            <div class="art-name">
                <h4>小白先生</h4>
                <p>硬件技术部</p>
            </div>
            <div class="art-follow">关注</div>
        </section>
        <div class="art-content">
            <div class="wenben">
                <h4>【📣 新征文活动即将上线!~ 今天先来沸点盖楼抽奖!】</h4>
                <p> “程序员必懂小知识”创作挑战,你可以分享:对程序员很重要的小知识点、实践及踩坑经验、社区 的好用的技术工具、刷题找到了独特的思路,等等。专门为写作困难症同学设计,解决你的一切写 作问题,轻轻松松拿大奖!</p>
                <p>>> 活动详情:juejin.cn </p>
                <p>💥 今天,先来沸点盖楼抽奖预热一下吧,</p>
                <p> -- 👀 沸点盖楼活动规则:</p>
                <p> - 在本条下方评论关键词【9月24日分享小知识】,即可参与抽奖(注意关键词没有空格)。</p>
                <p>- 盖楼时间:即日起至 9 月 18 日 23:59:59 🎁 盖楼活动奖励:抽取 3 人,每人一个掘金抱枕</p>
                <p>⏰ 开奖时间:9 月 19 日,请大家提前扫码进群,并留意群内通知和系统消息,以免错过发奖~ [加好友] 进群方式:扫描图 2 ,添加掘金酱为好友,回复关键词“小知识”进群。</p>
            </div>
            <img src="./img/1.webp" alt="">
            <div class="ach">
                <div class="lab">摸鱼选手</div>
                <p>126人表达了态度 👀</p>
            </div>
            <div class="art-bottom">
                <div class="time">
                    今天13:39
                </div>
                <div class="degree">
                    <div class="thumb">
                        <span>&#xec7f</span>1458
                    </div>
                    <div class="reply">
                        <span>&#xe8b4</span>3270
                    </div>
                </div>
            </div>
        </div>
        <footer class="comment">
            <div class="comment-in">
                <img src="./img/2.webp" alt="">
                <textarea name="reply" id="" cols="20" rows="1" placeholder="发表你的看法"></textarea>
                <button>发表</button>
            </div>
            <div class="all-comment">
                <div class="all-c-top">
                    <h3>全部评论</h3>
                    <ul>
                        <li class="hot">最热</li>
                        <li class="early">最早</li>
                        <li class="new">最新</li>
                    </ul>
                </div>
                <div class="all-comment-items">
                    <ul class="comtent-items">

                    </ul>
                </div>
                <input type="text"  placeholder="">
            </div>
        </footer>
    </div>
</main>


css代码:

     @font-face {
        font-family: 'iconfont';
        src: url('../font_41hjo1ecyhb/iconfont.ttf') format('truetype');
    }

    .iconfont {
        font-family: "iconfont" !important;
        font-size: 16px;
        font-style: normal;
        -webkit-font-smoothing: antialiased;
        -moz-osx-font-smoothing: grayscale;
    }

    * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
    }

    li {
        list-style: none;
    }

    a {
        text-decoration: none;
    }

    body {
        background-color: gray;
        width: 100%;
    }

    @keyframes headerOpacity {}

    header {
        display: flex;
        width: 100%;
        height: 56px;
        line-height: 56px;
        background-color: #F39800;
        padding: 0 18%;
        margin-bottom: 20px;
    }

    .logo {
        flex-shrink: 0;
        width: 95px;
        height: 40px;
        margin: auto 0;
        margin-right: 50px;
        background-color: #fff;
    }

    .logo img {
        width: 100%;
        height: 100%;
        border-radius: 10px;
    }

    .column {
        margin-right: 30px;
        flex: 1;
        overflow: hidden;
    }

    .column ul li {
        float: left;
        padding: 0 10px;
        margin: 0 10px;
    }

    .column ul li a {
        color: #000;
    }

    .column ul li:hover {
        background-color: #c07c06;
    }

    .search {
        width: 20%;
        height: 65%;
        margin: auto 0;
        margin-right: 20px;
        background-color: #fff;
        border-radius: 20px;
        overflow: hidden;
    }

    .search input {
        display: block;
        float: left;
        width: 60%;
        height: 75%;
        border: none;
        outline: none;
        border-radius: 10px;
        margin: 5px 0 0 10px;
        padding-left: 10px;
    }

    .search button {
        float: right;
        width: 19%;
        height: 80%;
        margin-top: 3px;
        margin-right: 6px;
        outline: none;
        border: none;
        border-radius: 20px;
        background-color: #f39800;
        color: #fff;
        cursor: pointer;
    }

    .upload {
        width: 6%;
        height: 65%;
        line-height: 35px;
        margin: auto 0;
        text-align: center;
        border-radius: 15px;
        color: #f39800;
        background-color: #fff;
        font-size: 14px;
        margin-right: 30px;
        cursor: pointer;
        overflow: hidden;
    }

    .profile {
        position: relative;
        padding-left: 30px;
    }

    .profile .ring {
        position: absolute;
        top: 8px;
        left: -10px;
        margin-top: 20px;
        width: 16px;
        height: 16px;
        line-height: 0;
        margin-right: 10px;
        font-family: 'iconfont';
        font-size: 30px;
        color: #fff;
        cursor: pointer;
    }

    .profile .hp {
        float: right;
        width: 36px;
        height: 36px;
        border-radius: 50%;
        margin-top: 10px;
        background-color: #fff;
        background: url(../img/2.webp) no-repeat center center;
        cursor: pointer;
    }
    
    
main {
    width: 47%;
    height: auto;
    margin: 0 auto;
}

@media screen and (max-width:450px) {
    .main {
        width: 90%;
        height: auto;
        margin: 0 auto;
    }
}

.article {
    padding: 15px;
    background-color: #fff;
    border-radius: 8px;
}

.article section {
    display: flex;
    height: 60px;
}

.art-hp {
    width: 60px;
    height: 60px;
    border-radius: 50%;
    background-color: orange;
    margin-right: 10px;
    cursor: pointer;
}

.art-hp img {
    width: 100%;
    height: 100%;
    border-radius: 50%;
}

.art-name {
    flex: 1;
    padding-top: 9px;
    cursor: pointer;
}

.art-name p {
    font-size: 10px;
    color: gray;
    margin-top: 4px;
}

.art-follow {
    float: right;
    width: 48px;
    height: 24px;
    line-height: 24px;
    text-align: center;
    font-size: 12px;
    margin: auto 0;
    background-color: #f39800;
    color: #fff;
    border-radius: 20px;
    cursor: pointer;
}

.art-follow2 {
    float: right;
    width: 48px;
    height: 24px;
    line-height: 24px;
    text-align: center;
    font-size: 12px;
    margin: auto 0;
    background-color: #fff;
    color: #666;
    border: 1px solid #666;
    border-radius: 20px;
    cursor: pointer;
}

.art-content {
    padding: 0 20px 0 80px;
    padding-bottom: 30px;
}

.art-content h4 {
    margin-bottom: 20px;
}

.art-content p {
    margin-bottom: 18px;
}

.art-content img {
    width: 40%;
    height: auto;
    border-radius: 8px;
    margin: 5px 0;
}

.ach {
    margin: 10px 0;
    height: 30px;
}

.ach .lab {
    float: left;
    width: 76px;
    height: 28px;
    line-height: 28px;
    text-align: center;
    border-radius: 35px 35px 35px 2px;
    border: 1px solid #F39800;
    background: rgba(243, 152, 0, 0.10);
    color: #F39800;
    cursor: pointer;
}

.ach p {
    float: right;
    color: #BDC3C7;
}

.art-bottom {
    width: 100%;
    height: 30px;
}

.time {
    float: left;
    font-family: PingFangSC-Regular;
    font-size: 16px;
    color: #BDC3C7;
    letter-spacing: 0;
    line-height: 24px;
}

.degree {
    float: right;
}

.degree .thumb {
    user-select: none;
    float: left;
    margin-right: 14px;
    cursor: pointer;
}

.degree .reply {
    user-select: none;
    float: right;
    cursor: pointer;
}

.degree span {
    display: inline-block;
    width: 21px;
    height: 21px;
    margin-right: 4px;
    font-family: "iconfont";
    font-size: 20px;
    margin-top: 1px;
}

.comment {
    margin-bottom: 50px;
    padding: 0 20px;
}

.comment-in {
    display: flex;
    position: relative;
    height: 60px;
}

.comment-in img {
    flex-shrink: 0;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    vertical-align: top;
    margin: 12px 5px 0 0;
}

.comment-in textarea {
    flex: 1;
    width: 90%;
    height: 60px;
    resize: none;
    border: 0;
    outline: none;
    background-color: #F5F7FA;
    border-radius: 10px;
    padding-left: 5px;
    padding-top: 20px;
    font-size: 16px;
}

.comment-in button {
    position: absolute;
    bottom: -35px;
    right: 5px;
    width: 60px;
    height: 30px;
    background-color: #f39800;
    color: #fff;
    outline: none;
    border: none;
    border-radius: 4px;
}

.all-c-top {
    margin-top: 50px;
    margin-bottom: 10px;
    height: 30px;
}

.all-c-top h3 {
    position: relative;
    float: left;
    width: 72px;
    height: 24px;
    font-size: 16px;
}

.all-c-top h3::before {
    content: '';
    position: absolute;
    top: 1px;
    left: -10px;
    width: 2px;
    height: 20px;
    background-color: #f39800;
}

.all-c-top ul {
    float: right;
}

.all-c-top ul li {
    float: left;
    position: relative;
    margin: 0 5px;
    color: #5f5e5e;
}

.all-c-top .hot {
    color: #202020;
}

.all-c-top ul li:nth-child(2)::after,
.all-c-top ul li:nth-child(3)::after {
    content: '';
    position: absolute;
    top: 4px;
    left: -5px;
    width: 2px;
    height: 16px;
    background-color: #5f5e5e;
}

.all-comment-items .item {
    padding: 0 20px;
}

.item-head {
    display: flex;
}

.item-hp {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background-color: orange;
    margin-right: 10px;
    vertical-align: bottom;
}

.item-hp img {
    width: 100%;
    height: 100%;
    border-radius: 50%;
}

.item-name {
    flex: 1;
    font-size: 14px;
}

.item-name p {
    font-size: 10px;
    color: gray;
    margin-top: 4px;
}

.item-content {
    padding: 15px 0 15px 40px;
    color: #666;
}

.item-content p {
    margin-bottom: 5px;
}

.item {
    position: relative;
    margin: 16px 0;
}

.item-bottom {
    width: 100%;
    height: 30px;
}

.item-content::after {
    content: '';
    position: absolute;
    bottom: -6px;
    right: 16px;
    width: 91%;
    height: 1px;
    background-color: #eee;
}

.answer {
    background-color: #F5F7FA;
    padding: 5px 20px;
    margin: 5px 0;
}

.answer img {
    width: 30px;
    height: 30px;
    border-radius: 50%;
    vertical-align: middle;
}

.answer p {
    display: inline-block;
    width: 65%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: middle;
    margin-left: 5px;
}

.answer-item {
    margin: 5px 0;
}

.answer-all {
    font-size: 14px;
    padding: 5px;
}

.active {
    color: #f39800;
}

a span {
    font-family: 'iconfont';
    color: #000;
}

.reply_ a {
    color: #000;
}

.reply_ {
    display: none;
    width: 100%;
    height: 120px;
    border-radius: 8px;
    background-color: #eee;
    padding: 5px;
    margin-bottom: 10px;
}

.reply_ #text {
    width: 100%;
    height: 65%;
    border-radius: 8px;
    padding-left: 10px;
    border: none;
    outline: none;
    margin-bottom: 5px;
}

.reply_ a {
    float: left;
    margin-right: 10px;
}

.reply_ #submit {
    float: right;
    width: 88px;
    height: 30px;
    border: none;
    outline: none;
    border-radius: 2px;
    color: #fff;
    background-color: #f39800;
}

js代码:

 //关注
        function Follow() {
            let follow = document.querySelector('.art-follow')
            follow.addEventListener('click', function() {
                if (follow.innerHTML === '关注') {
                    follow.innerHTML = '已关注'
                    follow.className = 'art-follow2'
                } else {
                    follow.innerHTML = '关注'
                    follow.className = 'art-follow'
                }
            })
        }
        Follow()

        //发表评论
        function setComment() {
            let comment_in = document.querySelector('.comment-in')
            let text = comment_in.querySelector('textarea')
            let button = comment_in.querySelector('button')
            button.addEventListener('click', function() {
                release()
            })
            text.addEventListener('keydown', function(event) {
                if (event.key === 'Enter') {
                    event.preventDefault();
                    if (text.value === "") {
                        event.returnValue = false
                    } else {
                        release()
                    }
                }
            })


            function release() {
                let content = text.value
                arr.push({
                    "img": "./img/2.webp",
                    "content": content,
                    "id": "3",
                    "content_child": ""

                })
                comment(arr)
                text.value = ''
            }
        }
        setComment()



        // 评论数据
        let arr = [{
            "img": "./img/2.webp",
            "content": "CPU相当手机的大脑,核心的运算能力。强劲的CPU可以为手机带来更高的运算能力,也会增加手机玩游戏 看电影的速度体验,CPU主要参数有2,核心数和主频,当然,这些参数也不是越大越好,合理够用即可",
            "id": "1",
            "content_child": ""

        }, {
            "img": "./img/2.webp",
            "content": "CPU相当手机的大脑,核心的运算能力。强劲的CPU可以为手机带来更高的运算能力,也会增加手机玩游戏 看电影的速度体验,CPU主要参数有2,核心数和主频,当然,这些参数也不是越大越好,合理够用即可",
            "id": "2",
            "content_child": [

                {
                    "id": "01",
                    "content_child_img": "./img/2.webp",
                    "content_child_info": "CPU相当手机的大脑,核心的运算能力。强劲的CPU可以为手机带来更高的运算能力"
                }, {
                    "id": "02",
                    "content_child_img": "./img/2.webp",
                    "content_child_info": "核心的运算能力。强劲的CPU可以为手机带来更高的运算能力"
                }, {
                    "id": "03",
                    "content_child-img": "./img/2.webp",
                    "content_child_info": "强劲的CPU可以为手机带来更高的运算能力"
                }

            ]


        }, ]


        //评论渲染
        function comment([]) {
            let items = document.querySelector('.comtent-items')
            let comment_items = document.querySelector('.comtent-items')
            for (let i = items.children.length; i < arr.length; i++) {
                let li = document.createElement('li')
                li.innerHTML = `
                                <div class="item-head">
                                    <div class="item-hp">
                                        <img src=" ${arr[i].img} " alt="">
                                    </div>
                                    <div class="item-name">
                                        <h4>小白先生</h4>
                                        <p>硬件技术部</p>
                                    </div>
                                </div>
                                <div class="item-content">
                                    <p> ${ arr[i].content }
                                    </p>
                                    <form action="" class="reply_">
                                <input type="text" value="" placeholder="回复小白先生" id="text" autocomplete = "off">
                                <a href="#"><span>&#xe8ba</span>图片</a>
                                <a href="#"><span>&#xe54d</span>视频</a>
                                <input type="submit" id="submit" value="发表评论">
                            </form> 
                                    <div class="item-bottom">
                                        <div class="time">2021/08/07 11:49</div>
                                        <div class="degree">
                                            <div class="thumb">
                                                <span class="thumb_icon">&#xec7f</span>点赞
                                            </div>
                                            <div class="reply">
                                                <span class="reply_icon">&#xe607</span>回复
                                            </div>
                                        </div>
                                    </div>
                                </div>`
                li.className = " item item" + "0" + parseInt(i + 1)
                items.appendChild(li)

                let item_content = document.querySelectorAll('.item-content')
                if (arr[i].content_child !== '') {
                    let j = 0
                    let div = document.createElement('div')
                    div.innerHTML = `<div class="answer">
                                        <div class="answer-1 answer-item">
                                            <img src=" ${arr[i].content_child[j].content_child_img} " alt="">
                                            <p>${arr[i].content_child[j].content_child_info}</p>
                                        </div>
                                        <div class="answer-2 answer-item">
                                            <img src=" ${arr[i].content_child[j++].content_child_img} " alt="">
                                            <p>${arr[i].content_child[j].content_child_info}</p>
                                        </div>
                                        <div class="answer-3 answer-item">
                                            <img src=" ${arr[i].content_child[j++].content_child_img} " alt="">
                                            <p>${arr[i].content_child[j].content_child_info}</p>
                                        </div>
                                        <div class="answer-all">
                                            <a href="#">
                                                全部80条回复
                                            </a>
                                        </div>
                                    </div>`
                    div.className = "answer"
                    item_content[i].firstChild.nextSibling.appendChild(div)
                }
            }
        }
        comment(arr)




        //事件冒泡(点赞 回复)
        let items = document.querySelector('.comtent-items')
        items.addEventListener('click', function(event) {
            //点赞
            if (event.target.className === 'thumb') {
                let num = event.target.lastChild.nodeValue //获取点赞数
                let patrn = /[\u4E00-\u9FA5]|[\uFE30-\uFFA0]/gi; //判断是否含有数字
                if (event.target.firstElementChild.className.search('active') != -1) {
                    event.target.firstElementChild.className = 'thumb_icon'
                    if (num == 1) {
                        event.target.lastChild.nodeValue = '点赞'
                    } else {
                        num--
                        event.target.lastChild.nodeValue = num
                    }
                } else {
                    event.target.firstElementChild.className = 'active thumb_icon'
                    if (!patrn.exec(num)) {
                        num++
                        event.target.lastChild.nodeValue = num
                    } else {
                        event.target.lastChild.nodeValue = 1
                    }
                }
            } else if (event.target.className.search("thumb_icon") !== -1) {
                let num = event.target.nextSibling.nodeValue //获取点赞数
                let patrn = /[\u4E00-\u9FA5]|[\uFE30-\uFFA0]/gi; //判断是否含有数字
                if (event.target.className.search('active') != -1) {
                    event.target.className = 'thumb_icon'
                    if (num == 1) {
                        event.target.nextSibling.nodeValue = '点赞'
                    } else {
                        num--
                        event.target.nextSibling.nodeValue = num
                    }
                } else {
                    event.target.className = 'active thumb_icon'
                    if (!patrn.exec(num)) {
                        num++
                        event.target.nextSibling.nodeValue = num
                    } else {
                        event.target.nextSibling.nodeValue = 1
                    }
                }
            }



            //回复
            if (event.target.className === "reply_icon" || event.target.className === "reply") {

                if (event.target.parentNode.parentNode.parentNode.children[1].style.display === "none") {
                    event.target.parentNode.parentNode.parentNode.children[1].style.display = "block"

                } else {
                    event.target.parentNode.parentNode.parentNode.children[1].style.display = "none"
                }
            }


            //回复评论


        })







        //飘窗









        //头部固定
        window.addEventListener('scroll', function() {
            let head = document.querySelector('header')
            if (window.scrollY >= 76) {
                head.style.position = "fixed"
                head.style.opacity = .9

            } else if (window.scrollY <= 20) {
                head.style.position = ""
                head.style.opacity = 1
            }
        })

基本功能可以实现,也有很多一部分没有完成,主要是想靠这个模块,和这篇文章,来讲讲事件冒泡,这是一个挺重要的点,大家感兴趣可以查看我的事件冒泡的文章

ps:写的不好大家作为一个参考或者一个练习笔记看就好~~