美食节项目总结

it2025-11-19  4

菜谱页面

一.需求:完成菜谱页面筛选功能以及分类标签页,点击标签改变样式,以及数据留存功能。 二.思路:先使用‘element组件’进行页面编辑,然后对他们进行数据渲染以及传参,用‘v-model’双向数据绑定来实现数据留存功能。 三.问题以及解决方法: 1.深度监听(监听属性的对象写法):‘handler’ 2.立即执行:‘immediate:true’ 3.reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。 reduce() 可以作为一个高阶函数,用于函数的 compose。 注意: reduce() 对于空数组是不会执行回调函数的。

Q:点击筛选小按钮实现点击第一次添加样式,第二次取消样式,循环反复 M:进行if判断如果按钮的‘title’全等于(===)按钮的‘type’属性让按钮的样式变为空删除按钮的‘title’否则给按钮添加样式 Q:实现多个小按钮的同时数据留存 M:‘v-model’双向数据绑定首先遍历集合当中的值相加,函数当中接收参数(o,item),然后去判断(三目运算符)query[item.title]有没有如果有的话则输出,没有则返回空,然后用if判断上面输出的值,如果有的话,然后先去把上面的之后存起来去把它放在一个数组中(data中v-model的数组中) 最后函数中有返回值返回参数 源数据当中的所有数据挨个加起来,存到一个大的数据当中

菜谱页面(右侧)

一.需求:完成菜谱大全页给分类添加默认值,分页功能以及筛选以及分类功能数据传参功能(右侧主体功能) 二.思路:1)右侧主体的三种情况: 1. 没有加载到数据 , 2. loading。。。 3.加载到数据 分页:引入‘element组件’进行数据与视图的相互改变 三.问题及解决方法: this.$nextTick()将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。(假设我们更改了某个dom元素内部的文本,而这时候我们想直接打印出这个被改变后的文本是需要dom更新之后才会实现的,也就好比我们将打印输出的代码放在setTimeout(fn, 0)中;) 分页功能点击页数的时候视图不会跟着改变 在组件当前页数属性当中添加‘.sync’修饰符 .sync修饰符它会被扩展为一个自动更新父组件属性的 v-on 监听器。当一个子组件改变了一个 prop 的值时,这个变化也会同步到父组件中所绑定 loading尺寸全屏 在组建中绑定class类名‘filter-menus-box’ 属性分类数据筛选问题 M:在组件方法getMenus中,给对象params赋值时,属性名正确(property) Q:给loading加载中添加样式

