Vue2.5开发去哪儿网App 从零基础入门到实战项目笔记(二)首页开发

目录结构及说明

我们编写代码是在src目录下,下面也仅分析src目录下的代码结构及意思

|——src 
| |—— assets : 资源文件
| |    |____ styles : 样式相关及iconfont 
| |—— common : 通用组件
| |    |____ fade : 渐隐渐现动画
| |    |____ gallary : 图片展示轮播
| |—— pages  : 主要的页面组件
| |    |____ city : 城市选择页面及其组件 
| |    |____ detail : 详情页面及其组件
| |    |____ home : 主页及其组件
| |—— router : 路由
| |—— store  : Vuex 状态组件
| |—— App.vue : App入口组件
| |—— main.js : 导入全部文件,调用初始化函数

入口分析

首先 main.js 是绑定在id ‘#app’上的,而这个文件就是根目录下的index.html文件里面的标签了,

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
    <title>travel</title>
  </head>
  <body>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

可以看到里面有一个id=”app”的div标签

main.js 代码里面,初始化Vue组件的代码

new Vue({
  el: '#app',
  router,
  store,
  components: { App },
  template: '<App/>'
})

可以从main.js 里面看到Vue接收一个对象,并定义了各种属性

  • el: '#app' 绑定元素
  • router router: router 的缩写,用了ES6的语法,交代路由模块
  • store 交代Vue模块,方便components通信
  • components: { App } 这个是注册组件
  • template: ‘<App/>’ 这个我几乎没遇到过,还不懂,等我懂了回来改

main.js的其他代码,导入及初始化

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'                 // 导入vue
import App from './App'               // 导入App.vue里面export 的App组件
import router from './router'         // 导入router组件
import 'styles/reset.css'             // 导入rest.css样式表,主要是一些基础设置
import fastclick from 'fastclick'     // 导入快速点击库,解决某些手机点击延迟问题
import store from './store'           // 导入store 组件,也就是我们组件之间通信的小东西
import 'styles/iconfont.css'          //  图标样式
import VueAwesomeSwiper from 'vue-awesome-swiper' // 轮播组件
import 'swiper/dist/css/swiper.css' // 轮播组件的样式
import 'styles/border.css'          // 解决手机端1像素边框样式边框问题
Vue.config.productionTip = false 
fastclick.attach(document.body)     // 把fastclick 绑定到文档上
Vue.use(VueAwesomeSwiper)           // 初始化轮播组件

再来看看我们的App.vue文件

<template>
  <div id="app">
    <keep-alive exclude="Detail">
      <router-view/>
    </keep-alive>
  </div>
</template>

<script>
export default {
  name: 'App'
}
</script>

<style>

</style>

一目了然,template放html和自定义组件、script放JS代码实现逻辑、style放样式代码

核心代码<router-view/>的作用就是告诉Vue,在这儿显示router下面的内容,默认肯定是显示根目录的内容了,后面router里,代码如下,以Home页面为例

router/index.js

import Vue from 'vue'
import Router from 'vue-router'
import home from '@/pages/home/home'
Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'home',
      component: home
    }]
})

注册路由以后,当你访问path / 时,也就是当你访问首页时,就可以访问到他对应的组件了

首页代码

首页代码结构

首先,首页时在src目录下的home 文件夹中

将首页拆分为Header、icons、Recommend、Swiper、Weekend等多个组件,放在home/components目录下,其实也就是模块化,方便维修升级嘛

然后通过home.vue将组件整合,非常符合工程化的设定,一看就是要搞大项目的节奏

自定义组件使用

以Header组件为例

创建Header.vue

首先是在components下新建Header.vue,直接套模板即可

<template>
  <div class="header">
  </div>
</template>

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

<style lang="stylus" scoped>
</style>

导入Header模块:

import HomeHeader from './components/Header'

前面的的name 属性,就是我们导入这个模块需要用到的名称了

注册组件

export default{
  name: 'home',
  components: {
    HomeHeader
  }
}

使用组件

<home-header></home-header>

