vue2.5去哪儿(慕课网)学习笔记

    xiaoxiao2024-11-09  77

    vue2.5去哪儿(慕课网)学习笔记

    文章目录

    vue2.5去哪儿(慕课网)学习笔记项目预热安装环境使用到的一系列Git指令vue-cli创建的项目的基本介绍单文件组件与Vue中的路由多页应用与单页应用项目代码的初始化在项目中使用[iconfont](https://www.iconfont.cn/) 项目实战 - 旅游网站首页开发首页header区域开发准备工作Header.vue页面开发零散的知识点 使用轮播图图标区域的开发零散知识点 推荐区域的开发零散知识点 周末游区域的开发零散知识点 Ajax获取首页数据零散知识点使用axios进行ajax 旅游网站城市列表页面开发配置路由搜索框(Search.vue)城市选择列表零散的知识点Better-scroll的使用字母表的设计(alphabet.vue)零碎的知识点 兄弟组件的联动-点击转到对应区域兄弟组件的联动-在字母表上下拖拽转到对应区域搜索功能的实现零散的知识点 使用Vuex实现数据共享使用Vuex使用localstorage记住用户的选择优化 使用keep-alive优化网页性能 旅游网站详情页面开发详情页动态路由及banner布局公用图片画廊组件拆分实现Header渐隐渐显效果(起初显示一个返回按钮,下滑的时候按钮消失,显示另一个返回的箭头)对全局时间的解绑list.vue的设计编写使用Ajax获取动态数据组件中的name值有什么用页面拖拽在多个页面之中相互影响 在项目中加入基础动画 优化收尾Vue项目的接口联调Vue项目的真机测试Vue项目打包上线

    项目预热

    安装环境

    安装Node.js 官网下载安装包进行安装输入 node -v ,如果显示版本号则安装成功输入 npm -v,安装包管理工具的验证 注册码云账号并关联本地仓库 码云创建仓库[语言:Javascript;开源许可:MIT ]本地安装Git 验证:输入 git --version ,显示版本号即为成功 关联本地与云仓库 码云->设置-> SSH公钥->本地Git窗口中输入一系列linux指令生成公钥复制线上仓库SSH地址,在需要的文件中使用Git窗口输入:git clone ‘复制的内容’ 使用vue-cli脚手架创建工程 全局安装vue-cli

    npm install --global vue-cli

    创建项目

    vue init webpack ‘文件夹名称’

    运行项目

    npm run dev

    使用到的一系列Git指令

    查看git状态 git status 提交项目到云端 git add . 将项目添加到缓存git commit -m ‘注释’ 将项目添加到本地仓库git push 将项目添加到云端仓库 分支的创建与切换 直接在码云的界面创建分支或者使用指令git pull 将线上创建的分支信息拉回本地git checkout ‘分支名称’ 切换操作的分支git merge ‘分支名称’ 将分支进行合并git branch 查看分支

    vue-cli创建的项目的基本介绍

    README.md 介绍项目package.json 记录了依赖的包package-lock.json 确定依赖的包的版本信息LICENSE 开源协议的说明index.html 项目默认的首页模板文件.gitignore 记录不希望上传到云仓库的文件与目录.eslintrc.js 语法规范文件.eslintignore 记录不需要检查语法的文件与目录.editorconfig 配置了编辑器的语法.babelrc 语法解析器,将vue转化为浏览器可以识别的代码static目录 存放静态资源node_modules目录 存放依赖的包src目录 存放项目的源代码 App.vue 项目最原始的根组件main.js 项目的入口文件router目录 路由组件components目录 项目要用的组件assets 目录 存放图片资源 config目录 存放项目配置文件 index.js 存放基础的配置信息dev.env.js 开发环境的配置信息prod.env.js 线上环境的配置信息 build目录 存放打包的webpack的配置内容 webpack.base.conf.js 基础的配置项webpack.dev.conf.js 开发环境配置项webpack.prod.conf.js 线上环境配置项

    单文件组件与Vue中的路由

    /main.js 项目的入口文件

    import Vue from 'vue' import App from './App' import router from './router' new Vue({ el: '#app', router, components: { App }, template: '<App/>' })

    /App.vue 项目默认的渲染文件

    <template> <div id="app"> <keep-alive exclude="Detail"> <router-view/> //显示当前地址所对应的内容 </keep-alive> </div> </template> <script> export default { name: 'App' } </script> <style> </style>

    router/main.js 路由配置文件

    import Vue from 'vue' import Router from 'vue-router' import Home from '@/pages/home/Home' import City from '@/pages/city/City' import Detail from '@/pages/detail/Detail' Vue.use(Router) export default new Router({ routes: [ { path: '/', name: 'Home', component: Home }, { path: '/city', name: 'City', component: City }, { path: '/detail/:id', name: 'Detail', component: Detail } ], })

    多页应用与单页应用

    多页应用 每次请求一个HTML首屏时间快,SEO效果好页面切换慢 单页应用 vue中使用: 列表页面 进行跳转使用JS感知页面的变化,然后清除当前页面的内容,显示新的内容特点 页面切换快首屏时间慢,SEO差使用JS渲染

    项目代码的初始化

    1./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> </body> </html> 引入重置页面的样式表 reset.css和一像素边框border.css和‘300毫秒延迟点击问题’fastclick库 将文件添加进来在main.js中添加代码

    import ‘./assets/styles/reset.css’ import ‘./assets/styles/border.css’

    关于fastckick库 npm install fastclick --save引入

    import fastclick from ‘fastckick’

    使用

    fastclick.attach(document.body)

    在项目中使用iconfont

    收集图标 创建帐号新建项目浏览图标库,将要使用的图表添加到购物车将购物车的内容添加至项目在项目中‘下载至本地’ 使用图标 解压文件包 将iconfont.eot,iconfont.svg,iconfont.ttf,iconfont.woff 添加到项目的assets/styles/iconfont/中将iconfont.css文件放到iconfont文件夹同级,修改下其中涉及到其他文件的路径 引入文件 在main.js中引入iconfont

    import ‘./assets/styles/iconfont.css’

    使用 在需要使用的地方

    图标代码 图表代码可以在购物车中的图表上查看

    项目实战 - 旅游网站首页开发

    首页header区域开发

    准备工作

    安装stylus

    install stylus --save install stylus-loader --save

    设计布局 home.vue 作为展示的容器,内部使用各个组件来搭页面在同一级创建目录‘components’,内部新建header.vue在 home.vue中引入并在components这个区域中命名它

    Header.vue页面开发

    零散的知识点
    限制样式只在当前页面有用,使用scoped对css区域进行修饰关于stylus 在reset.css中的html中的font-size: 50px 指示了 1rem=50px想要靠近可以设置负值将常使用的值设为变量 在styles文件夹中添加varibles.styl

    设置变量 $bgColor = #00bcd4

    在的首行进行引入

    import ‘~styles/assets/styles/varibles.styl’

    使用的时候,在值的部分输入

    $bgColor

    将常用的路径设置为常量(符号表示) 在build/webpack.base.conf.js中,resolve: 中的alias:中添加一个键值对

    ‘styles’ : resolve(‘src/assets/styles’),

    使用轮播图

    查看插件与语法 在GitHub上搜索vue-awesome-swiper新版可能存在bug,建议使用老版本 安装 npm install vue-awesome-swiper@2.6.7 --save 引入 在main.js中引入和使用

    import ‘swiper/dist/css/swiper.css’ import VueAwesomeSwiper from ‘vue-awesome-swiper’ Vue.use(VueAwesomeSwiper,‘可以给个参数’)

    使用,建立swiper.vue <template> <div class="wrapper"> <div class="iconw"> <div class="iconw-img"> <swiper :options="swiperOption" v-if="showSwiper" > //应用轮播插件 <swiper-slide v-for="item of list" :key="item.id"> <img class="swipper-img" :src="item.imgUrl" /> </swiper-slide> <div class="swiper-pagination" slot="pagination"></div> //应用下面的选择点 </swiper> </div> </div> </div> </template> <script> export default { name: 'HomeSwiper', props: { list: Array }, data () { return { swiperOption: { pagination: '.swiper-pagination', loop: true //可以从最好一个滚回到第一个 } } }, computed: { showSwiper () { return this.list.length } } } </script> <style lang="stylus" scoped> .wrapper >>> .swiper-pagination-bullet-active //样式穿透,将设置应用在非当前页面的class样式中,不受scoped的限制 background: #fff .wrapper overflow: hidden height: 0 padding-bottom: 30.9% //将高度设置为宽度的30.9% background: green .iconw position: relative .iconw-img position: absolute top: 0 left: 0 right: 0 .swipper-img width: 100% </style>

    图标区域的开发

    零散知识点

    利用computed进行计算:每8个图表放一个页面 data () { return { swiperOption: { autoplay: false //不允许自动播放 } } }, computed: { pages () { const pages = [] this.list.forEach((item, index) => { const page = Math.floor(index / 8) if (!pages[page]) { pages[page] = [] } pages[page].push(item) }) return pages } } 将图标名字长的部分进行隐藏,显示三个点 .icon-desc position: absolute left: 0 right: 0 bottom: 0 height: .44rem line-height: .44rem text-align: center color: $darkTextColor //以下三句话实现隐藏加点 overflow: hidden white-sapce: nowrap text-overflow: ellipsis

    推荐区域的开发

    零散知识点

    1像素边框的使用

    <li class="item **border-bottom** ">

    周末游区域的开发

    零散知识点

    有些时候希望组件的内容可以被调用的组件进行定制,使用 slot=""

    Ajax获取首页数据

    零散知识点

    json数据的最后一个大括号后面不要加逗号,否则可能出错

    使用axios进行ajax

    进行安装相应的模块

    npm install axios --save

    处理请求的api在开发环境进行重定向(转发) 开发中只有static中的文件可以被访问到,故在static文件夹中新建mock文件夹,然后建立index.json在config/index.js中的dev中的proxyTable中添加对象 proxyTable: { '/api': { target: 'http://localhost:8080', pathRewrite: { '^/api': '/static/mock' } } 在Home.vue进行使用 首先引入

    import axios from ‘axios’

    在mounted进行使用mounted () { this.getHomeInfo() }, 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 this.iconList = data.iconList this.recommendList = data.recommendList this.weekendList = data.weekendList this.cities = data.cities } } } 调用其他vue页面的时候将参数传递进去

    <city-al :citise="cities"><city-al>

    被调用的页面进行接收

    props:{ cities:Object }

    被调用的页面在接收后进行使用 <li class="item" v-for="item of letters" :key="item" :ref="item">{{item}}</li>

    旅游网站城市列表页面开发

    配置路由

    /router/index.js

    import Vue from 'vue' import Router from 'vue-router' import Home from '@/pages/home/Home' import City from '@/pages/city/City' import Detail from '@/pages/detail/Detail' Vue.use(Router) export default new Router({ routes: [ { path: '/', name: 'Home', component: Home }, { path: '/city', name: 'City', component: City }, { path: '/detail/:id', name: 'Detail', component: Detail } ], scrollBehavior (to, from, savedPosition) { return {x: 0, y: 0} //页面切换后从顶部开始显示内容 } })

    Header中点击城市名,将页面跳转到城市选择页面

    <router-link to='/city'> <div class="header-right"> {{this.city}} <span class="iconfont arrow-icon"></span> </div> </router-link>

    搜索框(Search.vue)

    搜索框样式

    <style lang="stylus" scoped> @import '~styles/varibles.styl' .search height: .72rem padding: 0 .1rem background: $bgColor .search-input box-sizing: border-box width: 100% height: .62rem padding: 0 .1rem line-height: .62rem text-align: center border-radius: .06rem color: #666 .search-content z-index: 1 overflow: hidden position: absolute top: 1.58rem left: 0 right: 0 bottom: 0 background: #eee .search-item line-height: .62rem padding-left: .2rem color: #666 background: #fff </style>

    城市选择列表

    零散的知识点

    修改之前引入的1像素边框的颜色 .border-topbottom &:before border-color: #ccc &:after border-color: #ccc

    Better-scroll的使用

    安装

    npm install better-scroll --save

    使用规范 查看Git官网的项目,来认识他的使用规范两层div里面放需要的内容,如其他的div,或者li等标签 使用 利用ref来获取dom 在需要使用scroll的div中添加

    <div class="list" ref="wrapper">

    引入

    import Bscroll from ‘better-scroll’

    在mounted中实例化

    mounted () { this.scroll = new Bscroll(this.$refs.wrapper) },

    字母表的设计(alphabet.vue)

    零碎的知识点
    通过点击获取li标签里面的文本

    console.log(e.target.innerText)

    样式 <style lang="stylus" scoped> @import '~styles/varibles.styl' .list display: flex list-style:none flex-direction: column justify-content: center position: absolute top: 1.58rem right: 0 bottom: 0 width: .4rem .item line-height: .44rem text-align: center color: $bgColor </style>

    兄弟组件的联动-点击转到对应区域

    目的:实现点击一个字母(alphabet.vue),将城市选择(cityList.vue)跳转到字母对应的区域

    首先在字母的li上绑定一个事件

    <li @click="handleLetterClick" >{{key}}</li>

    实现这个方法

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

    主页面中对这个组件进行监听

    <city-alphabet :cities=“cities” @change=“handleLetterChange”>

    实现handleLetterChange这个方法

    handleLetterChange (letter) { this.letter = letter }

    将letter传递给cityList.vue组件

    <city-list :cities="cities" :hot="hotCities" :letter="letter"></city-list>

    cityList.vue中进行接收

    props: { hot: Array, cities: Object, letter: String },

    利用侦听器进行侦听,若letter改变,则显示对应的区域

    watch: { letter () { if (this.letter) { const element = this.$refs[this.letter][0] this.scroll.scrollToElement(element) } } }

    在li标签中进行显示

    <div class="area" v-for="(item,key) of cities" :key="key" :ref="key"> <div class="title border-topbottom">{{key}}</div> //key中的值为A,B,C,D... <div class="item-list"> <div class="item border-bottom" v-for="innerItem of item" :key="innerItem.id" > {{innerItem.name}} //为具体的城市名称 </div> </div> </div>

    兄弟组件的联动-在字母表上下拖拽转到对应区域

    目的:实现在字母表(alphabet.vue)上滑动,将城市选择(cityList.vue)跳转到字母对应的区域

    在li标签中绑定一个事件

    <li class="item" v-for="item of letters" :key="item" :ref="item" @touchstart.prevent="handleTouchStart" @touchmove="handleTouchMove" @touchend="handleTouchEnd">{{item}}</li>

    实现对应的三个方法 props: { cities: Object }, computed: { letters () { const letters = [] for (let i in this.cities) { letters.push(i) } return letters } }, data () { return { touchStatus: false, startY: 0, timer: null } }, updated () { //当页面的数据被更新,页面完成了渲染 this.startY = this.$refs['A'][0].offsetTop //A距离顶部的高度 }, methods: { handleTouchStart () { this.touchStatus = true }, handleTouchMove (e) { if (this.touchStatus) { if (this.timer) { //提高效率,避免过于频繁的刷新 clearTimeout(this.timer) } this.timer = setTimeout(() => { const touchY = e.touches[0].clientY - 79 const index = Math.floor(touchY - this.startY) / 20 //算出当前手指的位置对应的字母下标 if (index >= 0 && index < this.letters.length) { this.$emit('change', this.letters[index]) } }, 16) } }, handleTouchEnd () { this.touchStatus = false } }

    搜索功能的实现

    Search.vue接收来自主页面的cities这个参数,并设置一个div,在查询内容不为空的条件下(v-show)显示,展示查询结果。

    零散的知识点

    运算放在computed中 <template> <div> <div class="search"> <input v-model="keyword" class="search-input" type="text" placeholder="输入城市名或拼音"/> </div> <div class="search-content" ref="search" v-show="keyword"> <ul> <li class="search-item border-bottom" v-for="item of list" @click="handleCityClick(item.name)" :key="item.id"> {{item.name}}</li> <li class="search-item border-bottom" v-show="hasNoData">没有找到匹配数据</li> </ul> </div> </div> </template> <script> import Bscroll from 'better-scroll' import { mapMutations } from 'vuex' export default { name: 'CitySearch', props: { cities: Object }, mounted () { this.scroll = new Bscroll(this.$refs.search) }, data () { return { keyword: '', list: [], timer: null } }, computed: { hasNoData () { return !this.list.length } }, methods: { handleCityClick (city) { this.changeCitys(city) this.$router.push('/') }, ...mapMutations(['changeCitys']) }, watch: { keyword () { if (this.timer) { clearTimeout(this.timer) } if (!this.keyword) { this.list = [] return } this.timer = setTimeout(() => { const result = [] for (let i in this.cities) { this.cities[i].forEach((value) => { if (value.spell.indexOf(this.keyword) > -1 || value.name.indexOf(this.keyword) > -1) { result.push(value) } }) } this.list = result }, 100) } } } </script>

    使用Vuex实现数据共享

    此时city与home,没有公用的组件,数据传递可以适用bus或者vuex。vuex是传递大量数据的数据框架

    使用Vuex

    安装

    npm install vuex --save

    新建src/store/index.js import Vue from 'vue' import Vuex from 'vuex' import state from './state' import mutations from './mutations' Vue.use(Vuex) export default new Vuex.Store({ state: state, mutations: mutations, getters: { doubleCity (state) { return state.city + ' ' + state.city } } }) 在main.js中引入

    import store from ‘./store’

    new Vue({ el: '#app', store: store, router, components: { App }, template: '<App/>' }) 在Header.vue中进行操作,将显示城市的内容改为

    this. s t o r e . s t a t e . c i t y 之 所 以 每 个 页 面 都 可 以 使 用 store.state.city 之所以每个页面都可以使用 store.state.city使store,是因为他在主js中引入,之后被派发到每一个页面

    在城市选择页面List.vue,将当前城市改为

    this.$store.state.city

    实现点击一个城市名,则将首页的城市显示为该城市名 methods: { handleCityClick (city) { this.changeCitys(city) this.$router.push('/') }, ...mapMutations(['changeCitys']) }, store/mutations.js export default { changeCitys (state, city) { state.city = city try { localStorage.city = city } catch (e) {} } } store/state.js let defaultCity = '上海' try { if (localStorage.city) { defaultCity = localStorage.city } } catch (e) { } export default { city: defaultCity }

    使用localstorage记住用户的选择

    默认首页的城市为上海,当用户切换后,刷新页面会重新变为上海,

    优化

    vuex方法写法优化

    先引入 <script> import { mapState, mapGetters } from 'vuex'

    this.$store.state.city 的写法优化

    computed: { …mapState([‘city’]), } 使用时 {{this.city}}

    this.$store.state.city 的写法优化2

    computed: { …mapState({ currentCity: ‘city’ }) 使用时 {{this.currentCity}}

    2.vuex中的getters

    类似于computed的作用,可以使用数据计算数据

    使用keep-alive优化网页性能

    在App.vue中添加代码keep-alive 意思是;路由的内容加载一次以后,就将内容放到内存之中,下一次再取这个路由的时候直接从内存中取出,不需要重新渲染 发送ajax数据请求的时候带一个参数city

    axios.get(’/api/index.json?city=’ + this.city).then(this.getHomeInfoSucc)

    引入city这个参数的方法是vuex

    import { mapState } from ‘vuex’computed: { …mapState([‘city’]) },

    此时由于包含在keep-alive中并不会重新发送请求,可以使用activated,他在页面每次重新显示的时候被加载

    activated () { if (this.lastCity !== this.city) { this.lastCity = this.city this.getHomeInfo() //这个方法发送ajax请求 } },

    旅游网站详情页面开发

    详情页动态路由及banner布局

    在内容的外部包裹路由跳转

    <router-link tag="li" :to=" '/detail/'+ item.id">

    在index.js中加入该路由信息(带有参数) { path: '/detail/:id', name: 'Detail', component: Detail } 实现文字区域背景图片的渐变色

    background-image: linear-gradient(top, rgba(0, 0, 0, 0),rgba(0, 0, 0, 0.8))

    公用图片画廊组件拆分

    detail/banner.vue

    <template> <div> <div class="banner" @click="handleBannerClick"> <img class="banner-img" :src="bannerImg"> <div class="banner-info" > <div class="banner-title">{{this.sightName}}</div> <div class="banner-number"><span class="iconfont banner-icon"></span>{{this.bannerImgs.length}}</div> </div> </div> <fade-animation> <common-gallary :imgs="bannerImgs" v-show="showGallary" @close="handleGallaryClose"></common-gallary> </fade-animation> </div> </template> <script> import commonGallary from 'common/gallary/Gallary' import FadeAnimation from 'common/fade/Fade' export default { name: 'DetailBanner', props: { sightName: String, bannerImg: String, bannerImgs: Array }, data () { return { showGallary: false } }, methods: { handleBannerClick () { this.showGallary = true }, handleGallaryClose () { this.showGallary = false } }, components: { commonGallary, FadeAnimation } } </script> <style lang="stylus" scoped> .banner position: relative overflow: hidden height: 0 padding-bottom: 51% .banner-img width: 100% .banner-info display: flex position: absolute left: 0 right: 0 bottom: 0 line-height: .6rem color: #fff background-image: linear-gradient(top, rgba(0, 0, 0, 0),rgba(0, 0, 0, 0.8)) .banner-title flex:1 font-size: .32rem padding: 0 .2rem .banner-number margin-top: .14rem padding: 0 .4rem line-height: .32rem height: .32rem border-radius: .2rem background: rgba(0, 0, 0, .8) font-size: .24rem .banner-icon font-size: .24rem </style>

    common/gallary.vue

    <template> <div class="container" @click='handleGallaryClick'> <div class="wrapper"> <swiper :options="swiperOptions"> <swiper-slide v-for="(item,index) in imgs" :key="index"> <img class="gallary-img" :src="item" /> </swiper-slide> <div class="swiper-pagination" slot="pagination"></div> </swiper> </div> </div> </template> <script> export default { name: 'CommonGallery', props: { imgs: { type: Array, default () { return ['https://img1.qunarzz.com/vs_ceph_vs_tts/4d217b8b-a26b-4c50-80ef-c37bcbb8005a.jpg', 'http://img1.qunarzz.com/vs_ceph_vs_tts/b60743c9-5a9c-407a-8e4f-a73344f63ffc.jpg_r_500x333x90_5a5cead1.jpg'] } } }, data () { return { swiperOptions: { pagination: '.swiper-pagination', paginationType: 'fraction', observeParents: true, observer: true } } }, methods: { handleGallaryClick () { this.$emit('close') } } } </script> <style lang="stylus" scoped> .container >>> .swiper-container overflow: inherit .container display: flex z-index: 99 position: fixed flex-direction: column justify-content: center left: 0 right: 0 top: 0 bottom: 0 background: #000 .wrapper height: 0 width: 100% padding-bottom: 100% .gallary-img width: 100% .swiper-pagination color: #fff bottom: -1rem </style>

    实现Header渐隐渐显效果(起初显示一个返回按钮,下滑的时候按钮消失,显示另一个返回的箭头)

    detail/header.vue

    <template> <div> <router-link tag="div" to="/" class="header-abs" v-show='showAbs'> <div class="iconfont header-abs-back"></div> </router-link> <div class="header-fixed" v-show="!showAbs" :style="opacityStyle" > <router-link to="/"> <div class="iconfont header-fixed-back"></div> </router-link> 景点详情 </div> </div> </template> <script> export default { name: 'DetailHeader', data () { return { showAbs: true, opacityStyle: { opacity: 0 } } }, activated () { window.addEventListener('scroll', this.handleScroll) }, deactivated () { window.removeEventListener('scroll', this.handleScroll) }, methods: { handleScroll () { const top = document.documentElement.scrollTop if (top > 60) { let opacity = top / 140 opacity = opacity > 1 ? 1 : opacity this.opacityStyle = { opacity } this.showAbs = false } else { this.showAbs = true } } } } </script> <style lang="stylus" scoped> @import '~styles/varibles.styl' .header-abs position: absolute left: .2rem top: .2rem width: .8rem height: .8rem line-height: .8rem text-align: center border-radius: .4rem background: rgba(0,0,0,.8) .header-abs-back color: #fff font-size: .4rem .header-fixed z-index: 2 position: fixed top: 0 left: 0 right: 0 height: $headerHeight line-height: $headerHeight text-align: center color: #fff background: $bgColor font-size: .32rem .header-fixed-back position: absolute top: 0 left: 0 width: .64rem text-align: center font-size: .4rem color: #fff </style>

    对全局时间的解绑

    在header.vue中的方法

    window.removeEventListener(‘scroll’, this.handleScroll) 该方法是对全局的影响,使用deactivated()钩子进行消除影响

    list.vue的设计编写

    关于递归组件

    组件的name值,常用于递归组件的调用

    <template> <div> <div class='item' v-for="(item,index) of list" :key="index"> <div class="item-title border-bottom"> <span class='item-title-icon'></span> {{item.title}} </div> <div v-if="item.children" class="item-children"> <detail-list :list="item.children"></detail-list> </div> </div> </div> </template> <script> export default { name: 'DetailList', props: { list: Array } } </script> <style lang="stylus" scoped> .item-title-icon position: relative left: .06rem top: .06rem display: inline-block width: .36rem height: .36rem background: url(http://s.qunarzz.com/piao/image/touch/sight/detail.png) 0 -.45rem no-repeat margin-right: .1rem background-size: .4rem 3rem .item-title line-height: .8rem font-size: .32rem padding: 0 .2rem .item-children padding: 0 .2rem </style>

    detail.vue中写了一些模拟数据

    使用Ajax获取动态数据

    将detail/list的数据通过Ajax获取 detail.vue

    <template> <div> <detail-banner :sightName="sightName" :bannerImg="bannerImg" :bannerImgs='gallaryImg' ></detail-banner> <detail-header></detail-header> <div class="content" > <detail-list :list="list"></detail-list> </div> </div> </template> <script> import detailBanner from './components/Banner' import DetailHeader from './components/Header' import DetailList from './components/List' import axios from 'axios' export default { name: 'Detail', components: { detailBanner, DetailHeader, DetailList }, data () { return { sightName: '', bannerImg: '', gallaryImg: [], list: [] } }, methods: { getDetailInfo () { // axios.get('/api/detail.json?id=' + this.$route.params.id) axios.get('/api/detail.json', { params: { id: this.$route.params.id } }).then(this.handleGetDataSucc) }, handleGetDataSucc (res) { res = res.data if (res.ret && res.data) { const data = res.data this.sightName = data.sightName this.bannerImg = data.bannerImg this.gallaryImg = data.gallaryImgs this.list = data.categoryList } } }, mounted () { this.getDetailInfo() } } </script> <style lang="stylus" scoped> .content height: 50rem </style>

    组件中的name值有什么用

    递归组件使用取消对个别页面的缓存 浏览器中vue调试工具看到的也是名字

    页面拖拽在多个页面之中相互影响

    在router/index.js中添加scrollBahavior

    Vue.use(Router) export default new Router({ routes: [ { path: '/', name: 'Home', component: Home }, { path: '/city', name: 'City', component: City }, { path: '/detail/:id', name: 'Detail', component: Detail } ], scrollBehavior (to, from, savedPosition) { return {x: 0, y: 0} } })

    在项目中加入基础动画

    在详情的点击进入图片轮播这里加入基础动画 common/Fade.vue <template> <transition> <slot> </slot> </transition> </template> <script> export default { name: 'Fade' } </script> <style lang="stylus" scoped> .v-enter, .v-leave-to opacity: 0 .v-enter-active, .v-leave-active transition: opacity .5s </style> 引入之后,注册,然后包裹在轮播组件之外

    优化收尾

    Vue项目的接口联调

    Vue项目的真机测试

    修改package.json文件 这样你就可以通过ip访问这个开启的项目了手机与电脑在同一个局域网,然后访问项目开启的端口即可

    Vue项目打包上线

    运行命令 npm run build项目目录中出现dist这个目录,这个目录中的文件就是上线的代码如果打包后在后端服务器中放到某个文件夹中 /config/index.js 重新进行打包,然后将打包结果放到服务器中
    最新回复(0)