Bootstrap

vue+nodejs商城实战项目【登录 + 购物车 + 支付】

从零开始一个前端项目并将其完成需要经历一系列步骤。以下是一个常见的开发流程,可以帮助规划和管理项目:

  1. 需求分析和规划:

    • 确定项目的目标和范围。
    • 定义用户需求和功能要求。
    • 制定项目计划和时间表。
  2. 技术选型:

    • 选择适当的前端技术栈,如HTML、CSS、JavaScript框架。
    • 针对项目需求选择合适的工具和库,例如React、Vue.js、Angular等。
  3. 创建项目结构:

    • 设置项目文件夹和版本控制(如Git)。
    • 创建初始的项目文件结构,包括HTML、CSS和JavaScript文件。
  4. 设计用户界面:

    • 创建项目的用户界面原型。
    • 设计UI和UX,包括页面布局、颜色、字体等。
  5. 开发前端:

    • 编写HTML、CSS和JavaScript代码。
    • 制作网页布局和设计,确保响应式设计。
    • 添加交互性,例如表单验证、动画等。
    • 集成第三方库和API(如数据获取)。
  6. 测试和调试:

    • 在不同的浏览器和设备上测试项目,确保兼容性。
    • 进行单元测试和集成测试。
    • 调试和修复问题。
  7. 性能优化:

    • 优化页面加载速度和性能。
    • 压缩和缩小文件。
    • 使用懒加载和CDN。
  8. 安全性考虑:

    • 防止常见的安全漏洞,如跨站脚本攻击(XSS)。
    • 使用HTTPS和其他安全措施。
  9. 文档和注释:

    • 编写清晰的代码注释和项目文档。
    • 记录项目结构、功能和用法。
  10. 版本控制:

    • 使用版本控制系统(如Git)来跟踪代码更改。
    • 创建分支和合并更改。
  11. 部署:

    • 选择合适的托管平台(如GitHub、Netlify、Vercel等)。
    • 部署项目到生产环境。
    • 配置域名和DNS。
  12. 运维和维护:

    • 监控网站性能和安全性。
    • 定期更新依赖项和解决问题。
    • 添加新功能和进行持续改进。
  13. 用户反馈和测试:

    • 收集用户反馈,并根据需求进行更新。
    • 迭代开发,持续改进项目。
  14. 学习和成长:

    • 持续学习新的前端技术和最佳实践。
    • 参与社区和讨论,获取反馈和建议。

1、课程介绍

该项目是一个商城项目,

需要掌握的知识

 运用的技术

 功能模块

2、项目有哪些功能 

1、短信验证码登录|注册

2、Vuex

  • 地址管理
  • 订单管理
  • 购物车数据管理

3、Router

4、导航守卫(拦截)

5、支付

技术选型上为什么采用Vue?

1、vue合适

2、领导熟悉

Git常见命令:

  • git clone :(作用是从一个**远程仓库**下载一个**副本**到本地,包括所有的文件、分支和提交。使用git clone [url]来指定你想要克隆的仓库的地址)
  • git branch -r:(git branch -r是一个Git命令,它的作用是列出所有的**远程分支**¹,远程分支是指你从远程仓库克隆或者拉取的分支,它们跟踪远程仓库的状态。如果你想查看**本地分支**,你可以使用git branch命令,如果你想查看**本地和远程分支**,你可以使用git branch -a命令)

3、仓库搭建和初始化

3.1创建仓库

