基于Vue+Node.js的菜谱webapp

基于Vue+Node.js的移动端菜谱网站

【Food Corner】是我在学习Vue、Node.js等相关技术后独立开发完成的一个菜谱webapp,包含一个后台管理系统,参考了现在主流菜谱应用的功能和界面设计。

从3月初开始选择一个自己感兴趣的内容到最后基本上完成想要实现的功能,总共花费了大半个月的时间,虽然说是完全自己开发的,但是还是在之前练手的王者荣耀移动端基础上进行开发,也参考了一些开源的项目。整体功能设计还是比较简单的,在移动端的设计上与纯静态展示界面相比还是增加了一些新的功能。

作为一个小白,明白还要学习的内容还有很多,完成这个人小项目就当做是巩固之前学过的内容吧,毕竟熟能生巧,跟着视频学总觉得没什么难点,一旦完全自己做,还是有很多意想不到的bug,在解决这些问题的同时也觉得能力有了一定的提升。

项目说明

开发环境 Win10 node.js 10.16.0 Chrome

Github地址:https://github.com/Zhouqiaoqiao1026/fullstack-food-corner

项目地址:webapp后台管理系统

技术栈

vue + node.js + express + mongodb + elementui

项目运行

运行前你需要安装好:
node.js 10+、mongodb、nodemon、vue cli3

项目运行:
clone项目到本地
npm install
cd web(移动端)/admin(后台管理系统)
npm run serve
访问地址

目标功能

移动端:

  • 注册新用户

  • 登录、退出登录

  • 轮播广告位

  • 菜谱列表

  • 菜谱详情

  • 搜索菜谱

  • 活动文章/社区文章列表

  • 文章详情

  • 查看菜谱分类

  • 查看某个类别下的菜谱

  • 添加菜谱(需登录)

  • 个人中心查看(需登录)

后台管理系统:

  • 登录管理员账号

  • 登录校验

  • 数据统计展示(菜谱数量、菜谱种类、用户数)

  • 菜谱类别列表

  • 新建、编辑菜谱类别

  • 菜谱列表

  • 菜谱详情(基本信息、食材、步骤)

  • 新建、编辑菜谱

  • 文章列表

  • 新建、编辑文章

  • 广告位管理

  • 用户列表

  • 管理员用户管理

个人全栈项目Food Corner,基于node-express-vue-mongodb的菜谱应用,含后台管理系统移动端网页

项目截图

移动端-首页
在这里插入图片描述
在这里插入图片描述
后台管理:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

项目总结

与上一个练手的王者荣耀移动端项目相比,在这个项目中我结合实际情况添加了新的功能,比如用户登录注册、登录后个人中心显示、用户发布菜谱、搜索菜谱等,不再是单纯的静态页面展示。

在页面设计上也引入一些未使用过的组件,如底部导航栏、横向滚动条、分类导航等,当然也遇到了非常多的问题。

