前端Vue商城项目学习笔记(1)——超详细(持续更新)

文章目录

前言

主要为自己项目过程做记录
内容较口语化,知识不够专业化

有错误之处,可批评指正!感谢

1.vue-cli脚手架初始化项目

node + webpack + 淘宝镜像

2.项目目录介绍

node_mudules:项目依赖文件夹

public:放置静态资源

src(程序员源代码文件夹):

​ assets:放置静态资源

​ components:放置非路由组件(全局组件)

​ App.vue:唯一的根组件

​ main.js:程序入口文件,整个程序中最先执行的文件

babel.config.js:配置文件

package.json:类似项目身份证

package-lock.json:缓存性文件

3.项目其他配置

1.cmd中npm run serve时可以自动打开页面

package.json文件中
  "scripts": {
    "serve": "vue-cli-service serve --open --host=localhost",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },

2.关闭语法校验

在vue.config.js里

module.exports = defineConfig({
  transpileDependencies: true,
  lintOnSave:false//关闭语法校验
})

3.src文件夹简写方法,给src配置别名

因为项目大的时候src(源代码文件夹):里面目录会很多,找文件不方便,设置src文件夹的别名的好处,找文件会方便一些
创建jsconfig.json文件
{
    "compilerOptions": {
        "baseUrl": "./",
        "paths": {
            "@/*": [
                "src/*"
            ]
        }
    },
    "exclude": [//表示@这个别名在以下两个文件夹中不可使用
        "node_modules",
        "dist"
    ]
}

4.项目路由

何为路由?

即一组映射关系(key-value)

key:url(地址栏中的路径)

value:相应的路由组件

在该项目中:

路由组件:

Home首页路由组件、Search路由组件、Login路由组件、Register注册路由组件

非路由组件:

Header(首页、搜索页)、Footer(首页、搜素页)

创建组件时,准备好组件结构+样式+资源

开发项目步骤
  1. 书写静态页面
  2. 拆分组件
  3. 获取服务器的数据动态展示
  4. 完成相应的动态业务逻辑

5.完成非路由组件部分

非路由组件放在components文件夹里

使用组件步骤

1.创建或定义组件

2.引入

3.注册

4.使用

1.创建组件

1.html:在资料里将home.html文件中将Header的html结构复制到我们自己的项目文件的Header.vue的template里

2.CSS:再将css中的home.less的Header部分复制到Header.vue的style

此时会出现问题,浏览器不识别less样式,需通过less、less-loader进行处理,将less样式变为css样式

安装
cnpm install --save less less-loader@5

安装成功后

再在style标签里加上lang=“less”,即可识别less

3.images:相应的图片也要复制过来

记得script里name:‘Header’

2.引入组件

App里引入组件

import Header from './components/Header'
3.注册组件
components:{'Header'}
4.使用组件

写组件标签

<Header></Header>

Footer部分同上

注意

但此时由于一些默认样式的存在,使得样式出现问题

复制reset.css文件到public文件夹下,记得在index.html文件中引入,清除整体的默认样式

错误

在这里插入图片描述

1.样式没显示

原因:import引入的是Header文件夹

​ 并且components 是复数!后面是{}

6.完成路由组件部分

在这里插入图片描述

路由组件放在pages或views文件夹里

  • Home首页路由组件
  • Search路由组件
  • Login路由组件
  • Register注册路由组件
vue-router

搭建路由组件必须使用vue-router插件

安装:
cnpm install --save vue-router@3
//此处安装的是可以支持vue2的vue-router的3版本
配置路由

配置路由放在router文件夹内

步骤1-4都在router/index.js内完成

1.引入Vue和vur-router
import Vue from 'vue'
import VueRouter from 'vue-router'
2.使用插件
Vue.use(VueRouter)
3.引入路由组件
import Home from '@/pages/Home'
import Login from '@/pages/Login'
import Register from '@/pages/Register'
import Search from '@/pages/Search'
4.配置路由
export default new VueRouter({
    routes:[
        {
            path:"/home",
            component:Home
        },
        {
            path:"/search",
            component:Search
        },
        {
            path:"/login",
            component:Login
        },
        {
            path:"/register",
            component:Register
        },
        //重定向,使访问时直接定向到首页
        {
            path:'*',
            redirect:"/home"
        }
    ]
})
5.注册路由

在main.js

//引入路由
import router from '@/router'
//注册路由
new Vue({
  render: h => h(App),
  router,//完整写法为router:router,但因kv一致,可以简写
}).$mount('#app')

