全栈开发入门级保姆教程——通讯录(mongodb+express+bootstrap+jQuery)

项目虽然不大,但在里面蕴含的知识点还是蛮多的,通过此项目,你可以进一步了解到前后端的数据发送。
一、功能概述
在此项目里,要实现的功能有:
1.getAllContact 获取全部联系人=>返回一个联系人数组,用户ajax请求后填充页面 get
2.search 搜索联系人 get
3.addContact 添加联系人 post
4.removeContat 删除联系人 get
5.reviseContact 修改联系人 post
二、利用express模块,实现后端服务器的搭建
1.就从简单的模块引用说起吧,首先我们要引入express模块,直接开启我们的终端(ctrl+`),键入npm init(-y)生成我们的package.json 和package-lock.js文件,接下来npm install express --save 这里要注意的是–save不要忘记写(方便日后项目的迁移),由于我们要处理post请求,所以我们还需要引入一个body-parser模块,指令如下:npm install body-parser --save。最后是我们的mongodb(多说一句,mongodb因为其为轻量级数据库,操作语句简单,经常被用来完成小项目的实现),语句为:npm install mongodb --save.
2.为了程序的模块化,我们首先对mongodb的操作语句用node.js进行封装:
首先我们要引入mongodb模块,并初始化一些内容(这些都是固定操作):

const mongodb = require('mongodb')
const MongoClient = mongodb.MongoClient
const mongoUrl = 'mongodb://localhost:27017'

接下来我们就要建立连接啦,无论是什么操作,都基于此语句下:

MongoClient.connect(mongoUrl, { useUnifiedTopology: true }, (err, client) => {
    if (err) {
        console.log(err)
        return
    } else {
        // 选库
        var db = client.db('xinKu')
        // 选表
        var xinBiao = db.collection('xinBiao')
        //具体操作语句.......
}

对于mongodb数据库的原生增删改查语句如下:
①增: insertOne 插入一个对象 第一个参数是对象
insertMany 插入一个数组。第一个参数是数组

        xinBiao.insertMany([{name:'sss'},{name:"sss"}],(error,final)=>{
            if(error){
                console.log(error)
                return
            }else{
                console.log(final.result)
                client.close()
            }
        })

②删:deleteOne 默认删除第一个
deleteMany 删除所有的

        xinBiao.deleteOne({ name: "sss" }, (error, final) => {
            if (error) {
                console.log(error)
                return
            } else {
                console.log(final.result)
                client.close()
            }
        })

③改: updateOne 更新一个
updateMany 更新多个

        xinBiao.updateMany({ name: "sss" }, { $set: { name: "www", age: 20 } }, (error, final) => {
            if (error) {
                console.log(error)
                return
            } else {
                console.log(final.result)
                client.close()
            }
        })

④查(经常封装为byid,这样查找更精确)

        xinBiao.find({name:"sss"}).toArray((error,final)=>{
            if(error){
                console.log(error)
                return
            }else{
                // final表示结果数组
                console.log(final)
                client.close()
            }
        })

至此,我想你已经大致了解了如何利用node.js操作mongodb,但我们要想实现项目,还是需要进一步的封装(注意点有几点:
1.利用const ObjectId=monggodb.ObjectId 实现id操作数据库
2.注意this指向问题
3.注意关闭数据库)

var MongControll = function (dataBaseName, formName) {
    this.dataBaseName = dataBaseName
    this.formName = formName

    //封装方法时要有callback回调函数,方便我们了解处理的结果
    this.insertOne = function (newData, callback) {
        MonggoClient.connect(monggoUrl, { useUnifiedTopology: true }, (err, client) => {
            if (err) {
                console.log(err)
                return
            }
            var db = client.db(this.dataBaseName)  //由于用了this,所以要用es6的语法,这样才能指向上层的this
            var form = db.collection(this.formName)
            form.insertOne(newData, (err, final) => {
                if (err) {
                    console.log(err)
                    return

                }

                if (callback) {  //如果有callback 我们就返回运行的结果
                    callback(err,final.result)
                }
                else {
                    console.log(final.result)  //没有直接打印出来结果
                }
                client.close()  //所有操作完毕必须关闭数据库

            })



        })
    }
    this.insertMany = function (newDataArr, callback) {
        MonggoClient.connect(monggoUrl, { useUnifiedTopology: true }, (err, client) => {
            {
                if (err) {
                    console.log(err)
                    return
                }
                else {
                    var db = client.db(this.dataBaseName)
                    var form = db.collection(this.formName)
                    form.insertMany(newDataArr, (error, final) => {
                        if (error) {
                            console.log(error)
                            return
                        } else {
                            if (callback) {
                                callback(error,final.result)
                            } else {
                                console.log(error,final.result)
                            }
                            client.close()
                        }
                    })
                }
            }
        })
    }

    // 删除语句的封装
    this.delete = function (deleteObj, callback) {
        MonggoClient.connect(monggoUrl, { useUnifiedTopology: true }, (err, client) => {
            if (err) {
                console.log(err)
            }
            var db = client.db(this.dataBaseName)
            var form = db.collection(this.formName)
            form.deleteOne(deleteObj, (error, final) => {
                if (error) {
                    console.log(error)
                    return
                }

                if (callback) {
                    callback(error,final.result)
                }
                else {
                    console.log(final.result)
                }
                client.close()

            })
        })
    }
    this.deleteMany = function (deleteObjArr, callback) {
        MonggoClient.connect(monggoUrl, { useUnifiedTopology: true }, (client, err) => {
            if (err) {
                console.log(err)
                return
            }
            else {
                var db = client.db(this.dataBaseName)
                var form = db.connect(this.formName)
                form.deleteOne(deleteObjArr, (error, final) => {
                    if (error) {
                        console.log(error)
                        return
                    }

                    if (callback) {
                        callback(err,final.result)
                    } else {
                        console.log(final.result)
                    }
                    client.close()

                })
            }
        })
    }
    this.deleteById=function(id,callback)
    {
        MonggoClient.connect(monggoUrl,{useUnifiedTopology:true}, (err,client)=>
        {
            if(err)
            {
                console.log(err)
            }
            var db = client.db(this.dataBaseName)
            var form = db.collection(this.formName)
            form.deleteOne({_id:ObjectId(id)}, (error, final) => {  //利用id传参数时,必须引用ObjectId()对id进行处理,否则会报错
                if (error) {
                    console.log(error)
                    return
                }

                if (callback) {
                    callback(error,final.result)
                }
                else {
                    console.log(final.result)
                }
                client.close()

            }) 

        })
    }
    
    //查找语句的封装
    this.find = function (findObj, callback) {
        MonggoClient.connect(monggoUrl, { useUnifiedTopology: true }, (err, client) => {
            if (err) {
                console.log(err)
                return
            }
            var db = client.db(dataBaseName)
            var form = db.collection(formName)
            form.find(findObj).toArray((error, final) => {
                if (error) {
                    console.log(error)
                    console.log(1)
                    return
                } else {
                    if (callback) {
                        callback(error,final)
                    } else {
                        console.log(final.length)
                    }

                    client.close()
                }
            })

        })
    }
    this.findById=function(id,callback)
    {
        MonggoClient.connect(monggoUrl, { useUnifiedTopology: true }, (err, client) => {
            if (err) {
                console.log(err)
                return
            }
            var db = client.db(dataBaseName)
            var form = db.collection(formName)
            form.find({_id:ObjectId(id)}).toArray((error, final) => {
                if (error) {
                    console.log(error)
                    return
                } else {
                    if (callback) {
                        callback(error,final)
                    } else {
                        console.log(final.length)
                    }

                    client.close()
                }
            })

        })
    }

    //更新语句的封装
    this.updateOne = function (updateObj, newdataobj, callback) {
        MonggoClient.connect(monggoUrl, { useUnifiedTopology: true }, (err, client) => {
            if (err) {
                console.log(err)
            }
            else {
                var db = client.db(this.dataBaseName)
                var form = db.collection(this.formName)
                form.updateOne(updateObj, { $set: newdataobj }, (error, final) => {
                    if (callback) {
                        callback(final.result)
                    }
                    else {
                        console.log(final.result)
                    }
                    // callback(final.result) 
                    client.close()
                })

            }
        })

    }
    this.updateById=function(id,newdataobj,callback)
    {
        MonggoClient.connect(monggoUrl, { useUnifiedTopology: true }, (err, client) => {
            if (err) {
                console.log(err)
            }
            else {
                var db = client.db(this.dataBaseName)
                var form = db.collection(this.formName)
                form.updateOne({_id:ObjectId(id)}, { $set: newdataobj }, (error, final) => {
                    if (callback) {
                        callback(error,final.result)
                    }
                    else {
                        console.log(error,final,1)
                    }
                    client.close()
                })

            }
        })
    }
    this.updateMany = function (updateObjArr, newdataobj, callback) {
        MonggoClient.connect(monggoUrl, { useUnifiedTopology: true }, (err, client) => {
            if (err) {
                console.log(err)
            }

            var db = client.db(this.dataBaseName)
            var form = db.collection(this.formName)
            form.updateMany(updateObjArr, { $set: newdataobj }, (err, final) => {
                if (err) {
                    console.log(err)
                    return
                }
                else {
                    if (callback) {
                        callback(err,final.result)
                    }
                    else {
                        console.log(final.result)
                    }
                }

                client.close()
            })


        })

    }

}

至此,我们的模块就封装好了,接下来,将其导出

exports.MongControll = MongControll

3.利用导出的MongControll模块+express搭建服务器
在利用express模块搭建服务器首先引入我们需要的模块

const bodyParser = require('body-parser')
const express = require('express')
const app = express()
const unlencodeParser = bodyParser.urlencoded({ extended: true })
const MongoControll = require('./MongoControll').MongControll
var contact = new MongoControll('addressBook', 'list')//初始化一个数据库+表,存储数据

实现框架如下:

app.use(express.static('./static')) //引入静态文件 初始化页面
app.use(unlencodeParser) //为了post请求
app.get('url', (req, res) => {
............. 
})
app.post('url', unlencodeParser, (req, res) => {
.......
})
app.listen(3000)

首先是获取全部联系人:

app.get('/getAllContact', (req, res) => {
    contact.find({}, function (err, final) { 
    if (err) {
            handle500(res)
            return
        }
        else {
            res.status(200).send(final)

        }
    })
})

2.删除联系人

app.get('/removeContact', (req, res) => {
    var id = req.query.id
    contact.deleteById(id, (err, final) => {
        if (err) return handle500(res)
        res.status(200).send(final)
    })
})

3.修改联系人

app.post('/reviseContact', unlencodeParser, (req, res) => {
    var { name, id, phoneNumber } = req.body
    var docs = {
        name: name,
        phoneNumber: phoneNumber
    }
    // 方法一、先插入后删除
    // contact.insertOne(docs, function (err, final) {
    //     if (err) {

    //         handle500(res)
    //         console.log('插入出错')
    //         return
    //     }
    //     contact.deleteById(id, (err, final) => {
    //         if (err) return handle500(res)
    //         res.status(200).send(final)
    //     })

    // })
    //方法二 直接利用update
    contact.updateById(id,{name:name,phoneNumber: phoneNumber},(err,final)=>
    {
                    if (err) return handle500(res)
            res.status(200).send(final)
    })

})

4.查找联系人

app.get('/search', (req, res) => {
    var wd = req.query.wd
    var reg = new RegExp(wd, 'i')
    contact.find(
        {
            $or:
                [
                    { name: { $regex: reg } },
                    { phoneNumber: { $regex: reg } }

                ]
        }, (err, final) => {
        if (err) {
            handle500(res)
            return
        }
        else {
            res.status(200).send(final)

        }
    }
    )
})

5.增加联系人

app.post('/addContact', unlencodeParser, (req, res) => {
    var { name, phoneNumber } = req.body
    var docs = {
        name: name,
        phoneNumber: phoneNumber
    }
    contact.insertOne(docs, function (err, final) {
        if (err) {

            return handle500(res)
        }
        res.send({ final: 'ok' })

    })

})

三、jQuery+ajax实现前端数据请求
首先是获取全部联系人

         $.ajax(
        {
            type: 'GET',
            url: '/getAllContact',
            data: {},
            success: function (result) {
                console.log(result)
                // 获取到数据之后,填充数据
                renderPage(result)
            }
        }
    )

2.增加联系人

 $.ajax(
        {
            type: 'POST',
            url: '/addContact',
            data: {
                name: name,
                phoneNumber: phoneNumber
            },
            success: function (result) {
                //添加好联系人之后,获取所有联系人
                getAllContact()

            }
        }
    )

3.修改联系人信息

    $.ajax(
        {
            type: 'POST',
            url: '/reviseContact',
            data: {
                name: name,
                id: id,
                phoneNumber: phoneNumber
            },
            success: function () {
                getAllContact()
            }
        }
    )

4.查找联系人

 $.ajax({
        type:'GET',
        url:'/search',
        data:{
            wd:wd
        },
        success:function(e)
        {
            renderPage(e)
        }
    })

5.删除联系人

var removeContact = function (id) {
    // $.ajax(
    //     {
    //         type: 'GET',
    //         url: '/removeContact',
    //         data: { id: id },
    //         success: function (req, res) {
    //             console.log(id)
    //             getAllContact()
    //         }
    //     }
    // )
        $.ajax(
        {
            type: 'POST',
            url: '/removeContact',
            data: { id: id },
            success: function (req, res) {
                getAllContact()
            }
        }
    )
}

此外,我们还要利用ajax实现页面的渲染,即将我们获取到的数据,填充到html页面中:

var renderPage = function (array) {
    var html = ''
    array.forEach(element => {
        html += `
        <li class="list-group-item">
        <h3>${element.name}</h3>
        <p>${element.phoneNumber}</p>
        <div class="btn-group" role="group" aria-label="...">
            <a type="button" href="tel:${element.phoneNumber}" class="btn btn-default">拨打号码</a>
            <button type="button" class="revise-button btn btn-default" phone="${element.phoneNumber}" name ="${element.name}" data-_id="${element._id}">修改联系人</button>
            <button type="button" class="remove-button btn btn-default" data-_id="${element._id}">删除联系人</button>
           
          </div>
        </li>
        `
    });
    contactList.html(html)
    addEventListner()
}

总结一下注意的一些点:
1.因为我们的css样式,有些功能是我们在点击按钮后才会弹出,所以我们要注意此类函数的实现,以及事件的监听,它是发生在我们填充完html之后的,所以获取元素要注意将此类事件封装到一个函数当中,在渲染函数后调用,而不是在全局直接获取此类元素 。
2.在修改联系人的时候要避免数据更新不及时而导致重复修改的问题,针对此点,我们要在revise监听器内,实现一个/getContact(它是利用id方法曲查找联系人),以便数据的更新


        $.ajax(
            {
                type: 'GET',
                url: '/getContact',
                data: {
                    id: data_id,   
                },
                success: function (e) {
                   console.log(e)
                   var nowRevise=e[0]
                   if(nowRevise)
                   {
                       reviseContactName.val(nowRevise.name)
                       reviseContactPhoneNumber.val(nowRevise.phoneNumber)
                   }
                   reviseModal.show()
                }
            }
        )

3.前端功能的一些简单封装

class Modal{
    constructor(jQueryDom,inputIdList)
    {
        this.dom=jQueryDom
        this.inputList=[]
        var me=this
        inputIdList.forEach(function(e)
        {
            me.inputList.push($('#'+e))
        })
    }
    show()
    {
        this.dom.modal('show')
    }
    hide()
    {
        this.dom.modal('hide')
    }
    resetInput()
    {
        this.inputList.forEach(function(e)
        {
            e.val('')
        })
    }
}
var reviseModal=new Modal(
    $('.revise-modal'),
    ['revise-contact-name','revise-contact-phoneNumber']
    )

四.html是利用bootstrap实现的,查看文档就好啦这里不再赘述(引入语句如下)

   <script src="./js/jquery-2.1.0.js"></script>
    <script src="./bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
    <link rel="stylesheet" href="./bootstrap-3.3.7-dist/css/bootstrap.min.css">

遇到的坑:利用id操作数据时一定要!!注意空格呀 千万不要手滑…因为这个原因找了半个小时的bug(也算长经验了)
五、实现页面如下
在这里插入图片描述
源码上传至Github,有需要者可以自行下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值