# vue完全入门项目-多栏目功能模块 **Repository Path**: noctilucent/vue-xiaomi-mall ## Basic Information - **Project Name**: vue完全入门项目-多栏目功能模块 - **Description**: 一个完整的基础vue技术,学会了算入门嗯,提供给广大程序员入坑 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 0 - **Created**: 2022-03-02 - **Last Updated**: 2024-07-22 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Store(参考小米商城) ## 前言 `Vue.js`、`Node.js` ### 账号 admin123456 admin123456 ### 下载图片功能 ````js let url = 'http://r74mocdcd.hd-bkt.clouddn.com/yushi/bg.jpg' let link = document.createElement('a') fetch(url).then(res=>res.blob()).then(blob=>{ link.href = URL.createObjectURL(blob) link.download = "" document.body.appendChild(link) link.click() }) ```` ### elementui input框无法输入 后面无意中发现 elementUI中@input事件可以拿到当前的输入的值 问题找到了 视图没有更新的问题 那么怎么解决了 刷新通过this.$forceUpdate() 可以解决这个问题 ### 插槽 这个是重点 插槽就是子组件提供给父组件使用的一个占位符 用slot表示 父组件可以在这个占位符中填充任何模块代码 ````js //插槽 Vue.component('child-1',{ template:"
插槽1
" }) ```` 一、插槽内容 一句话:插槽内可以是任意内容。 先看一下下面的代码:声明一个child-1组件, ````html Vue.component('child-v',{ template:`
插槽1-会占用,不显示原本元素
` }) 你好 ```` 插槽就是现实原本不会显示东西的内容 ### 具名插槽 给插槽起个名字 没有名字的就是默认插槽
你好
Vue.component('child-v', { template: `
插槽1-会占用,不显示原本元素
` }) ### 作用域插槽 比较难以理解,可能 说白了,就是我在组件上的属性,可以在组件元素内使用 键值对 你好 Vue.component('child-v', { template: `
插槽1-会占用,不显示原本元素
` }) 这里输出的就是键值对{ "say": "aaaa" } ````html Vue.component('child', { props: ["lists"], template: `
` }) nameLists: [{ id: 1, name: '1' }, { id: 2, name: '2' }, { id: 3, name: '3' }, { id: 4, name: '4' }, { id: 5, name: '5' }, ], ```` 这样我就可以在这元素上随便玩了啊 当id等于1的时候,我前面加个你好 我可以随便根据这个对象的属性值进行操作 ### 报错:You are using the runtime-only build of Vue where the template compiler is not available. ````js /* * @Description: 配置文件 */ module.exports = { publicPath: './', //关闭严格模式 lintOnSave: false, // webpack配置 - 简单配置方式 configureWebpack: { resolve: { alias: { // 别名 vue$: "vue/dist/vue.esm.js", //加上这一句 解决报错 } } }, devServer: { open: true, proxy: { '/api': { // target: 'http://localhost:3000/', // 本地后端地址 target: 'http://101.132.181.9:3000/', // 线上后端地址 changeOrigin: true, //允许跨域 pathRewrite: { '^/api': '' } } } } } ```` ### 父组件和子组件 props 想象一下,从父组件向子组件传递数据时候 有一些深度嵌套的组件,而深层次子组件只需要父组件的部分内容 我们可以用一对 provide 和 inject 父组件有一个provide提供寒数据,子组件有一个inject开始使用 成对出现:provide和inject是成对出现的 作用:用于父组件向子孙组件传递数据 使用方法:provide在父组件中返回要传给下级的数据,inject在需要使用这个数据的子辈组件或者孙辈等下级组件中注入数据。 使用场景:由于vue有$parent属性可以让子组件访问父组件。但孙组件想要访问祖先组件就比较困难。 通过provide/inject可以轻松实现跨级访问父组件的数据 跨级访问 ### 父组件向子组件传值 props provide和inject ### 子组件向父组件传值 子组件通过$emit方法 1.子组件定义一个方法 2.方法里面用$emit EmitToParent(){ this.$emit('child-event',this.shopdata) }, 3.父组件上面添加 child-event对应子组件emit第一个参数 4.父组件接收数据 peventEvent(data){ console.log('父组件接收子组件数据1',data); }, 或者数据总线,也可以实现两个组件之间相互传递数据 ### Vue warn: Invalid prop: type check failed for prop "data". Expected Array, 看错误信息:提示我们需要数组,不是字符串,我们渲染表格定义的初始变量需要的是数组,而我定义的是字符串,导致报错 ### fileheader-vscode插件,自动生成头部注释 koroFileHeader 生成这个注释的快捷键是 ctrl+alt+i ### 深拷贝和浅拷贝 深拷贝: 1.递归或者 2.json对象的parse和stringify https://www.cnblogs.com/echolun/p/7889848.html ### mockjs发送get请求 也可以同下面的一样传递参数 ### mockjs发送post请求 Mock.mock(/\/api\/getUserInfo(.*)/, 'post', (o) => { console.log('o',o); let data = Mock.mock({ "data|50": [ { "id|+1": 1, "name": "高兴庄", "dw_name": "国家电网", "type|+1": [, "风电", "火电", "水电" ], dy_dj: "100kV", "ddjg": '华北分中心', "ID": "01122222023330", date: Mock.Random.date('yyyy/MM/dd') } ] }) return apiInterface(data.data) }) getUserInfo() { let api = '/api/getUserInfo' this.$axios .post(api, { categoryID: "this.categoryID", currentPage: "this.currentPage", pageSize: "this.pageSize" }) .then(res => { console.log('res-post',res); }) .catch(err => { return Promise.reject(err); }); } 上面的额分别对应着get和post的请求参数的传递,这样助于你自己需要执行对应的增删查改逻辑,在mock接口文件中能够获取到你传入的参数,打印option形参得到结果,参数全部都在body中,接着你可以对应的参数来进行你所需要的逻辑 {url: "http://test/getmock.com", type: "GET", body: "{\"categoryID\":\"this.categoryID\",\"currentPage\":\"this.currentPage\",\"pageSize\":\"this.pageSize\"}"} ### 与provide一起使用异步数据 提供,我想把我在router-view中的数据与provide一起使用。当我使用provide with data时,它会给我一个空数组。如何将其用于异步数据? export default { components: { TheSidebar, TheMain, }, data() { return { posts: [], stories: [], works: [], }; }, methods: { async fetchData(resource) { const res = await fetch("http://localhost:3000/" + resource); const data = await res.json(); return data; }, }, async created() { this.posts = await this.fetchData("posts"); this.stories = await this.fetchData("stories"); this.works = await this.fetchData("works"); }, provide() { return { stories: this.stories, posts: this.posts, works: this.works, }; }, }; ### 异步数据,同步数据 ### 前端异步方法总结 传统的方案: 1.回调函数 2.事件 工具的方案 1.promise 2.gengrator函数 3.async await 4.nodejs nextTick setimmediate 5.第三方库 async.js promise 状态 fullfilled 和 reject 参数是一个回调函数,回调函数中两个参数 resolve reject * resolve是一个函数,函数中接收参数,参数为任务 * resolve中任务主线程,而then中任务是放在异步队列中的,执行在主线程之后 * 即:promise对象新建后立即执行,首先输出的是promise,然后,then方法指定的回调函数,将在当前脚本所有同步任务执行完才执行 all方法 数组里面可以接收多个promise实例,将数组中所有的任务执行完毕之后,才执行then里面的任务 race方法 表示赛跑,谁快,谁输出,只要有一个率先改变值,状态就跟着改变 ### vetur插件 教程:https://www.cnblogs.com/axingya/p/13563973.html 配置文件 之后页面输入vue ### axios 从入门到源码分析 ### 安装json-server 通过启动json-server服务并侦听db.json,就可以将db.json文件托管成一个 web 服务,此时db.json就充当了数据库服务器的作用。 命令:json-server --port 53000 --watch db.json(不指定端口时默认端口是3000) json-server 启动参数表 语法:json-server [options] source可以是json文件或者js文件 [options]参数列表: 参数 简写 默认值 说明 --config -c 指定配置文件 [默认值: "json-server.json"] --port -p 设置端口[默认值为3000] Number --host -H 设置域[默认值为"0.0.0.0"] String --watch -w Watch file(s) 是否监听 --routes -r 指定自定义路由 --middlewares -m 指定中间件 files [数组] --static -s Set static files directory 静态目录,类比:express的静态目录 --readonly --ro Allow only GET requests [布尔] --nocors --nc Disable Cross-Origin Resource Sharing [布尔] --no gzip gzip --ng Disable GZIP Content-Encoding [布尔] --id -i Set database id property (e.g. _id) [默认值: "id"] --delay -d Add delay to responses (ms) --snapshots -S Set snapshots directory [默认值: "."] --foreignKeySuffix -- fks Set foreign key suffix (e.g. _id as in post_id) [默认值: "Id"] --help -h 显示帮助信息 [布尔] --version -v 显示版本号 [布尔] 几种启动json-server的方式 命令1:json-server db.json 命令2:json-server --watch app.js 命令3:json-server --watch -c ./jsonserver.json 命令4:json-server --port 8888 --watch db.json(不指定端口时默认端口是3000) ### 搭配mockjs食用 新建一个js文件,使用mockjs ````js /* * @Author: hy * @Date: 2022-03-Tu 10:28:08 * @Last Modified by: hy * @Last Modified time: 2022-03-Tu 10:28:08 */ // import Mock from "mockjs" let Mock=require('mockjs'); let Random=Mock.Random; module.exports=()=>{ let data={ news:[] }; let images=[1,2,3].map(x=>Random.image('120x60',Random.color(),Random.word(2,6))); for(let i=0;i<100;i++){ let content=Random.cparagraph(0,10); data.news.push({ id:i, title:Random.cword(8,20), desc:content.substr(0,40), tag:Random.cword(2,6), views:Random.integer(100,5000), images:images.slice(0,Random.integer(1,3)) }) } return data } ```` json-server src/api/getGoods.js ### 参数说明 参数应用 1 分页【关键字:_page】 应用:http://localhost:3000/posts?_page=1 2 排序【关键字:_sort,_order】 _sort后面为要分类的键名 应用:http://localhost:3000/posts?_sort=author _order为排序的方式。DESC(倒序),ASC(顺序) 应用:http://localhost:3000/posts?_sort=author&_order=DESC 3 切分【关键字:_start,_end,_limit】 类似于js里面的slice函数。slice(_start,_end),从数据里面取出数据。数据不包括_end, _limit可以和_start配合,表示从_start位置开始_limit条数据被取出来。 应用:http://localhost:3000/posts?_start=1&_limit=3 4 操作【关键字:_gte,_lte,_ne,[key]_like】 _gte:大于或等于,_lte:小于或等于,_ne:不等于,[key]_like:模糊搜索 应用:http://localhost:3000/posts?author_like=author 5 全局搜索【关键字:q】 q为数据中全局搜索传入的参数 应用:http://localhost:3000/posts?q=json 6 字段扩展【关键字:_embed,_expand】 _embed:扩展子数据字段 _expand:扩展父数据字段 应用:http://localhost:3000/posts/2?_embed=search ### 项目中使用promise all race 解决异步编程的相关问题 ### element-china-area-data Element UI 中国省市区级联数据 provinceAndCityData是省市二级联动数据(不带“全部”选项) regionData是省市区三级联动数据(不带“全部”选项) provinceAndCityDataPlus是省市区三级联动数据(带“全部”选项) regionDataPlus是省市区三级联动数据(带“全部”选项) “全部"选项绑定的value是空字符串”" CodeToText是个大对象,属性是区域码,属性值是汉字 用法例如:CodeToText[‘110000’]输出北京市 extToCode是个大对象,属性是汉字,属性值是区域码 用法例如:TextToCode[‘北京市’].code输出110000,TextToCode[‘北京市’][‘市辖区’].code输出110100,TextToCode[‘北京市’][‘市辖区’][‘朝阳区’].code输出110105 ### 完成天气查询功能模块 动态数据渲染 切换背景图 样式css的优化 ### 使用本地数据存储技术 ````js // 登录信息存到本地 let user = JSON.stringify(res.data.user); localStorage.setItem("user", user); JSON.parse(localStorage.getItem("user")) ```` 以上技术可以存储需要的数据 ### 前端基础知识 1.ES6语法规范 2.ES6模块化 3.包管理器 4.原型,原型链 5.数组常用方法 6.axios 7.promise ### object defineProperty ````js Object.defineProperty(this.person, 'key', { get() { // console.log( "有人读取了数据"); return this.key }, set(value){ this.person.key=value } }) ```` ### vue结构 如何分解,树状图 ### vue-router 路由跳转的理解 this.$router.push 声明式导航 编程式导航 路由传参,参数有哪几种反射光hi params参数 query参数,类似于ajax中的querystring ### Vue 设置style样式 1.直接添加行内样式 2.通过绑定设置style样式 3.将vue的属性设置为样式 4将多个vue属性设置为样式 ````html

sssss

sssss

sssss

sssss

```` ### 什么是localStorage、sessionStorage 在HTML5中,新加入了一个localStorage特性 这个特性主要是用来作为本地存储来使用的,解决了cookie存储空间不足的问题(cookie中每条cookie的存储空间为4k),localStorage中一般浏览器支持的是5M大小,这个在不同的浏览器中localStorage会有所不同。 IE8以上的IE版本才支持localStorage这个属性 本质上是对字符串的读取,如果存储内容多的话会消耗内存空间,会导致页面变卡 * localStorage与sessionStorage的唯一一点区别就是localStorage属于永久性存储,而sessionStorage属于当会话结束的时候,sessionStorage中的键值对会被清空 * 基本使用 * 1.设置值 * 2.获取值 * 3.清除值 ````js var storge = window.localStorage; storge.setItem("goods",res) let data = window.localStorage.getItem('goods') console.log('data',data); ```` 上面这样打印会打印 data [object Object] 我们可以处理一下 //清除所有的值 storage.clear(); //删除指定的值 storage.removeItem("a"); ### 数组遍历 forEach and map ````js array.forEach(element => { selectArray.push(element.dw_name) }); ```` //foreach遍历 array.forEach(element => { selectArray.push(element.dw_name) }); //map遍历 array.map((item,index,arr)=>{ console.log('',item,index,arr); }) * 1.foreach * 对于空数组不会调用回调函数 * 应用场景:为一些相同的元素,绑定事件处理器 * 不可以链式调用 * 2.map * 返回一个新的数组,数组中的元素为处理好的元素 * 处理之后,返回值有 * 不会对空数组进行检测 * 不会改变原来的数组 不同点:就是返回值 ````js let itemDate = array.forEach(element => { return element.date }); console.log('itemDate',itemDate,"注意foreach方法遍历数组没有返回值"); ```` itemDate undefined 注意foreach方法遍历数组没有返回值 ### 获取对象的key值,可以使用 Object.keys(this.init) //返回结果是一个数组,里面放的是获取到的key值 //实际开发中判断 if (Object.keys(this.init).length > 0 ? keyLength = Object.keys(this.init).length : console.log('没有key值')) ### 什么是数据可视化 帮助我们更好的分析数据 增加数据的灵性 ### echarts 1.丰富的可视化类型 2.多数据格式无需转换 3.千万级别数据进行展示 4.移动端优化 5.多渲染方案跨平台使用 6.深度的交互方案 7.动态数据 8.绚丽的特效 ### echarts-title配置 先准备好一个容器div 在vue 里面 我们要学会使用ref ````js let myEcharts = echarts.init(this.$refs.mychart) //设置我们定义的 myEcharts.setOption({ //设置图标的标题 title:{ text:"主标题" }, xAxis:{ data:["111","222","333"] }, yAxis:{ }, series:{ name:"数字大全", type:"bar", data:[1111,2222,3333] } }) ```` * 1.title text * 主标题文本,支持使用 \n 换行 * 2.title link * 主标题文本超链接 * link:"http://www.baidu.com" ````js title:{ text:"主标题\n副标题", link:"http://www.baidu.com" }, ```` * target:"self" 当前页打开 * ### vue 使用动态ref动态显示echarts图坑总结 * 需求 vue项目中动态给div赋予ref属性,以达到动态显示echarts图数量的目的。 * 坑 首先说下最开始的实现思路: 在页面挂载的时候调用接口获取需要图形化展示的参数列表,以及展示图形的数量 在接口数据接收完毕后调用画echarts图的方法 步骤并不复杂,但是其中涉及到了vue生命周期的坑,分析如下: 我们是动态给div赋予ref的: ````html ```` 也就是说我们在上边的第一步接收完接口的数据后,会根据接收到的count数量更新DOM内容。 接下来如果立即执行画echarts图的方法,打印refs内容如下图所示,发现refs内容为空。 此时我们需要使用this.$nextTick方法,在该方法中回调画echarts图的方法,该方法的作用就相当于延迟调用方法,在DOM更新的时候不会立即执行回调函数,在DOM更新完毕后会执行回调函数。这样我们就可以在画echarts图的方法中获取ref内容。 当DOM更新完毕后在获取ref内容的时候不能使用this.$refs[refName]的方式获取,如下图此方式获取的是对应的ref后的数组,我们需要获取的是数组内的内容,所以要使用this.$refs[refName][0]的方式获取。 ````js this.$nextTick(() => { renderEchart(this.$refs[item.name][0], this.person) }) ```` ### CSS中伪元素before和after怎么使用 ````css .font { margin-left: 20px; font-size: 38px; font-weight: bold; color: blue; text-shadow: 5px 5px 5px rgb(177, 172, 172); } .font::after { content: ""; display: flex; position: absolute; background-color: aquamarine; width: 40px; height: 12px; } ```` ### 后端express搭建 ### 人这一辈子 什么最好 大叔,你觉得这辈子什么zuihao 生病的时候,健康最好 没钱的时候,钱最好 房子好呢,也有带不走的一天 究竟什么最好 真正最好的东西是最珍贵的 健康最好 真正的感情最好 活着每一天最好 加油,年轻人 ## 技术栈 - **前端:**`Vue`+`Vue-router`+`Vuex`+`Element-ui`+`Axios` - **后端:**`Node.js`、`Koa框架` - **数据库:**`Mysql` ## 功能模块 ### 登录 页面使用了element-ui的`Dialog`实现弹出蒙版对话框的效果,`登录`按钮设置在App.vue根组件,通过`vuex`中的`showLogin`状态控制登录框是否显示。 这样设计是为了既可以通过点击页面中的按钮登录,也可以是用户访问需要登录验证的页面或后端返回需要验证登录的提示后自动弹出登录框,减少了页面的跳转,简化用户操作。 用户输入的数据往往是不可靠的,所以本项目前后端都对登录信息进行了校验,前端基于element-ui的表单校验方式,自定义了校验规则进行校验。 ### 注册 页面同样使用了element-ui的`Dialog`实现弹出蒙版对话框的效果,`注册`按钮设置在App.vue根组件,通过父子组件传值控制注册框是否显示。 用户输入的数据往往是不可靠的,所以本项目前后端同样都对注册信息进行了校验,前端基于element-ui的表单校验方式,自定义了校验规则进行校验。 ### 首页 首页主要是对商品的展示,有轮播图展示推荐的商品,分类别对热门商品进行展示。 ### 全部商品 全部商品页面集成了全部商品展示、商品分类查询,以及根据关键字搜索商品结果展示。 ### 商品详情页 商品详情页主要是对某个商品的详细信息进行展示,用户可以在这里把喜欢的商品加入购物车或收藏列表。 ### 我的购物车 购物车采用vuex实现,页面效果参考了小米商城的购物车。 ### 订单结算 用户在购物车选择了准备购买的商品后,点击“去结算”按钮,会来到该页面。 用户在这里选择收货地址,确认订单的相关信息,然后确认购买。 ### 我的收藏 用户在商品的详情页,可以通过点击加入 喜欢 按钮,把喜欢的商品加入到收藏列表。 ### 我的订单 对用户的所有订单进行展示。 ``` 1. Clone project git clone https://github.com/hai-27/vue-store.git 2. Project setup cd vue-store npm install 3. Compiles and hot-reloads for development npm run serve 4. Compiles and minifies for production npm run build ```