此处写router,使得每一个组件都拥有了 r o u t e 和 route和 routerouter属性

r o u t e 和 route和 routerouter属性

$route:一般获取路由信息,路径、query、params等

$router:一般进行编程式路由导航、进行路由跳转,push、replace等

6.展示路由

在根组件App.vue内

<template>
  <div>
    <Header></Header>
    <router-view></router-view>//路由出口
    <Footer></Footer>
  </div>
</template>
router-view

我们都知道,路由指的是组件和路径的一种映射关系。Router-view也被称为路由的出口,

也就是:

路径--------------------------------------------------------------->页面

可以把router-view理解成一类代码存放的位置。

在App.vue加个路由组件存放的位置即可。

为什么不在其它的组件里面放router-view?

因为App.vue是根组件,最开始的页面就显示在这里。

总结:

1.router-view是路由的出口,没有它页面则没法进行显示。

2.二级路由的出口对应在一级路由里面进行配置。

路由跳转

有两种形式:

1.声明式导航router-link

我认为它适合作用在链接身上

在这里插入图片描述

一定要有to属性

2.编程式导航push/replace

适合一些点击按钮后跳转,可以包含一定业务逻辑

在这里插入图片描述

存在问题:若多次执行会出现警告

输出一下push,会发现返回值为promise

在这里插入图片描述

在这里插入图片描述

因为vue-router引入了promise,而promise有成功和失败的回调,

解决方法,在push里写两个()=>{},传入相应成功和失败的回调,但是治标不治本

this.$router.push({
                name:'search',
                params:{
                    keyWord:this.keyWord
                },
                query:{
                    k:this.keyWord.toUpperCase()
                }
            },()=>{},()=>{})

从this.$router.push来深究一下

this:当前组件vc实例

this. r o u t e r :是这个 v c 身上的一个属性,是 V u e R o u t e r 类的一个实例,来自 m a i n . j s 里注册路由时使每一个组件都有了 router:是这个vc身上的一个属性,是VueRouter类的一个实例,来自main.js里注册路由时使每一个组件都有了 router:是这个vc身上的一个属性,是VueRouter类的一个实例,来自main.js里注册路由时使每一个组件都有了router$route属性

push:VueRouter原型对象里的一个方法

最终要治本,我得改vuerouter有关push的代码

重写push/replace代码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CyILgcju-1662516438193)(C:\Users\86137\AppData\Roaming\Typora\typora-user-images\image-20220905163606743.png)]

重写replace同上,就复制一下改push为replace

call与apply

1.相同点:都可以调用函数一次,都可以篡改函数上下文一次(上下文就是指this的作用域)

不同点:call传参逗号隔开,apply传数组

总结——路由组件和非路由组件区别?

1.文件夹不同:路由组件->pages/views

​ 非路由组件->components

2.使用方法不同:路由组件->要在router文件夹中注册

​ 以形式呈现

​ 不写组件标签,无需在根组件中引入注册

​ 非路由组件->以组件标签形式使用

​ 要引入要注册

​ 写组件标签以使用

3.相同点:注册路由后,组件都有 r o u t e 和 route和 routerouter属性

7.Footer组件的显示与隐藏

footer在登录和注册时隐藏

方式1:v-show

根据$router.path获取当前路由路径信息

<Footer v-show="$route.path=='/home' || $route.path=='/search'"></Footer>
v-if v-show

v-if:通过操纵dom元素来切换显示状态,会频繁操作DOM,表达式的值为true,元素存在于dom树中,为false,从dom树中移除

v-show:只是样式的显示与隐藏,是display:block/none

方式2:meta路由元信息

在$route身上
在这里插入图片描述

有时,你可能希望将任意信息附加到路由上,如过渡名称、谁可以访问路由等。这些事情可以通过接收属性对象的meta属性来实现,并且它可以在路由地址和导航守卫上都被访问到。

我们无法随意向配置对象上加属性,配置对象身上的属性是固定的,但专门留了个空的meta来让程序员可进行一些自定义操作,所以信息可以向meta里加

在这里插入图片描述

配合v-show进行判断,即可实现根据路由路径信息来判断是否显示Footer

<Footer v-show="$route.meta.showFooter"></Footer>

8.路由传参

1.query参数

在这里插入图片描述

2.qarams参数

在路由配置时一定要在path里写占位符,且一定要给路由命名!

且若为对象形式,路径只能写name不能写path

在这里插入图片描述
在这里插入图片描述