loading= this.$loading({ target:'.filter-menus-box', //目标地址(在那个地方加入loading) text:'加载中.....', //显示的文本内容 spinner:"el-icon-loading", //小圈圈缓冲样式 background:'ragb(0,0,0,0.7)' //背景颜色最后一位是透明度 })

Home页面:

一.需求:完成home页面的轮播功能,以及内容精选的瀑布流功能效果(类似于分页功能) 二.思路 :(轮播)引入‘element Ui’组件(走马灯组件),然后再‘mouted’里面去渲染进去data.list (瀑布流):然后先去判断(元素什么时候触发滚动事件)元素的下边距如果小于页面的可视高度然后就触发滚动事件,接着请求加载数据,然后把数据去渲染页面 三.问题以及解决方式: Q:优化,每隔一段时间再去执行函数不用频繁触发函数 M:函数防抖和节流:import {throttle} from ‘throttle-debounce’ this.scrollHandler = throttle(300, this.scroll.bind(this));

函数节流指的是某个函数在一定时间间隔内(例如 3 秒)只执行一次,在这 3 秒内 无视后来产生的函数调用请求,也不会延长时间间隔。3 秒间隔结束后第一次遇到新的函数调用会触发执行,然后在这新的 3 秒内依旧无视后来产生的函数调用请求,以此类推。

箭头函数this的指向问题 箭头函数无自己的this,导致内部的this就是指向的外层代码块的this 当数据加载完结时,加载样式小菊花不会再显示 进行if判断,判断当前页数是否大于总页数,如果是的话,让loading状态恢复默认false,之后return返回,(数据销毁之后移除scroll事件) 向上取整一般页面进行数据影响视图是类似于分页功能会产生数据与页数或者总类数不能整除情况下,就必须要进行向上取整,因为你不可能不管多的那几个数据,所以得在多一个页面进行存放,进行数据的向上取整 Z.Element.getBoundingClientRect() 方法返回元素的大小及其相对于视口的位置。

登录页面

一.需求:实现点击跳转登录页面,判断是否登录成功 二.思路:注册登录组件,点击提交登录进行存储,判断是不是跳转登录页面 三.问题以及解决方式: 1.通过配置路由里面的源信息以及路由守卫进行登录验证; 2.登录还是没登陆? 通过login页面 将用户名,密码发送给后端,返回结果 成功: 传统做法:返回session放在cookie中,访问页面时或者发送请求时,浏览器把值发送给后端

现在做法:后端返回token,前端自己决定把token存在cookie中还是localStorage中

*每次请求: 都要把token带个后端,后端进行验证 放在请求的header中,约定key值, authorizetion 3.路由切换的时候,都要想后端发送token,验证合法不合法 不管路由需要不需要登录,都需要展示用户信息 都需要向后端发请求,拿到用户信息 4.在methods中定义方法来向后端发送登录用户名和密码,如果请求成功那么就保存到本地,失败弹出错误信息。点击登录判断当前的登录状态,需要登录是已经登录就直接近,没有登录,但是要进入登录页面,直接进入,没有登录,进入的也不是登录页面,跳转到登陆页面。

登录页面

一.需求:点击登录显示个人中心,点击退出。 二.思路:通过登录状态来进行视图的改变,点击退出后清楚本地存储并回到首页。 三 .问题以及解决方式:在路由中引入store仓库,在路由守卫获取到本地存储,当前端提交登录时,利用store.commit将token数据传到store中,利用提交过来的方法在store的mutations里把数据赋值给state中的对象,在getter中定义isLogin来判断是否登录,询问是否退出,el组件选择弹框,methods里定义方法,通过async、await里拿到login—out,然后清楚本地的token,再回到首页(window.location.herf=’/’)。 个人中心 一.需求:个人空间显示自己的信息 在点击其他用户时显示其他用户信息 二.思路: 显示别人的信息: a、 地址栏中如有userId,则显示对应用户的数据。

b、 通过指定的方法(userInfo)向后端发送请求, 并携带用户id。 c、 后端返回对应的数据,渲染到视图中。

显示自己的信息: a、 地址栏中没有userId,则默认显示自己。

a-2、如果在菜谱中点击了自己进入空间,也有userId 显示在地址栏中。

b、 不需要向后端拿;登录时,自己的信息存在 了vuex中,直接获取。

三.问题及其解决方法 1、地址栏中是否有userId 在判断显示自己 或其他用户的信息 先看一下地址栏有没有

let { userId } = this.$route.query;

用if判断 if (!userId) {

没有就是当前的用户

this.userInfo = this.$store.userInfo;

有的话那么就返回这个用户的userid

else { const data = await userInfo({ userId }); console.log(11111); console.log(data); this.userInfo = data.data; }

2、没有响应 immediate默认为false 则初始值不执行handler方法 immediate如果为true 代表如果在 wacth 里声明了之后,就会立即先去执行里面的handler方法

个人中心,菜单

一、需求:实现编辑个人中心功能 , 完成发布菜单 与后端的交互并完善功能 二、思路: 编辑个人中心功能 将需要用到的数据提取到edit.vue 中

data(){ const userInfo = this.$store.state.userInfo // console.log(userInfo) return { avatar:userInfo.avatar, name:userInfo.name, sign:userInfo.sign } },

并通过双向数据绑定 实现数据和视图同步,数据发生变化,视图跟着变化,视图变化,数据也随之发生改变

<el-input v-model="sign" type="textarea" class="create-input" placeholder="请输入内容"></el-input> <el-input v-model="name" class="create-input" placeholder="请输入内容"></el-input>

在methods中声明一个sava 方法 因为是异步需要添加 async 通过let声明一个data变量

let data = await userEdit({avatar:this.avatar , name:this.name , sign:this.sign})

并sava方法在保存中使用 保存到 后端 userEdit中并通过判断code是否为0来跳转路由页面

if(data.code===0){ this.$router.push({ name:'space' }) }

修改头像时在upload-img.vue 组件中通过props完成组件中的通信

props: { action: { type: String, default: "" }, imageUrl: { type: String, default: "", }, imgMaxWidth: { type: String, default: "auto", }, },

并在标签中响应使用

<el-upload class="avatar-uploader" :action="action" :show-file-list="false" :on-success="handleAvatarSuccess" :before-upload="beforeAvatarUpload" > <img :src="url" :style="{ maxwidth: imgMaxWidth + 'px' }" /> </el-upload>

并向edit组件中传递并更新头像图片

完成发布菜单 并传输入后端中 初始化一个变量 backData const backData = {} 并在data中定义一个backData属性 并在定义的属性中定义一个title 来获取 用户输入的信息并用v-model双向数据绑定

data() { return { backData: { titile: "", } } }

引入api 并引入getProperty方法 在data中定义一个properties属性 并将getProperty中的数据传入到properties中 通过v-for渲染入页面中

getProperty().then(({ data }) => { console.log(data); this.properties = data; } <el-select v-for="item of properties" :key="item.parent_type" :placeholder="item.parent_name" v-model="backData.property[item.title]" > <el-option v-for="option of item.list" :key="option.type" :label="option.name" :value="option.type" ></el-option> </el-select>

v-model="backData.property[item.title]"为了数据分类对应数组

this.backData.property = data.reduce((o, item) => { o[item.title] = ""; return o; }, {});

菜谱分类与属性方式相似定义classify api引入getClassify方法 将数据传入classify中

getClassify().then(({ data }) => { console.log(data); this.classify = data; });

用v-for渲染到页面中

三、问题 1.基本数据类型 ? 引用数据类型 ?、 基本数据类型:Number、String 、Boolean、Null和Undefined。基本数据类型是按值访问的,因为可以直接操作保存在变量中的实际值。示例:     var a = 10;    var b = a;    b = 20;    console.log(a); // 10值 引用数据类型:也就是对象类型Object type,比如:Object 、Array 、Function 、Data等。保存在堆内存中的对象。 与其他语言的不同是,不可以直接访问堆内存空间中的位置 示例: var obj1 = new Object();    var obj2 = obj1;    obj2.name = “我有名字了”;    console.log(obj1.name); // 我有名字了 2.map() map()方法返回一个新数组,数组中的元素为原始数 组元素调用函数处理的后值。 map()方法按照原始数组元素顺序依次处理元素。

最新回复(0)