将远程仓库克隆到本地(git clone 远程仓库的地址)

  • 在gitee上新建一个空白远程仓库(有两种访问方式HTTPS和SSH)
  • 初始化
  • 在桌面右键打开Git Bash Here,把项目克隆(git clone https://gitee.com/sjffj/vue-node.js.git)下来,然后进入项目文件( cd vue-node.js)查看分支( git branch -r)

在master(主分支:git默认帮我们创建的)下创建develop分支,并且提交到远程仓库中

创建develop分支步骤:

  1.  git branch develop创建develop分支
  2. git checkout develop切换到develop分支
  3. git branch查看本地分支
  4. git push --set-upstream origin develop将develop提交到远程仓库

在develop分支下创建功能分支

创建功能分支步骤:

  • git branch feature/home:创建新分支
  • git checkout feature/home:切换到新分支
  • git push --set-upstream origin feature/home:将本地分支提交到远程仓库

3.2初始化一个项目

创建前端项目(vue-cli)

       vue create <项目名称>

 用vue-cli创建项目的一些选择:

进入到桌面文件夹,运行vue created vue-node.js(需要和克隆下的文件名一样,创建好才会放到它里边)图中

上下键移动到位置,按空格键即可选中

 

 

 

 

 

项目初始化下载中

 

此时文件是这样的

  创建后端项目

  1.  全局:cnpm install express-generator -g(用于在全局安装express-generator,它是一个用于快速创建Express应用骨架的工具)【之前安装过的可直接进行下一步】
  2.  局部:进入到vue-node.js文件夹——>express --view=ejs <项目名称>(用于使用ejs模板引擎来生成一个Express应用的骨架。ejs是一种嵌入式JavaScript模板,可以让你在HTML中使用JavaScript代码)
  3. cd server
  4. npm install
  5. npm run start
  6. http://localhost:3000/可以访问

        启动项目:http://localhost:3000/

表示启动成功

把项目提交到develop分支下

在前端项目创建成功的终端下:(将本地分支推送到远程develop分支下)

  • 进入vue-node.js目录:cd vue-node.js
  • 查看当前分支:git branch
  • 进入到develop分支:git checkout develop
  • 跟踪所有新文件:git add .
  • 提交更新:git commit -m '内容描述'
  • 将本地分支推送到远程仓库:git push

 

 

只有develop分支下显示初始化项目

以上可能是需要老板来完成的,然后需要员工把以下初始化项目全部克隆下来进行开发即可

4、开发者Git操作

4.1在主分支下克隆的代码

git clone https://gitee.com/xuexiluxian/vue-tea.git(不能用这个,这个是在主分支下克隆代码)

4.2指定分支克隆代码

  •  git clone -b 分支名称 地址(git clone -b develop https://gitee.com/sjffj/vue-node.js.git

4.3克隆是在远程的dev分支下,但是上传代码要在某一个分支上

 

如何解决这个问题?

首先在dev分支下看日志:git log 

  • 配置本地身份

        git config user.name '大炮'

        git config user.email '[email protected]'

  • dev分支下看一下日志:git log(在develop执行的命令)

       记录hash:5711918637cb18c459e0ad8105198ca20ee4bdee 

  • 远程分支拉到本地仓库

        git checkout --track origin/feature/home

  •  将dev分支commit对应的hash值提交的代码合并在home分支上: git cherry-pick hash码(5711918637cb18c459e0ad8105198ca20ee4bdee )

然后就可以在该分支开发代码了

下一节就开始写项目了,项目链接:http://m.tea7.com/index.htm

5、封装Tabbar(底部导航栏)

涉及面试知识点

SPA

SPA就是单页面应用程序,指一个Web网站,只有唯一的一个html页面,所有组件的展示与切换都在这唯一的一个页面内完成此时,不同组件之间的切换需要通过前端路由Hash 地址(类似锚点链接) 与 组件之间的对应关系 )来实现。

SPA的优缺点

SPA( single-page application )仅在 Web 页面初始化时加载相应的 HTML、JavaScript 和 CSS。一旦页面加载完成,SPA 不会因为用户的操作而进行页面的重新加载或跳转;取而代之的是利用路由机制实现 HTML 内容的变换,UI 与用户的交互,避免页面的重新加载。

优点:

  • 用户体验好、快,内容的改变不需要重新加载整个页面,避免了不必要的跳转和重复渲染;

  • 基于上面一点,SPA 相对对服务器压力小;

  • 前后端职责分离,架构清晰,前端进行交互逻辑,后端负责数据处理;

缺点:

  • 初次加载耗时多:为实现单页 Web 应用功能及显示效果,需要在加载页面的时候将 JavaScript、CSS 统一加载,部分页面按需加载;

  • 前进后退路由管理:由于单页应用在一个页面中显示所有的内容,所以不能使用浏览器的前进后退功能,所有的页面切换需要自己建立堆栈管理;

  • SEO 难度较大:由于所有的内容都在一个页面中动态替换显示,所以在 SEO 上其有着天然的弱势。

单页项目的路由怎么实现

通过hash地址(#后边的那部分)来实现

手动实现前端路由:通过onhashchange函数监听哈希地址的变化,使用动态组件渲染把当前hash地址对应的组件渲染到页面上。(location.hash可以获取到当前hash地址)

vue-router

在实际应用中不需要我们自己创建路由,在Vue项目中,vue-router(vue.js 官方给出的 路由解决方案 。它只能结合 vue 项目进行使用,能够轻松的管理 SPA 项目中组件的切换)可以帮助我们快速创建路由,只需要告诉其对应关系即可。以商城项目为例来分析vue-router的使用:(可参考vue2.0——第七天(前端路由的概念与原理、vue-router 的基本使用、vue-router 的常见用法、后台管理案例)_大炮不想学习的博客-CSDN博客

1、 安装 vue-router 包

npm i [email protected] -S

2、创建路由模块

3、导入并挂载路由模块

4、声明路由链接和占位符(声明式导航)

但是项目中用的是编程式导航(调用API方法实现导航的方法)

5、声明路由的匹配规则

该商城项目:

  • 没有用到router-link,而是使用编程式导航(调用API方法实现导航的方式)
  • 并且路由模式用的是history
SPA⾸屏加载速度慢的怎么解决?

⾸屏时间(First Contentful Paint),指的是浏览器从响应⽤户输⼊⽹址地址,到⾸屏内容渲染完成的 时间,此时整个⽹⻚不⼀定要全部渲染完成,但需要展示当前视窗需要的内容 ⾸屏加载可以说是⽤户体验中最重要的环节

路由重定向

px、em、rem

路由懒加载

router——index.js

Tabbar组件中:动态渲染的实现原理

vue项目实现的过程:

要实现的界面:

底部导航栏:Tabbar是一个公共的组件,有的页面有,有的没有,需要的引入该组件即可。

Tabbar公共组件,哪里使用直接导入、注册、使用即可

SPA体现在:4个页面的切换,所以需要新建四个组件,需要用到前端路由

创建一个路由模块并向外导出
导入并挂载路由模块
声明路由的匹配规则 ,除了首页其他都是懒加载
安装包文件

 进行一些删除操作:

 

底部Tabbar组件的实现

 布局实现:(HTML+CSS+JS)ul里边4个li分别包含一个img和span(首页、分类、购物车、我的)——>借助js进行动态渲染

 总结

6、config文件配置路径

 @就代表src目录

7、首页头部切换插件(ly-tab)

涉及面试知识点

  • 字体图标:iconfont
  • ly-tab:topbar切换插件
  • 页面和页面中的组件

要实现的界面:(在component中新建一个home文件夹来存放HOME页面中的组件)

目录分配

views      ===》 页面

components  ===》页面中的组件(模块)

Header.vue 页面实现

字体图标:iconfont

使用:iconfont-阿里巴巴矢量图标库

搜索需要的加入购物车,然后下载到本地,在一下 目录进行引入

使用(icon-fangdajing在浏览器中的名字)

头部topbar切换插件 

ly-tab:一个用于移动端的可触摸滑动具有回弹效果的可复用Vue组件

使用:GitHub - ScoutYin/ly-tab: 🎉 A mobile touch-swappable tabs component for Vue.js 2.x

标题

8、Swiper(轮播图)部分

涉及面试知识点

插件实现Swiper插件的使用

要实现的界面:点击不同的topbar,可以切换到不同的页面,不同页面的数据是通过后端接口请求过来的

怎么判断展示的??

把首页页面从上到下布局实现(topbar、swiper.......Tabbar),把首页中推荐、红茶、大红袍...不同之间的布局实现,针对每个盒子进行v-if判断

代码实现布局 

下载:

npm install [email protected] -S

这是一个Vue.js的插件,名为"vue-awesome-swiper",用于在Vue.js应用程序中集成swiper组件来实现轮播图效果。其中"swiper"和"swiperSlide"是组件的两个子组件,分别用于设置swiper的整体样式和单个轮播项的样式。

使用:

9、icons布局 

要实现的界面

新建一个组件在Hom中使用(后续的数据需要通过接口获取)

10 、爆款推荐布局

涉及面试知识点

  • 逻辑实现
  • 插槽使用:通常用于构建可重用和灵活的组件。插槽允许你将组件的内容动态插入到组件内部的特定位置,从而增加了组件的灵活性和可配置性。

要实现的界面

插槽实现(<slot></slot>)

 11、better-scroll和ref

涉及面试知识点

  • better-scroll滚动插件
  • 生命周期函数
  • ref:获取DOM

better-scroll 使用:

GitHub - ustbhuangyi/better-scroll: :scroll: inspired by iscroll, and it supports more features and has a better scroll perfermance:scroll: inspired by iscroll, and it supports more features and has a better scroll perfermance - GitHub - ustbhuangyi/better-scroll: :scroll: inspired by iscroll, and it supports more features and has a better scroll perfermanceicon-default.png?t=N7T8https://github.com/ustbhuangyi/better-scroll

这个插件是在页面加载的时候执行的,所以有DOM才可以执行,created生命周期函数中有数据但是没节点,created生命周期函数中vm.el 已完成 DOM 的挂载与渲染

滚动原理:

 

绿色部分为 wrapper,也就是父容器,它会有固定的高度。黄色部分为 content,它是父容器的第一个子元素,它的高度会随着内容的大小而撑高。那么,当 content 的高度不超过父容器的高度,是不能滚动的,而它一旦超过了父容器的高度,我们就可以滚动内容区了,这就是 better-scroll 的滚动原理。

实现代码:

 下载——>引入——>使用(注意:要分清什么时候有节点,什么时候better-scroll 必须添加在mounted中,子元素高度比父元素高度要高)

12、猜你喜欢布局 

涉及面试知识点

  • 插槽的使用:直接把之前的Card导入使用即可
  • 静态页面的布局
  • 在Home中导入Like组件即可

13、首页其他板块简单布局 

涉及面试知识点

  • v-if

 报错:Proxy error: Could not proxy request /api/index_list/0/data/1 from localhost:8080 to http://localhost:3000/.

需要让服务器也跑起来,然后才不会报错!!!

实现内容

点击不同的Topbar切换到对用的页面

点击之后可以得到对应的index,就可以判断当前点击项,后续可以通过接口获取数据然后进行渲染

14、点击Top切换数据 

涉及面试知识点

后端启动

跨域

axios

async/await

Promise

前后端交互

props:父组件给子组件传值(扩展:组件之间通信)

Vue面试题:父组件传值到子组件_哔哩哔哩_bilibili

⼦组件设置 props 属性,接收⽗组件通过自定义属性传递过来的参数

扩展:

$emit:子组件传值给父组件

Vue面试题:子组件传值到父组件_哔哩哔哩_bilibili

⼦组件通过 $emit触发 ⾃定义事件, $emit 第⼆个参数为传递的数值,⽗组件绑定事件获取到⼦组件传递过来的参数

兄弟组件之间通信

Vue面试题:兄弟组件之间的传值_哔哩哔哩_bilibili

创建⼀个中间事件Bus,兄弟组件通过 $emit 触发⾃定义事件, $emit 第⼆个参数为传递的数值,另⼀个兄弟组件通过 $on 监听⾃定义事件

启动后端

证明后端没问题

跨域

端口不一样出现跨域问题

 解决:Webpack配置中包含了一个代理服务器的设置,它将以/api为前缀的请求代理到http://localhost:3000。根据你的配置,代理服务器将会把/api/index_list/0/data/1请求代理到http://localhost:3000/api/index_list/0/data/1

请求接口 

安装axios

引入:import axios from 'axios'——>在Home中发起请求(created)——>在后端写接口

是可以拿到code的
在后端写接口

axios请求相关 

这也就是为什么要使用async/await

推荐页数据的获取渲染 

Topbar数据渲染

内容部分的渲染

之前的swiper是写死的

{{item.data}}拿到swiper数据,通过props传递

15、nextTick

涉及面试知识点

nextTick:获取更新后的DOM内容

为什么要用nextTick?

原因:仅仅进行了视图的更新,DOM是没有走的,只是改了它里边的数据,所以获取的还是原来的123,无法获取更新后的结果
使用nextTick可以解决这个问题
nextTick使用场景

一些跟DOM相关的插件,比如滑动的插件,我们的数据可能来自接口,我们需要把接口数据放到页面上,但是插件无法准确获取高度,就会出现以下的空白现象,就可以把插件放到nextTick中,等DOM更新后再执行。

ref/$refs:

下拉出现空白的问题

 

在div没有渲染的时候,不知道其有多高,所以应该先把数据渲染到页面上再去加载滚动插件进行滚动,应该先放DOM再执行better-scroll,所以以下顺序需要改变

js是单线程的,

16、搜索页面布局

21、axios的二次封装

涉及面试知识点

axios二次封装

mint-ui组件

实现内容

加载页面的时候显示一个加载中 ,用到以下mint-ui组件

mint-ui documentation

实现方法

 问题:首页、购物车页、分类页...发请求,每个页面都要写,代码比较冗余,可以只写一次吗?——>针对axios进行二次封装

实际开发中,axios一定要进行二次封装的,后期验证用户是否是登录状态,需要把当前用户信息传到后端,每次传特别长的串是不好的,我只要穿个True/false就方便很对,可以通过二次封装来做。

axios二次封装

 代码实现

console.log(v);
console.log(res);直接是返回的数据

 src-common-request.js

import { Indicator } from 'mint-ui';
import axios from 'axios'
export default {

    common: {
        method: 'GET',
        data: {},
        params: {}
    },
    // $axios是一个函数,options是形参,实参由Home那边传递过来
    $axios(options = {}) {
        // this.common.method默认的是GET, options.method是传递过来的 
		// 如果不传就执行默认的
        options.method = options.method || this.common.method;
        options.data = options.data || this.common.data;
        options.params = options.params || this.common.params;

        //请求前==》显示加载中...
        Indicator.open('加载中...');

        return axios(options).then(v => {
            // console.log(v);
			// 直接封装了,拿到数据,后边会简单很多
            let data = v.data.data;
            return new Promise((res, rej) => {
                if (!v) return rej();
                //结束===》关闭加载中(有个交互,所以加了个定时器)
                setTimeout(() => {
                    Indicator.close();
                }, 500)
                res(data);
            })
        })

    }

}

Home.vue

  methods:{
	async getData(){
		// $axios是一个函数
		let res = await http.$axios({
			url:'/api/index_list/0/data/1',
		})
		console.log(res);
		this.items = Object.freeze(res.topBar);
		this.newData = Object.freeze(res.data);
		
		//当dom都加载完毕了再去执行
		this.$nextTick(()=>{
			this.oBetterScroll = new BetterScroll(this.$refs.wrapper, {
			  movable: true,
			  zoom: true
			})
		})
		
	},

22、渲染搜索结果的数据 

23、搜索商品的价格和销量排序 

24、懒加载

25、分类页布局

26、分类页数据渲染

27、实现商品分类左右联动

28、进入商品详情页

29、详情页吸顶动画

30、渲染数据和keep-alive

涉及面试知识点

keep-alive:

生命周期:

31、登录布局

32、登录模块【前端和后端逻辑】

39、购物车页面布局

40、token和送会员福利

涉及面试知识点

token

cookie、SessionStorage、LocalStorage

 token?

进入到商品详情页——>点击加入购物车(前端发送一个请求给后端,后端把数据加入到数据库)。然后就会出现问题:要不要告诉后端哪个用户发送的请求(前端要知道是哪一个用户,然后把这个用户传给后端)?——>就要用到token!!!

token是一个令牌,就是来验证用户信息的

token使用流程:

  1. 客户端使用用户名跟密码请求登录
  2. 服务端收到请求,去验证用户名与密码
  3. 验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端
  4.  客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里
  5. 客户端每次向服务端请求资源的时候需要带着服务端签发的 Token
  6. 服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据

token是后端生成的, 并且token是不能重复的

        1. 下载

       

            npm install jsonwebtoken

           

        2. 引入

       

            require('jsonwebtoken');

           

        3. 生成token语法

           

            jwt.sign( 用户信息 , 口令 , 过期时间)

       

        4. 解析token

       

           jwt.decode(token);

   

 66、导航守卫

涉及面试知识点

路由导航守卫:

如果是登录状态,可以进入到地址管理,如果是未登录状态,点击地址管理会报错并跳转到登录界面(是因为我们在request.js中封装了)执行力axios。我们要做的就是不能让它登录页,所以就要做导航守卫拦截了!!!

导航守卫分类:

  • 全局的
  • 路由独享的
  • 组件内的

;