组件:

  • 横向滚动条

    横向滚动条和垂直滚动条类似,换了一下滚动的方向,需要设置高度和计算得到所有元素的总宽度

    <!--横向活动菜单-->
      <p class="fs-llg my-2 px-2"><i class="iconfont icon-icon-test1 mr-2"></i><strong>热门活动</strong></p>
      <div class="father_scroll d-flex" ref="father_scroll">
         <div class="child_scroll" ref="child_scroll">
              <router-link tag="div" v-for="item in articles" :key="item._id" class="mx-1"
              :to="`/article/detail/${item._id}`">
                <div class="bg-grey-1" style="height:80px;border-radius:10px">
                  <img :src="item.banner" class="h-100" style="border-radius:10px">
                </div>
              </router-link>
        </div>
      </div>
    
    created(){
       //横向滚动条
          this.$nextTick(() => {//回调横向滚动方法
             this.personScroll();
        });},
    //计算出横向滚动组件需要的总宽度
    GetNum(){
            this.width=80*3;
            return this.width;
          },
    personScroll() {
         this.$refs.child_scroll.style.width = this.GetNum() + "px";
         this.$nextTick(() => {
         if (!this.scroll) {
            this.scroll = new BScroll(this.$refs.father_srcoll, {
              startX: 0,
              click: true,
              scrollX: true,  //x方向滚动
              scrollY: false,
              eventPassthrough: "vertical"
          });
        } else {
              this.scroll.refresh();
            }
          });
          },
    
  • 搜索框

    点击右边的搜索图标进行查找

     <!--搜索框-->
      <div class="d-flex jc-center my-1 pb-1">
        <input class="search w-90 p-2 bg-grey-1 text-grey-2" placeholder=" 搜索食谱" v-model="searchMenu"/>
        <i class="iconfont icon-sousuo0101" style="margin-top:10px" @click="searchBtn"></i>
      </div>
    
  • 底部导航

    底部导航的写法可以写成组件引入,也可以直接在Main.vue中写入,采用for循环出底部导航的每个item,点击时加上active效果

    <div class="nav-item"
            v-for="(item, index) of list"
            :key="index"
            :class="{active:index == num}"
            @click="addClassName(index)">
            <router-link  tag="div" class="nav-link" :to="item.path">
              <i v-show="num!=index" :class="item.icon" class="fs-ic"></i>
              <i v-show="num==index" :class="item.active" class="fs-ic"></i>
              <p>{{ item.name }}</p>
            </router-link>
          </div>
        </div>
        <router-view/>  //内容展示
    

    定义一个数组存放导航item的名称、图标、路由地址等

    data() {
        return {
          num: 0,
          list: [
            {
              icon: "iconfont icon-shouyeweixuanzhong",  //原始显示的图标
              active: "iconfont icon-shouyexuanzhong", //点击之后要显示的图标
              name: "首 页",
              path: "/home"
            },
            {
              icon: "iconfont icon-guanzhuweixuanzhong",
              active: "iconfont icon-guanzhuxuanzhong",
              name: "社 区",
              path: "/community"
            },
            {
              icon: "iconfont icon-xinzeng",
              active: "iconfont icon-xinzeng1",
              name: "发 布",
              path: "/add"
            },
            {
              icon: "iconfont icon-fenlei",
              active: "iconfont icon-fenlei1",
              name: "分 类",
              path: "/category"
            },
            {
              icon: "iconfont icon-zhanghaoweixuanzhong",
              active: "iconfont icon-zhanghaoxuanzhong",
              name: "我 的",
              path: "/personalcenter"
            },
            ],
         
          tabName: ""
        };
      },
    
  • 分类导航

    分类导航是一个单独的页面,左侧一级分类用ul li实现,右侧内容根据点击的一级菜单选择呈现的内容

    效果图:
    在这里插入图片描述

    /*左侧一级菜单*/
    <div class="left-nav">
        <ul class="nav-title fs-lg">
          <li v-for="(item,index) in tabParent" 
          :key="item._id" @click="get(index)" 
          :class="{active:cur==index}">
             <h4>{{item.name}}</h4>
          </li>
        </ul>
      </div>
    /*右侧二级菜单*/
      <div class="nav-content d-flex jc-start flex-wrap mt-5 ml-3" style="width:300px;height:300px;">
        <div style="width:80px;text-align:center;" class="mt-3"
            v-for="(item,index) in tabChildren" 
            :key="index">
            //根据点击分类跳转显示对应类别的所有菜谱
            <router-link tag="div" :to="`/menu/list/${item._id}`"> 
            <img :src="item.icon" class=" " style="width:50px;height:50px">
              <p class="fs-md">{{item.name}}</p>
            </router-link>
        </div>
      </div>
    