例子:params和query结合
字符串形式

在这里插入图片描述

模板字符串形式

在这里插入图片描述

对象形式(常用)

在这里插入图片描述

在这里插入图片描述

面试题&错误

1.路由传递参数(对象写法) path是否可以结合params参数一起使用?

答:不可以。

​ 路由跳转传递参数的时候, 对象的写法可以是 name、path形式。
  但是需要注意的是, path这种写法不能与 params参数一起使用,会导致对应页面获取不到params参数。

2.如何指定 params参数可传可不传?

前提:

若我已经在路由配置的时候给路径写了占位符,相当于路由要求传递params参数,但我用了name且只用了query,这就会导致URL出现问题,即从http://localhost:8080/#/search/?k=DOWN,直接变成http://localhost:8080/#/?k=DOWN

解决方法:在路由配置的时候给路径写了占位符,再加个问号,如此便可使params参数可有可没有,路径不会错

 path:"/search/:keyWord?",
3.如果 params参数传递的是空字符串, 如何解决?

即使有name,即使加了问号,即使query和params都有,但我一旦params传的是空字符串,则路径会再次出现上一题中的问题

解决方法:

params: {keyWord: '' || undefined},

虽然对应页面获取不到params参数了,但至少路径没出错

反正就是,在编程式导航里面,用了name,那就不能让它空着,用query不行,即使有params但空字符串也不行

因为 params参数属于路径地址当中的一部分, 在配置路由的时候已经占位准备接收了。但是没有接收到所以路径就出现问题了。

4.路由组件能不能传递props参数?

答:可以,有三种方式。

3.props参数(较少使用)

在这里插入图片描述

在这里插入图片描述

3.1 对象

配置时额外传一些数据,接收方要props接收

3.2 布尔值

针对params参数,发送方就正常用params参数传数据,接收方要props接收,插值语法里直接写id,可以省得$route.params.id

3.3 函数

query或者params都行,发送方就正常用参数传数据,路由这边中转一下,接收方要props接收,插值语法里直接写id

错误

1.传params参数时忘记带斜杠

在这里插入图片描述

9.Home组件

1.三级联动组件

三级联动多次使用,所以注册为全局组件

先把样式结构图片都复制过来

1.在main.js中注册全局组件

import TypeNav from '@/components/TypeNav'
vue.component(TypeNav.name,TypeNav)

2.使用

在这里插入图片描述

因为是全局组件,所以无需再引入

2.其余组件

耐心

图片里 style里有 template里也有

且不要将images变成多级目录,不论原本资料里的怎么写图片路径,我们都只创建一个images,与改组件相关的图片都放里面

先把样式结构图片都复制过来

再引用使用

错误

1.图片路径出错

注意路径!

10.axios二次封装

why二次封装?

为了使用请求拦截器和响应拦截器

安装axios

cnpm install --save axios

在src下新建目录api 新建文件request.js

//对axios进行二次封装
import axios from 'axios'
//request即为axios,只不过稍微配置一下
//利用axios对象的方法create,去创建一个axios实例
const requests = axios.create({
    //配置对象
    baseURL:'/api',//基础路径,发请求的时候让路径自带api
    timeout:5000,//设置超时时间
});
//请求拦截器:监测发送请求
requests.interceptors.request.use((config)=>{//config:配置对象,其中header请求头属性很重要
    return config;
})
//响应拦截器
requests.interceptors.response.use((res)=>{
    return res.data;
},(error)=>{
    return Promise.reject(new Error('fail'));
});
//对外暴露
export default requests;

11.API接口统一管理

在api文件下新建文件index.js

(以三级联动接口为例)

在这里插入图片描述

本地浏览器向服务器发送请求,出现问题,因为跨域了

常用解决方法:JSONP、CORS、代理

12.代理

选择代理方法

从webpack官网文档中截取以下代码,加入vue.config.js

注意,服务器之间没有跨域问题,浏览器之间才有

//代理跨域
devServer: {
    proxy: {
      '/api': {
        target: 'http://gmall-h5-api.atguigu.cn',
        //一旦发请求时路径中带有/api,则代理服务器会转发请求,向真实服务器要数据
      },
    },
  },

13.nprogress进度条

安装

cnpm install --save nprogress

在request.js中使用

引入进度条

import nprogress from 'nprogress'

引入进度条样式

import "nprogress/nprogress.css" ;//想改样式 进入该css文件即可

在请求拦截器return之前加入进度条开始

nprogress.start();

在响应拦截器return之前加入进度条结束