使用的时候,也很简单呢

导出接口的属性和方法解释

export default{
  name: 'home',
  components: {},
  data () {
    return {
      lastCity: ''
    }
  },
  computed: {},
  methods: {
    getHomeInfo () {}
  },
  mounted () {
    this.lastCity = this.city
    this.getHomeInfo()
  },
  activated () {
    if (this.lastCity !== this.city) {
      this.lastCity = this.city
      this.getHomeInfo()
    }
  }
}

name就不多说了

components 是用来给我们自定的组件注册用的,注册之后才能使用

data 很明显是存数据的,一些参数之类的,比如首页的城市

computed : 计算属性,可以用来写一个逻辑代码在里面

methods: 顾名思义,存放方法用的,也就是各种函数,比如axios发起的http请求就可以放在里面

mounted、activated : 是状态函数,表示网页加载的不同阶段在Vue里面叫生命周期钩子 Vue官网提供的图示还是可以参考一下的

Vue 实例生命周期

但其实对我这种小白来说还是比较困惑的,所以我简单理解就是

mounted == 页面被加载完成

activated == keep-alive启动后的页面加载完成

使用axios通过网络获取数据

代码

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

首先是在data中设置一个用来接收的参数,比如这里的swiperList,被设置成了一个空数组。

紧接着在methods中定义发起异步get请求的链接和参数 getHomeInfo,和请求成功后的处理函数 getHomeInfoSucc,最后通过this.swiperList = data.swiperList 来将获取到的参数赋值给我们在data中事先定义好的参数。

父子组件传值

1.父组件给子组件传值

在我的情况里,就是home.vue给swiper.vue传值,按照下面的格式写在自定义组件中即可,list是传递到子组件之后使用的名称,swiperList 是这个数据在父组件里面使用的名称

<home-swiper :list="swiperList"></home-swiper>

子组件还需要接收这个参数, 名称+类型即可

  props: {
    list: Array
  }

然后就可以在代码中使用了

      <swiper-slide v-for="item of list" :key="item.id">
        <img class="swiper-img" v-bind:src="item.imgUrl" >
      </swiper-slide>
      <div class="swiper-pagination"  slot="pagination"></div>
    </swiper>

2.子组件给父组件传值

首先,在子组件中通过emit发送参数

methods: {
  handleLetterClick (e) {
    this.$emit('change', e.target.innerText)
  }
}

然后,在父组件中监听该操作,并制定接收参数的方法

 <city-alphabet @change="handleLetterChange"></city-alphabet>

3.父组件与父组件传值

父组件与父组件传值,其实就是通信。在学习操作系统中,我们知道进程与进程之间通信需要选择一个中间实体,比如一块共享内存,一个缓冲管道,或者某种其他的数据结构,父组件与父组件通信也需要

我们需要用到vuex,使用前需要安装

npm install vuex --save

然后在src目录下创建store,并新建index.js

src/store/index.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    city: ''
  },
  actions: {
    changeCity (ctx, city) {
      ctx.commit('changeCity', city)
    }
  },
  mutations: {
    changeCity (state, city) {
      state.city = city
    }
  }
})

所以其实就是引入Vuex并初始化,然后通过state、actions、mutations来处理,而export其实还将这个组件命名为Store,你可以通过 this.$store来访问他的方法

actions可以被跳过

然后在需要发送数据的父组件中

导入

import { mapState, mapMutations } from 'vuex'

然后发送数据

经典的发送方式

  this.$store.dispatch('changeCity', city)
  this.$store.commit('changeCity', city)

省略的方式

 ...mapMutations(['changeCity'])
this.changeCity(city)

接收

computed: {
    ...mapState(['city'])
  }

接收后就可以直接在组件中通过 this.city 调用它了,而且你还可以用对象来以重命名的方式接收他

  computed: {
    // ...mapState(['city'])
    ...mapState({
      currentCity: 'city'
    })
  },

暂无评论

发表评论

您的电子邮件地址不会被公开,必填项已用*标注。

相关推荐