首页 > 其他分享 >Vue项目首页实战 - 父子组组件间传值

Vue项目首页实战 - 父子组组件间传值

时间:2023-06-14 10:02:44浏览次数:43  
标签:Vue res height item 首页 components import data 传值

1 city

Home.vue新增一个属性:

<template>
   <div>
     <home-header :city="city"></home-header>
     <home-swiper></home-swiper>
     <home-icons></home-icons>
     <home-recommend></home-recommend>
     <home-weekend></home-weekend>
   </div>
 </template>
export default {
   name: 'Home',
   // 声明 局部组件,注册到 Home 组件之后,Home的模板里就能使用它了
   components: {
     HomeHeader,
     HomeSwiper,
     HomeIcons,
     HomeRecommend,
     HomeWeekend
   },
   data () {
     return {
       city: ''
     }
   },

修改对应的 Header 组件:

<script>
 export default {
   name: 'HomeHeader',
   props: {
     city: String
   }
 }
 </script>

ajax请求到数据后,要拿到数据内容:

Vue项目首页实战 - 父子组组件间传值_ios

效果:

Vue项目首页实战 - 父子组组件间传值_ios_02

别急,还有获得的其他字段呢。

2 Swiper.vue

将之前定义的 list 删除,并新增一个 props:

【Swiper.vue】

<template>
 <!--  div来包裹整个轮播图,防止图片还未加载出来导致轮播图区域下面的东西提前显示
 最后又移动位置了-->
   <div class="wrapper">
 <!--    通过v-if来判断是否展示轮播图,如果list数组有数据则展示,否则不展示-->
     <swiper :options="swiperOption" v-if="showSwiper">
       <swiper-slide v-for="item of list" :key="item.id">
         <img class="swiper-img" :src="item.imgUrl" />
       </swiper-slide>
 <!--      在swiper标签里面使用了一个不带页码的点号显示,通过slot来实现-->
       <div class="swiper-pagination"  slot="pagination"></div>
     </swiper>
   </div>
 </template>
 
 <script>
 export default {
   name: 'HomeSwiper',
   props: {
     list: Array
   },
   // 子组件中定义 data 时,必须是个函数 ES6中可省略 function 简化代码
   data () {
     return {
       swiperOption: {
         pagination: '.swiper-pagination',
         // 轮播图支持循环轮播
         loop: true
       }
     }
   },
   computed: {
     // 判断list数组是否有数据,如果有则返回true,展示轮播图
     showSwiper () {
       return this.list.length
     }
   }
 }
 </script>
 
 <style lang="stylus" scoped>
 // <<<  符号表示使用深度选择器,可以选择父级的所有后代元素。
 .wrapper >>> .swiper-pagination-bullet-active
   // 将轮播图的当前页码的背景颜色设为白色
   background: #fff
 .wrapper
   overflow: hidden
   width: 100%
   height: 0
   // 这里是为了实现固定的宽高比(标准写法)
   padding-bottom: 31.25%
   background: #eee
   .swiper-img
     width: 100%
 </style>

连带修改,得到 AJAX 接收到的值:

【Home.vue】

data () {
   return {
     city: '',
     // 新增
     swiperList: []
   }
 },
 methods: {
   getHomeInfo () {
     axios.get('/api/index.json')
       .then(this.getHomeInfoSuccess)
   },
   getHomeInfoSuccess (res) {
     res = res.data
     if (res.ret && res.data) {
       const data = res.data
       this.city = data.city
       // 新增
       this.swiperList = data.swiperList
     }
   }
 },

效果:

Vue项目首页实战 - 父子组组件间传值_ci_03

3 icons

【Icons.vue】修改如下:

<!--在页面上显示一个图标集合,通过Swiper实现分页滑动效果-->
 <template>
   <div class="icons">
     <!-- 在模板中,使用Swiper组件 并将swiperOption作为参数传入 swiperOption中设置了autoplay为false。-->
     <swiper :options="swiperOption">
       <!-- v-for循环遍历page数组中的每个元素,即每一页中的每个图标-->
       <swiper-slide v-for="(page, index) of pages" :key="index">
         <!-- 使用div包裹每个图标,并设置其样式。-->
         <div class="icon" v-for="item of page" :key="item.id">
           <div class='icon-img'>
             <img class='icon-img-content' :src='item.imgUrl'/>
           </div>
           <p class="icon-desc">{{ item.desc }}</p>
         </div>
       </swiper-slide>
     </swiper>
   </div>
 </template>
 
 <script>
 export default {
   name: 'HomeIcons',
   props: {
     list: Array
   },
   computed: {
     pages () {
       const pages = []
       // 将list数组中的每个元素,按8个为一组进行分页
       // 存储在pages数组
       this.list.forEach((item, index) => {
         const page = Math.floor(index / 8)
         if (!pages[page]) {
           pages[page] = []
         }
         pages[page].push(item)
       })
       return pages
     }
   }
 }
 </script>
 
 <!--设置图标的基本样式,包括宽高、位置 图标图片和描述的样式。-->
 <style lang="stylus" scoped>
 @import '~styles/varibles.styl'
 @import '~styles/mixins.styl'
 .icons >>> .swiper-container
   height: 0
   padding-bottom: 50%
 
 .icons
   margin-top: .1rem
 
   .icon
     position: relative
     overflow: hidden
     float: left
     width: 25%
     height: 0
     padding-bottom: 25%
 
     .icon-img
       position: absolute
       top: 0
       left: 0
       right: 0
       bottom: .44rem
       box-sizing: border-box
       padding: .1rem
 
       .icon-img-content
         display: block
         margin: 0 auto
         height: 100%
 
     .icon-desc
       position: absolute
       left: 0
       right: 0
       bottom: 0
       height: .44rem
       line-height: .44rem
       text-align: center
       color: $darkTextColor
       ellipsis()
 </style>

【Home.vue】

<template>
   <div>
     <home-header :city="city"></home-header>
     <home-swiper :list="swiperList"></home-swiper>
     <home-icons :list="iconList"></home-icons>
     <home-recommend></home-recommend>
     <home-weekend></home-weekend>
   </div>
 </template>
 
 <script>
 import HomeHeader from './components/Header'
 import HomeSwiper from './components/Swiper'
 import HomeIcons from './components/Icons'
 import HomeRecommend from './components/Recommend'
 import HomeWeekend from './components/Weekend'
 import axios from 'axios'
 
 export default {
   name: 'Home',
   // 声明 局部组件,注册到 Home 组件之后,Home的模板里就能使用它了
   components: {
     HomeHeader,
     HomeSwiper,
     HomeIcons,
     HomeRecommend,
     HomeWeekend
   },
   data () {
     return {
       city: '',
       swiperList: [],
       iconList: []
     }
   },
   methods: {
     getHomeInfo () {
       axios.get('/api/index.json')
         .then(this.getHomeInfoSuccess)
     },
     getHomeInfoSuccess (res) {
       res = res.data
       if (res.ret && res.data) {
         const data = res.data
         this.city = data.city
         this.swiperList = data.swiperList
         this.iconList = data.iconList
         this.recommendList = data.recommendList
         this.weekendList = data.weekendList
       }
     }
   },
   mounted () {
     this.getHomeInfo()
   }
 }
 </script>
 
 <style>
 </style>

效果:

Vue项目首页实战 - 父子组组件间传值_ico_04

4 recommend && weekend

<!--用于在页面上展示商品列表-->
 <!--组件接受一个名为list的数组作为参数,每个元素包含商品的标题、描述和图片等信息。
 组件会在页面上渲染一个标题“热销推荐”和一个商品列表,
 每个商品都包含标题、描述、图片和一个“查看详情”的按钮。
 当用户点击某个商品时,组件会跳转到该商品的详情页。-->
 
 <!--代码中的<template>部分定义了组件的HTML结构,包括一个标题和一个商品列表。
 商品列表中的每个商品都是一个<router-link>标签,用于实现页面跳转。
 :v-for指令用于遍历list数组中的每个元素,并将其绑定到变量item上,
 :key指令用于为每个商品设置一个唯一的标识符。-->
 <template>
   <div>
     <div class="title">热销推荐</div>
     <ul>
       <router-link
         tag="li"
         class="item border-bottom"
         v-for="item of list"
         :key="item.id"
         :to="'/detail/' + item.id"
       >
         <img class="item-img" :src="item.imgUrl"/>
         <div class="item-info">
           <p class="item-title">{{ item.title }}</p>
           <p class="item-desc">{{ item.desc }}</p>
           <button class="item-button">查看详情</button>
         </div>
       </router-link>
     </ul>
   </div>
 </template>
 
 <script>
 export default {
   name: 'HomeRecommend',
   props: {
     list: Array
   }
 }
 </script>
 
 <!-- 样式都是基于flex布局实现的,以便在不同设备上适应不同的屏幕尺寸。-->
 <style lang="stylus" scoped>
 @import '~styles/mixins.styl'
 // 设置标题的样式
 .title
   margin-top: .2rem
   line-height: .8rem
   background: #eee
   text-indent: .2rem
 
 // .item样式用于设置商品的样式,包括图片、标题、描述和按钮等。
 .item
   overflow: hidden
   display: flex
   height: 1.9rem
 
   .item-img
     width: 1.7rem
     height: 1.7rem
     padding: .1rem
 
   .item-info
     flex: 1
     padding: .1rem
     min-width: 0
 
     .item-title
       line-height: .54rem
       font-size: .32rem
       ellipsis()
 
     .item-desc
       line-height: .4rem
       color: #ccc
       ellipsis()
 
     .item-button
       line-height: .44rem
       margin-top: .16rem
       background: #ff9300
       padding: 0 .2rem
       border-radius: .06rem
       color: #fff
 </style>
 

[Home.vue]

<template>
   <div>
     <home-header :city="city"></home-header>
     <home-swiper :list="swiperList"></home-swiper>
     <home-icons :list="iconList"></home-icons>
     <home-recommend :list="recommendList"></home-recommend>
     <home-weekend></home-weekend>
   </div>
 </template>
 
 <script>
 import HomeHeader from './components/Header'
 import HomeSwiper from './components/Swiper'
 import HomeIcons from './components/Icons'
 import HomeRecommend from './components/Recommend'
 import HomeWeekend from './components/Weekend'
 import axios from 'axios'
 
 export default {
   name: 'Home',
   // 声明 局部组件,注册到 Home 组件之后,Home的模板里就能使用它了
   components: {
     HomeHeader,
     HomeSwiper,
     HomeIcons,
     HomeRecommend,
     HomeWeekend
   },
   data () {
     return {
       city: '',
       swiperList: [],
       iconList: [],
       recommendList: []
     }
   },
   methods: {
     getHomeInfo () {
       axios.get('/api/index.json')
         .then(this.getHomeInfoSuccess)
     },
     getHomeInfoSuccess (res) {
       res = res.data
       if (res.ret && res.data) {
         const data = res.data
         this.city = data.city
         this.swiperList = data.swiperList
         this.iconList = data.iconList
         this.recommendList = data.recommendList
         this.weekendList = data.weekendList
       }
     }
   },
   mounted () {
     this.getHomeInfo()
   }
 }
 </script>
 
 <style>
 </style>
 

[weekend.vue]

<template>
   <div>
     <div class="title">周末去哪儿</div>
     <ul>
       <li
         class="item border-bottom"
         v-for="item of list"
         :key="item.id"
       >
         <div class="item-img-wrapper">
           <img class="item-img" :src="item.imgUrl" />
         </div>
         <div class="item-info">
           <p class="item-title">{{item.title}}</p>
           <p class="item-desc">{{item.desc}}</p>
         </div>
       </li>
     </ul>
   </div>
 </template>
 
 <script>
 export default {
   name: 'HomeWeekend',
   props: {
     list: Array
   }
 }
 </script>
 
 <style lang="stylus" scoped>
   @import '~styles/mixins.styl'
   .title
     line-height: .8rem
     background: #eee
     text-indent: .2rem
   .item-img-wrapper
     overflow: hidden
     height: 0
     padding-bottom: 37.09%
     .item-img
       width: 100%
   .item-info
     padding: .1rem
     .item-title
       line-height: .54rem
       font-size: .32rem
       ellipsis()
     .item-desc
       line-height: .4rem
       color: #ccc
       ellipsis()
 </style>
 

效果:

Vue项目首页实战 - 父子组组件间传值_ico_05

Vue项目首页实战 - 父子组组件间传值_ios_06


标签:Vue,res,height,item,首页,components,import,data,传值
From: https://blog.51cto.com/JavaEdge/6475607

相关文章

  • vuex基础语法
    //importVuexfrom"vuex";//importVuefrom"vue";//Vue.use(Vuex);///*//vuex作用:数据共享//用法:在store新建一个js文件;newVuex.Store//方法://state:初始状态数据//mutations:监控数据的变化//流程:state仓库---UI---mutations(提交方法:commit)//注意:必须......
  • vue实现子父组件之间通信
    <template><div><button@click="handleClick":disabled="isLoading">{{isLoading?"loading":"submit"}}</button><divclass="err">......
  • vue事件总线
    //事件总线:类似于单独对于一个功能的处理。组件间通信的方式;适用于任意组件间通信//exportdefault{////监控事件//$on(eventName,handler){//if(!listeners[eventName]){//listeners[eventName]=newSet();//}//......
  • C++面试八股文:C++中,函数的参数应该传值还是传引用?
    C++面试八股文:C++中,函数的参数应该传值还是传引用?某日二师兄参加XXX科技公司的C++工程师开发岗位第8面:面试官:C++中,函数的参数应该传值还是传引用?二师兄:要看参数的用途。如果是出参,必须传引用。如果是入参,主要考虑参数类型的大小,来决定传值还是传引用。面试官:为什么不使用......
  • vue组件之间的数据传递
    一、组件之间的关系父子关系、兄弟关系、跨级关系二、父子之间数据传递1、父组件向子组件传递【使用props】第一步:在父组件中使用子组件时,给子组件绑定属性第二步:在子组件中使用props接收绑定的属性值2、子组件向父组件传递【使用$emit】第一步:在子组件中通过......
  • vue路由
    1、在dos窗口下安装npminstallvue-router@3--save-dev--registry=http://registry.npmmirror.com2、配置路由①在src目录下面,新建router文件夹②然后再其中创建index.js路由文件、index.js代码importVuefrom'vue'//导入路由插件importVueRouterfrom'......
  • 【vue】前端下载文件自定义文件名称
    【vue】前端下载文件自定义文件名称https://blog.csdn.net/weixin_48200589/article/details/125067618下载文件自定义文件名称文件下载名称不想和后端提供的URL一样怎么办呢?1.首先给按钮去绑定一个事件2.正常我们的下载处理方式3.自定义下载的文件名字文件下载名称......
  • Vue3
    目录一vue3介绍1Vue3的变化1.1性能的提升1.2源码的升级1.3拥抱TypeScript1.4新的特性2组合式api和配置项api3vue3之vue实例4创建vue3项目4.1使用vue-cli创建4.2使用vite创建5setup6响应式6.1ref函数6.2reactive函数7reactive与ref对比8计算,监听属性8.1监......
  • Vue-watch-deep 深度监听
    首先明确一个概念,Vue是可以监听到多层级数据改变的,且可以在页面上做出对应展示。但是Vue提供的watch方法,默认是不提供深度监听的(deep默认为false,也就是不开启深度监听)(刚挂载的时候是不执行的,只有挂载完成之后的变化才会执行。如果我们想要初次挂载的时候就l执行,则需......
  • vue 的双向绑定原理(vue 的响应式原理)流程
    一、原理 二、流程第一步,“数据劫持”vue2.x用Object.defineProperty()方法来实现数据劫持,为每个属性分配一个订阅者集合的管理数组depvue3.x用ES6的Proxy构造函数来实现数据劫持。第二步,“添加订阅者”在编译的时候在该属性的数组dep中添加订阅者添加方......