nprogress.done();

14.vuex状态管理库

vuex是官方提供的一个插件,是一个状态管理库,集中式管理项目中组件公用的数据

1.安装
cnpm install --save vuex@3 //下载vue2对应的vuex版本
2.创建总仓库

在src新建store文件夹 index.js(总仓库)

此处模块化开发

//该文件用于创建Vuex中最为核心的store
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex)

import home from './home'
import search from './search'

//创建并暴露store
export default new Vuex.Store({
	modules:{
        home,
        search
    }

})
3.创建小仓库

举个例子 为home模块的小仓库

export default {
    namespaced:true,
    actions:{},
    mutations:{},
    state:{},
    getters:{}
}

在main.js中

4.引入仓库
import store from './store'
5.注册仓库
new Vue({
  render: h => h(App),
  //注册路由
  router,//完整写法为router:router,但因kv一致,可以简写
  //注册仓库
  store,//组件实例会增加一个$store属性
}).$mount('#app')
错误

1.vuex版本下载太新了,不适配vue2

2.modules 是复数

15.动态展示三级联动数据

挂载完毕就请求数据,放在根组件里,这样防止重复请求数据

mounted() {
        //通知Vuex发送请求,获取数据,存储于仓库之中
        this.$store.dispatch('home/categoryList');
    },

在对应组件仓库中,即store/home/index.js

引入三级联动接口

import {reqCategoryList} from '@/api'

通过actions向接口请求数据

actions:{
        async categoryList({commit}){
            let result =await reqCategoryList();
            if(result.code===200){
                commit('CATEGORYLIST',result.data)
            }
        }
    },

如果不加async和await,获取到的就是一个promise对象,写了则可直接获得data

在这里插入图片描述

改变数据

mutations:{
        CATEGORYLIST(state,categoryList){
            state.categoryList=categoryList
        }
    },

存储数据

state:{
        categoryList:[]
    },

传递数据给三级联动部分 回到TypeNav/index.js

引入mapstate

import {mapState} from 'vuex'

映射为组件实例的一个属性

computed:{
        // ...mapState('home',['categoryList'])//数组写法
        ...mapState({//对象写法
            categoryList:(state)=>{
                return state.home.categoryList//home是仓库名,categoryList是state里的数据
            }
        })
    }

分结构,利用v-for层层循环嵌套

在这里插入图片描述

<div class="sort">
                    <div class="all-sort-list2">
                        <div class="item" v-for="c1 in categoryList" :key="c1.categoryid">//一级
                            <h3>
                                <a href="">{{c1.categoryName}}</a>
                            </h3>
                            <div class="item-list clearfix">
                                <div class="subitem" v-for="c2 in c1.categoryChild" :key="c2.categoryid">//二级
                                    <dl class="fore">
                                        <dt>
                                            <a href="">{{c2.categoryName}}</a>
                                        </dt>
                                        <dd>
                                            <em v-for="c3 in c2.categoryChild" :key="c3.categoryid">//三级
                                                <a href="">{{c3.categoryName}}</a>
                                            </em>
                                            
                                        </dd>
                                    </dl>
                                </div>
                            </div>
                        </div>
                      
                    </div>
                </div>
错误

1.开了命名空间使用了模块化一定注意路径问题!!!!!

手写方式:仓库命名/函数名

this.$store.dispatch('home/categoryList');

16.JS思想下的三级联动动态样式

css改也行

此处使用js来完成样式改变

在data中存储一个currentindex属性,值为-1,

给一级标题绑定鼠标进事件changeindex(index)

在methods的changeindex方法中使得this.currentindex=index

动态绑定类名:class={cur:currentindex===index}

注意 添加鼠标离开事件

改变三级分类位置 使得其和全部商品分类成为兄弟

另一个则是关于二三级分类显示与隐藏

原本用的是hover

改为js

:style="{display:currentIndex===index?'block':'none'}"
错误

1.动态绑定样式 注意block和none都要加引号!!!!

17.卡顿——节流和防抖

节流:(鼠标有关)

在规定时间内,不论你触发多少次事件,都不会触发回调,规定时间结束后,再给你挨个触发回调

防抖:(输入校验)

在规定时间内,触发一次事件,会等待一段时间再执行回调,如果在这个等待时间段内再次触发事件,则会被打断,你又得重新计时

类似:回城,老被人打断,就得再重读时间条

出现问题&解决方法

多次快速触发三级联动,会出现问题,用户移动鼠标太快,浏览器反应不过来,利用节流,给你延时一会,让浏览器反应一下来解决