功能:

  • 登录注册、登陆跳转
    在这里插入图片描述

    登录注册的大体实现和后台管理系统类似,表单提交上与elementUI的方法有一些不同

     <form @submit.prevent="login" style="text-align:center">
     <input type="text" v-model="model.username" class="p-2" placeholder=" 请输入用户名">
     <input type="password" v-model="model.password" class="p-2" 
            placeholder=" 请输入密码">
             <button class="bg-primary m-3 py-2 fs-lg" type="submit">登 录</button>
     </form>
    

    触发时间后我们要获取登录名并显示在个人中心就需要使用localStorage

    async login(){
            const res=await this.$http.post('/login',this.model);
            localStorage.token=res.data.token
           //用户名存入localStorage,localStorage.getItem('username')获取用户名
            localStorage.setItem('username', this.model.username); 
            this.$router.push(`/personalcenter`)
            this.$message({
                    type:'success',
                    message:'登录成功'
                })
        }
        }
    
  • 搜索菜谱

    searchBtn(){
          var searchMenu = this.searchMenu;
          if (searchMenu) {
                this.searchData = this.menus.filter(
                  value=>value.name.indexOf(this.searchMenu)!==-1  //查找菜谱
                 )
           }
          this.$router.push({path: '/search/list', query: {name: this.searchData}});
     }
    

    查询到的结果在SearchList.vue中以列表形式展示

  • 发布菜谱

    在已有用户登录情况下可以发布菜谱,否则会弹出登录页面;这里上传内容的方式和后台管理系统的类似,只不过很多用了原生的组件和方法,这里就不再多作解释,比较简单,可以看一下源码Add.vue

    效果图:
    在这里插入图片描述

令人抓狂的bug们:

  • 引入cors写法

    app.use(require('cors')())
    
  • 查询parent分类

    好几次在查询上级分类的时候发现只能请求到上级分类的id,在这个上面花了很多时间,发现忘了加上下面这个查询

    if(req.Model.modelName==='Xxx'){//xxx是包含父类对象的模型名称
                queryOptions.populate='parent'
     }
    
  • 使用静态资源(忘记加/),又是比较粗心的错误

    app.use('/uploads',express.static(__dirname + '/uploads'))
    

quire(‘cors’)())


- 查询parent分类

好几次在查询上级分类的时候发现只能请求到上级分类的id,在这个上面花了很多时间,发现忘了加上下面这个查询

if(req.Model.modelName===‘Xxx’){//xxx是包含父类对象的模型名称
queryOptions.populate=‘parent’
}


- 使用静态资源(忘记加/),又是比较粗心的错误

app.use(’/uploads’,express.static(__dirname + ‘/uploads’))





  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
基于 Vue.jsNode.js 的网站开发需要掌握以下技术: 1. Vue.jsVue.js 是一个轻量级的前端框架,它可以帮助你构建交互性强的单页应用程序。Vue.js 的核心思想是组件化,它提供了一套完整的组件化方案,让开发者可以轻松地构建复杂的应用程序。 2. Vuex:Vuex 是一个状态管理库,它可以帮助你管理 Vue.js 应用程序中的共享状态。Vuex 中的状态可以被多个组件共享使用,这样可以使应用程序更加的可维护。 3. Vue Router:Vue Router 是一个路由管理库,它可以帮助你实现单页应用程序的路由功能。Vue Router 可以帮助你实现页面之间的切换、URL 参数的传递等功能。 4. Node.jsNode.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境,它可以帮助你在服务器端运行 JavaScript 代码。在 Vue.js 应用程序中,你可以使用 Node.js 实现后台接口,从而实现前后端分离的开发模式。 5. Express:Express 是一个 Node.js 的 Web 框架,它可以帮助你实现 Web 应用程序。Express 提供了一套完整的路由管理系统,可以帮助你实现路由功能。 6. MongoDB:MongoDB 是一个 NoSQL 数据库,它可以帮助你存储非结构化的数据。在 Node.js 应用程序中,你可以使用 Mongoose 库来操作 MongoDB 数据库。 7. Webpack:Webpack 是一个模块打包工具,它可以帮助你将前端代码打包成可执行的 JavaScript 文件。Webpack 可以帮助你实现代码压缩、代码分割等功能,从而提高应用程序的性能。 8. Babel:Babel 是一个 JavaScript 编译器,它可以帮助你将 ES6+ 的代码编译成可执行的 JavaScript 代码。在 Vue.js 应用程序中,你可以使用 Babel 来编译 JavaScript 代码。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值