sell-app-day01
今日任务
- 项目的搭建
- 创建项目
- 仓库(把代码上传上去,切换个人分支)
- 工程化scss
- reset.scss
- main.scss [统一的出口]
- common.scss [公共的样式]
- vant.scss [覆盖vant的样式]
- var.scss 【变量的文件, 新】
- css3 的变量
- 一键切换皮肤 【了解一下】
- css3 的变量
- mixin.scss
- 屏幕适配 【新】
- px 转换成 vw
- axios的配置(token)
- 环境变量
- 路由划分
- vant引入
- 商家信息
- 接口: http://1.15.179.44:3001/ , http://129.211.169.131:5000
- 商品信息
- 接口
项目介绍
-
参考地址
-
用户的群体:给点外卖的用户。
-
功能点:
-
首页
- 商家信息
- 模糊效果
- 商品 【重点】
- 基本的页面的渲染
- 滚动效果的制作
- 左联右 【简单】
- 右联左【需要自己去计算】
- 商品页面与购物车组件联动
- vuex 【重点】
- 商家
- 评价
- 商家信息
-
详情页面
- 页面之间的通信【重点】
-
手机端适配
讲道理设计师只会给一份手机端项目设计稿(375px 750px)。
例子: 假设设计稿的宽度为750, 在设计稿上量出一个div的宽度为375px
真机的宽度 | 实际宽度 | 屏幕(视口)占比 | vw |
---|---|---|---|
375px | 187.5px | 50% | 50vw |
414px | 207px | 50% | 50vw |
912px | 456px | 50% | 50vw |
css3出了一个新的单位: vw。vw:视口(屏幕的宽度)的百分之1。
结论:将px单位转换为vw单位,就能够适配到各个手机端。等比的缩放
px转换为vw不需要开发者自己去算,有第三方插件: postcss-px-to-viewport
postcss-px-to-viewport配置
-
搜索文档: postcss-px-to-viewport npm
-
安装插件: yarn add postcss-px-to-viewport -D
-
在项目的根目录下创建文件: postcss.config.js
-
在postcss.config.js中编写配置
module.exports = { plugins: { // 插件: 将px转换为vw 'postcss-px-to-viewport': { // 设计稿宽度,你在设计稿上量出的宽度,不用自己划算,直接写。 viewportWidth: 750, } } }
-
重启
-
测试
- 给项目中的一个div加一个宽高,然后再浏览器切换机型,看他具体的大小
css3变量【了解!!】
scss/less变量
这个变量设置之后,并不是全局使用。你需要在使用的地方进行导入。
场景: 设置一系列全局变量。 在类名为.box下注入一个变量。
css3的变量
可以设置全局/局部的变量。
- 全局: 给最外层的节点注入一个变量
- 局部: 给某一个节点设置一个局部变量
特点:
- 可以很方便的被覆盖,很多ui组件库都在使用
主题色切换方案
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q1Ir9o7t-1690507265571)(…/resource/md/1.主题色切换.png)]
-
创建一个var.scss,定义三套主题色
// scss的变量页没有全局变量 【哪里需要哪里引入】 $main_color: #ff6900; // css3的变量 // 全局的变量 // :root { --base-color: #ff6900; } // 根节点 下面的某一些节点(有一个属性叫做 theme 属性的值为red) :root [theme="red"] { --base-color: red; } :root [theme="gray"] { --base-color: #ccc; }
-
在main.scss中引入变量文件(var.scss)
@import './reset.scss'; @import './common.scss'; @import './vant.scss'; @import './var.scss';
-
在main.js下全局注册main.scss
- import ‘@/assets/style/main.scss’
-
在App.vue 去指明主题
<div id="app" :theme="theme" > <nav> <router-link to="/">Home</router-link> | <router-link to="/about">About</router-link> </nav> <button @click="theme = 'red'">过年</button> <button @click="theme = ''">默认</button> <button @click="theme = 'gray'">灰色</button> <router-view/> </div> data() { return { // 默认的 theme: '' } }
-
在所有的组件中通过var取base-color
<style scoped lang="scss"> .theme-wrapper { color: var(--base-color); } .container { width: 50px; height: 50px; background: var(--base-color); } </style>
vant的引入
vant是一系列: 微信小程序(vant weapp),vue2 (vant2.x), vue3(vant4.x)。官网
-
安装
- yarn add vant@latest-v2
-
在页面中按需引入
import Button from 'vant/lib/button'; import 'vant/lib/button/style';
在页面中引入组件,引入它对应的样式。注册使用
-
全局,把所有组件都变成全局组件(类似于elementui)
import Vant from 'vant'; import 'vant/lib/index.css'; // Vant是一个对象,这个对象一定有一个方法: install Vue.use(Vant);
在main.js中引入样式,引入所有组件, use一下
-
全局,把你需要的组件,注册成全局。样式我们全局引入
import 'vant/lib/index.css'; import { Button, Tabs } from 'vant'; // 只把Button注册成全局组件 Vue.use(Button).use(Tabs)
我们这次采用这个
better-scroll的使用
官方链接
-
满足三个条件
- 滚动容器高度固定
- 滚动容器下只有一个节点(div)
- 滚动的内容 > 滚动容器
-
安装 BS
-
yarn add @better-scroll/core
-
-
导入
import BS from '@better-scroll/core'
-
初始化BS
// 字符串: #box // dom节点 new BS(滚动容器, { 一些配置 })
作业
- 修改tab刷新丢失问题
- 参考外卖管理端,刷新menu定位丢失问题!!!!
sell-app-day02
左联右
-
给每一个菜单绑定一个点击事件
<van-sidebar v-model="active"> <van-sidebar-item @click="clickType(item.name)" v-for="item in list" :key="item.name" :title="item.name"></van-sidebar-item> </van-sidebar>
-
给右侧每一类商品给一个id,目的就是为了和左边菜单一一对应起来
<div v-for="goods in list" :key="goods.name" :id="goods.name">
-
clickType里面获取右侧点击的菜单项
-
根据名字获取dom节点
-
然后把节点传递给右侧的实例
-
右侧实例调用scrollToElement达到左联右的效果·
clickType(id) { // 通知右侧的BS实例,你该滚动到哪里 // string: document.querySelector // dom this.rightBS.scrollToElement(document.getElementById(id), 500) }
注意如果这里传字符串,你要注意你的id的合法性
-
右联左
-
监听右侧内容的滚动距离
实例.on('监听事件', 回调) // 初始化右侧BS的时候,配置任何时候都派发滚动事件 this.rightBS = new BS('#goods_right', { click: true, // 滚动事件派发 probeType: 3 }) // 监听滚动 this.rightBS.on('scroll', (position) => { const { y } = position console.log(y, '~~~~~~~~~~~~~') })
-
通过计算属性获取每一类商品的高度
-
对高度进行处理 { active:0, min:0 , max: 100}
computed: { typeHeight() { let arr = [] // 第i项之前的总和,最开始为0 let prevHeight = 0 this.list.forEach((goods, i) => { // 得到当前第i项商品的高度 let height = document.getElementById(goods.name).offsetHeight arr.push({ active: i, min: prevHeight, // 第i项之前的总和 max: prevHeight + height // 第i项之前的总和 + 自身的高度 }) // push完之后prevHeight要加上height prevHeight += height }) return arr } },
-
-
滚动时候拿到滚动的距离y(取绝对值),在divHeight中进行判断
this.rightBS.on('scroll', (position) => { // 拿到滚动距离取绝对值 const y = Math.abs(position.y) for(let i = 0; i < this.typeHeight.length; i++) { let curType = this.typeHeight[i] if(y>=curType.min && y < curType.max) { this.active = curType.active break } } })
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6HBwXuGQ-1690507265572)(…/resource/md/左右联动思路图.png)]
商品页与购物车联动
将商品列表交给vuex保管
- 请求数据
- 修改数据
import { goodsListApi } from '@/api/goods.api'
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
// 全部的商品
list: []
},
getters: {
},
mutations: {
M_list(state, payload) {
state.list = payload
}
},
actions: {
// action是返回值(promise),如果你没有主动返回,同步代码执行完毕之后,返回一个Promise(undefine)
async A_list({commit}) {
// 请求后台的商品列表
const res = await goodsListApi()
res.forEach(goods => {
goods.foods.forEach(foods => {
foods.num = 0
})
})
commit('M_list', res)
}
},
modules: {
}
})
商品页调用action
- 商品页调用完action
- 当action把仓库中的数据修改之后再初始化BS
created() {
// 调用仓库中的acation
this.A_list().then(res => {
this.$nextTick(() => {
this.leftBS = new BS("#goods_left", {
click: true
});
this.rightBS = new BS("#goods_right", {
click: true,
// 滚动事件派发
probeType: 3
});
// 监听滚动
this.rightBS.on("scroll", position => {
const y = Math.abs(position.y);
for (let i = 0; i < this.typeHeight.length; i++) {
let curType = this.typeHeight[i];
if (y >= curType.min && y < curType.max) {
this.active = curType.active;
break;
}
}
});
});
});
}
编写一个修改数量的mutation
// 把foods 和 num传入
// payload: {foods, num}
M_num(state, payload) {
const { foods, num } = payload
foods.num += num
}
<!-- vuex的数据能直接改吗? -->
<button v-if="foods.num" @click="M_num({foods, num: -1})">-</button>
{{ foods.num }}
<button @click="M_num({foods, num: 1})">+</button>
编写一个getters表示被选中的商品
getters: {
// 被选中的foods
buyGoodsList(state) {
let result = []
state.list.forEach(goods => {
goods.foods.forEach(foods => {
if(foods.num > 0) result.push(foods)
})
})
return result
},
},
编写一个计算总价的getters
getters: {
// 计算总价
totalPrice(state, getters) {
let total = 0
getters.buyGoodsList.forEach(foods => {
total += foods.num * foods.price
})
return total
}
},
页面通信
页面通信的方式
-
本地存储
-
路由传参(vue-router)
-
query
this.$router.push({ query: foods, path: '/detail' })
特点: 数据保存在路径上,刷新页面不会丢失
-
params
this.$router.push({ params: {}, name: '路由的名字' })
刷新页面丢失!!!
-
-
中央事件总线文章来源:https://www.toymoban.com/news/detail-486414.html
- 可以做,但是有bug
- 步骤
- $bus
- Vue.prototype.$bus = new Vue()
- 发送方
- $bus.emit(‘自定义事件的名字’, 发送的数据)
- 接收方
- $bus.on(‘自定义事件的名字’, data => {})
- $bus
- 使用乱传做页面通信,第一次接收不到。
-
vuex文章来源地址https://www.toymoban.com/news/detail-486414.html
- vuex做页面通信,可能会造成数据丢失。
- 解决方式:做vuex的数据持久化(你把数据放在内存中, 你把数据存在本地,数据库,work,text)。
- 调用mutation的时候,把数据存到仓库里面一分,存到本地一分
- state里面:刷新的时候从本地里面取一下
- 实际开发中,配置持久化插件即可。参考链接
bug修改
- 菜单切换丢失
- tab切换,选择num丢失
- 在action之前判断一手
- list有值,不求请
- list没值,重新请求
- keep-alive的使用
- 缓存组件
- 在action之前判断一手
到了这里,关于外卖项目初始化01的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!