引入lodash(按需引入)

import throttle from 'lodash/throttle'

使用

methods: {
        // changeIndex(index){
        //     this.currentIndex = index;
        // },
        changeIndex:throttle(function(index){//节流,此处不要用箭头函数
            setTimeout(() => {
                this.currentIndex = index;
            }, 50);
            
        }),
        clearIndex(){
            setTimeout(() => {//解决bug
                this.currentIndex = -1;
            }, 55);
        }
    },
bug

加了节流后,快速移入移出会导致某个一级分类一直是蓝色,原因是移出的代码执行后又执行了一次移入的代码。移出时,currentindex确实为-1了,但是因为移入身上的定时器,致使虽然移出但我的定时器还在,延时时间结束,执行了this.currentIndex = index;的回调,导致某个一级分类一直是蓝色。

解决:给移出的代码加个延时器,时间大于或等于移入的时间

18.三级联动路由跳转和传参数

问题

如果直接把a改为router-link,会导致卡顿,因router-link是一个组件,一旦开始循环层层渲染,反复创建router-link组件,而组件又转化为组件实例,此过程很耗内存

如果绑定点击事件,也会导致回调太多

故而利用编程式导航+委派

给父节点委派绑定点击事件,则点击范围太广,无法定位到a标签身上,即我给父节点委派了,但只要子节点里的a标签才能触发,并且,还要区分一级二级三级分类

解决方法

首先为父节点委派绑定点击任务

为a添加自定义属性,:data-cateName=“c1/2/3.categoryName”(只有a标签有),:data-cate1id=“c1.categoryId”(不一一举例了)(只有相应分类有),配合event.target,实现定位a并分类

event.target

在获取目标事件源的情况,一般情况下我们获取目标事件源都是谁是调用者谁就是事件源,但是当有批量的DOM需要操作的时候,要判断哪一个dom是事件源就不是很明确了,使用e.target可以准确地获取事件源,并且在使用的过程中可以比较判断,从而实现我们的代码。

event.target可以获取当前点击元素,返回结果如下

在这里插入图片描述

如此便可以锁定a标签并分类

event.target.dataset

而event.target.dataset,可以获取自定义属性

在这里插入图片描述

注意!自定义属性里我们可能data-cateName写成驼峰命名法,而浏览器会自动将自定义属性全部转化为小写!!!

这意味着标签里管他咋写,但在方法里我们得小写!!!!

let {catename,cate1id,cate2id,cate3id} = event.target.dataset
//这里用了解构赋值,花括号里的和dataset里面的属性名称对应上了,就能把属性值赋给它
console.log(catename,cate1id,cate2id,cate3id);

锁定a标签并分类,目的是为点击跳转时,不同级别标题我们能跳转往不同页面并且携带参数,结合编程式导航

goSearch(event){//千万注意!标签里绑定点击事件要传参,且因为传的是event,所以绑定的时候是@click="goSearch($event)"
            let {catename,cate1id,cate2id,cate3id} = event.target.dataset
            if(catename){//是a标签吗?
                let location = {name:'search'}//跳转路径
                let query = {catename:catename}//传参,我占位符后面加了问号,可以name和query配合
                if(cate1id){//是一级标题吗?
                    query.cate1id=cate1id
                }else if(cate2id){//是二级吗?
                    query.cate2id=cate2id
                }else if(cate3id){//是三级吗?
                    query.cate3id=cate3id
                }
                location.query =query;//为location添加一个query属性
                this.$router.push(location);
            }
            
        }

在这里插入图片描述

错误

1.注意!自定义属性里我们可能写成驼峰命名法,而浏览器会自动将自定义属性全部转化为小写!!!

这意味着标签里管他咋写,但在方法里我们得小写!!!!

2.千万注意!标签里绑定点击事件要传参,且因为传的是event,所以绑定的时候是**@click=“goSearch($event)”**

19.合并参数

每次push时看看¥route里面有没有query或者params参数,有就塞在location里一起带过去

错误

1.search中 注意是挂载完成后三级分类板块就不再显示,

2.对于鼠标移入移出,注意绑定事件对象,是父亲而不是儿子,否则鼠标放在”全部商品分类“上刚展示一级菜单,鼠标一移开就不显示了,在显示的同时是需要一级菜单保留的,而绑定在父亲身上就不会产生此类问题

20.ListContainer

利用mockjs插件模拟数据

安装

cnpm install mockjs

在src创建mock文件夹

准备json数据

将mock需要的图片放在public的images下

创建mockServer.js文件,通过mockjs插件实现模拟数据

import Mock from 'mock.js'
//json 默认对外暴露 图片也是默认暴露的
import banner from './banner.json'
import floor from './floor.json'

Mock.mock('/mock/banner',{code:200,data:banner});
Mock.mock('mock/floor',{code:200,data:floor})

在入口文件中引入

import '@/mock/mockServer'

配置接口文件

在api文件夹下新建MockAjax.js

文件和二次封装axios的文件一模一样,唯独就是baseURL那里改成 ‘/mock’

在api/index.js

引入配置文件

import mockRequests from './MockAjax'

创建并暴露接口

export const reqgetBannerList =()=> mockRequests({url:'/banner',method:'get'})

在store/home/index.js内

引入reqgetBannerList接口

把连环状态啥的都再写一遍

在app.js中用dispatch发送请求,然后listcontainer里引入mapstate来接收

再循环

跟三级组件差不多

swiper

安装

cnpm install --save swiper@5

引入swiper样式(在main里引入)

import swiper from 'swiper'

引入swiper 在相应组件里引入

import Swiper from 'swiper'

创建swiper实例

问题

不能在mounted里写,因为v-for在动态遍历服务器返回的数据,此时页面结构不完整,却先实例化了swiper,而在实例化swiper时之前,页面结构必须完整

update也不行,因为数据更新一次就创建一次

总而言之就是dispatch设计到了异步问题

在这里插入图片描述

如上图所示,数据还没修改完就实例化swiper,页面结构不完整,所以无法实现轮播图

解决办法

根据我在弹幕上看到的,由async和await来解决

async和await

在这里插入图片描述

async mounted() {
    await this.$store.dispatch("home/getBannerList");
    var mySwiper = new Swiper(document.querySelector(".swiper-container"), {
        //此处可以用ref,获取DOM,写法为:new Swiper(this.$refs.xxxxx(这个xxx看你上面ref:"xxxx"里面咋起的名了),{})
      //   autoplay: 5000, //可选选项,自动滑动
      loop: true, //可选选项,开启循环
      pagination: {
        el: ".swiper-pagination",
      },
      navigation: {
        nextEl: ".swiper-button-next",
        prevEl: ".swiper-button-prev",
      },
    });
  },

或利用watch监听属性+nextTick,监听bannerList数据的变化

watch+nextTick
watch:
	bannerList:{
		handler(newValue,oldValue){
			var mySwiper = new Swipe......
			//这样也会出问题,因为我监听到了数据变化,但没不知道有没有渲染完成,只有v-for执行完毕才有了完整结构
		}
	}

在这里插入图片描述

可以保证页面有结构

mounted() {
    this.$store.dispatch("home/getBannerList");
    this.$nextTick(()=>{
        var mySwiper = new Swiper(document.querySelector(".swiper-container"), {
          //autoplay: 5000, //可选选项,自动滑动
          loop: true, //可选选项,开启循环
          pagination: {
            el: ".swiper-pagination",
          },
          navigation: {
            nextEl: ".swiper-button-next",
            prevEl: ".swiper-button-prev",
          },
        });
    })
  },
错误

引入Mock时时mockjs 没有点

dispatch是又忘了模块化时写法改变了

ref做标记,

21.Floor组件

组件通信

1.props

2.自定义事件

3.全局事件总线

4.消息订阅与发布

5.插槽

6.vuex

错误

1.在home里floor组件有两个,这意味着这两个floor是要利用v-for来使用的,所以dispatch不是在floor的vue内,而是在home的vue内

2.因为获取数据是在home这个父组件内,需要父子间进行组件通信,此处利用props,:list=“floor”,这个list来传递,故而在子组件里也是props:[‘list’],是list,不是floor,是名,不是内容

3.在home内已经完成了floor的的遍历,当我们使用:list=“floor”,向子组件传递过来了一个floor,所以接收后,对于list已经无需再遍历,懂不!我给你了一个floor,名子叫list,那在子组件里你直接用插值语法{{list.name}}来获取数据就完事了!

4.别瞎用遍历,普通图片直接写就行,就:src="list.recommendList[0]"就行,没必要再遍历

5.此处可以直接在mounted里面new swiper了,因为没有在floor里dispatch,其数据由父组件已经接收了,结构已经搭建完毕,父组件将数据发给子组件,子组件的v-for只会在等到了依赖的数据后才会开始解析渲染

  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值