亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

Vue框架之goods組件開發詳解

2019-11-19 14:28:58
字體:
來源:轉載
供稿:網友

一、 布局 Flex

Flex 布局,可以簡便、完整、響應式地實現各種頁面布局,Flex 是 Flexible Box 的縮寫,意為"彈性布局",用來為盒狀模型提供最大的靈活性。任何一個容器都可以指定為 Flex 布局。

// 指定為 Flex 布局 display: flex;

// 主要屬性
  flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
  flex屬性是flex-grow, flex-shrink 和 flex-basis的簡寫,默認值為0 1 auto。后兩個屬性可選。
  flex-grow屬性定義項目的放大比例,默認為0,即如果存在剩余空間,也不放大
  flex-shrink屬性定義項目的縮小比例,默認為1,即如果空間不足,該項目將縮小,flex-shrink屬性為0,其他項目都為1,則空間不足時,前者不縮小
  flex-basis屬性定義了在分配多余空間之前,項目占據的主軸空間(main size)。瀏覽器根據這個屬性,計算主軸是否有多余空間。它的默認值為auto,即項目的本來大小,設為跟width或height屬性一樣的值(比如350px),則項目將占據固定空間

flex : 等分 內容縮放 展位空間;flex : 0 0 80px

二、圖標組件

子組件 iconMap

<template lang="html"> <span class="iconMap" :class="iconClassMap[iconType]"></span></template>
export default { props: { // 圖標類型 iconType: Number }, created() { // 數組類名 this.iconClassMap = ['decrease', 'discount', 'special', 'invoice', 'guarantee'] }}

父組件 goods

import iconMap from '../iconMap/iconMap' // 注意路徑寫法// 注冊組件 components: { iconMap }
<ul> <li v-for='(item,index) in goods' class="menu-item"> <span class="text"> // json 數據 根據 type 判斷 是否有圖標 <iconMap v-show="item.type>0" :iconType="item.type"></iconMap> {{item.name}} </span> </li></ul>

三、better-scroll 應用

類似iscroll 實現滾動效果

安裝

npm install better-scroll

引入

import BScroll from 'better-scroll'

說明

(1)原理:父容器wrapper,它具有固定的高度,當它的第一個子元素content 的高度超出了wrapper的高度,我們就可以滾動內容區了,若沒有超出則不能滾動了。

(2)better-scroll 的初始化

better-scroll 的初始化時機很重要,因為它在初始化的時候,會計算父元素和子元素的高度和寬度,來決定是否可以縱向和橫向滾動。因此,我們在初始化它的時候,必須確保父元素和子元素的內容已經正確渲染了。如果子元素或者父元素 DOM 結構發生改變的時候,必須重新調用 scroll.refresh() 方法重新計算來確保滾動效果的正常。所以 better-scroll 不能滾動的原因多半是初始化 better-scroll 的時機不對,或者是當 DOM 結構發送變化的時候并沒有重新計算 better-scroll。

(3)better-scroll 結合 Vue

Vue.js 提供了我們一個獲取 DOM 對象的接口―― vm.$refs。在這里,我們通過了 this.$refs.wrapper 訪問到了這個 DOM 對象,并且我們在 mounted 這個鉤子函數里,this.$nextTick 的回調函數中初始化 better-scroll 。因為這個時候,wrapper 的 DOM 已經渲染了,我們可以正確計算它以及它內層 content 的高度,以確保滾動正常。

這里的 this.$nextTick 是一個異步函數,為了確保 DOM 已經渲染,底層用到了 MutationObserver 或者是 setTimeout(fn, 0)。其實我們在這里把 this.$nextTick 替換成 setTimeout(fn, 20) 也是可以的(20 ms 是一個經驗值,每一個 Tick 約為 17 ms),對用戶體驗而言都是無感知的。

(4)異步數據的處理

在我們的實際工作中,列表的數據往往都是異步獲取的,因此我們初始化 better-scroll 的時機需要在數據獲取后,代碼如下:

<template> <div class="wrapper" ref="wrapper"> <ul class="content"> <li v-for="item in data">{{item}}</li> </ul> </div></template><script> import BScroll from 'better-scroll' export default { data() { return { data: [] } }, created() { requestData().then((res) => { this.data = res.data this.$nextTick(() => { this.scroll = new Bscroll(this.$refs.wrapper, {}) }) }) } }</script>

這里的 requestData 是偽代碼,作用就是發起一個 http 請求從服務端獲取數據,并且這個函數返回的是一個 promise(實際項目中我們可能會用 axios 或者 vue-resource )。我們獲取到數據的后,需要通過異步的方式再去初始化 better-scroll,因為 Vue 是數據驅動的, Vue 數據發生變化(this.data = res.data)到頁面重新渲染是一個異步的過程,我們的初始化時機是要在 DOM 重新渲染后,所以這里用到了 this.$nextTick,當然替換成 setTimeout(fn, 20) 也是可以的。

注意:這里為什么是在 created 這個鉤子函數里請求數據而不是放到 mounted 的鉤子函數里?因為 requestData 是發送一個網絡請求,這是一個異步過程,當拿到響應數據的時候,Vue 的 DOM 早就已經渲染好了,但是數據改變 ―> DOM 重新渲染仍然是一個異步過程,所以即使在我們拿到數據后,也要異步初始化 better-scroll。

使用

初始化需要滾動的dom結構

借助ref屬性用來綁定某個dom元素,或者來說來綁定某個組件,然后在函數內用this.$refs.menuwrapper獲取到dom。

說明:如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素; 如果用在子組件上,引用就指向組件實例:

<div class="menu-wrapper" ref='menuWrapper'> </div><div class="foods-wrapper" ref="foodsWrapper"></div>

在ajax內執行_initScroll() 函數

在此之前我們要做一些準備和 注意事項

(1) dom結構完全加載完再調用_initScroll()方法才會生效

(2) 因為要監聽內容區域的高度,所以初始化應在created過程中去監聽dom結構是否完全加載,這里是在$nextTick對象中進行觸發檢測

ES6語法格式: this.$nextTick(() => {})

created (){ // 在實例創建完成后被立即調用 $el 屬性目前不可見。 axios.get('static/data.json').then((result) => { this.goods=result.data.goods //dom結構加載結束 this.$nextTick(() => { this._initScroll(); // 初始化scroll }) })}

(3) 在methods方法里面定義一個_initScroll的函數,主要用來對左右兩側dom結構進行初始化

methods:{ // 用來對左右兩側dom結構進行初始化 _initScroll (){ // 實例化 better-scroll 插件,傳入要滾動的DOM 對象  this.meunScroll=new BScroll(this.$refs.menuWrapper,{ click:true  }); this.foodScroll=new BScroll(this.$refs.foodsWrapper,{ click:true });  } }

說明:vue中更改數據,DOM會跟著做映射,但vue更新DOM是異步的,用 $nextTick ()來確保Dom變化后能調用到_initScroll()方法。調用_initScroll()方法能計算內層ul的高度,當內層ul的高度大于外層wrapper的高度時,可以實現滾動。

此時倆側可以分別滾動了!

(4) 實現左右聯動

原理:我們計算出右側實時變化的y值,落到哪一個區間,我們就顯示那一個區間。首先我們要計算整體區間的一個高度,然后分別計算第一個區間的高度,第二個區間的高度,以此類推。然后將區間數存入一個定義好的數組。當我們在滾動的時候實時拿到y軸的高度,然后對比在哪一個區間,這樣我們就會得到一個區間的索引值去對應左側的菜品類別,最后我們用一個vue的class去綁定高亮文本。

1.定義一個方法在 _initScroll 下面,作為計算高度的方法叫做_calculateHeight () ,再定義一個listHeight:[]數組,存放獲取到的每一塊foods類的高度。然后通過給每個li 定義類名來供js 選擇 從而計算出高度存放到listHeight數組里。

// 通過 方法 計算foods內部每一個塊的高度,組成一個數組listHeight。 // 每個li 定義一個類food-list-hook 通過獲取該類 來計算 每一塊的高度 存到數組listHeight里 _calculateHeight (){ // 獲取 li 通過food-list-hook let foodList=this.$refs.foodsWrapper.querySelectorAll(".food-list-hook"); let height=0;// 初始化高度 this.listHeight.push(height) // 把第一個高度存入數組 //通過循環foodList下的dom結構,將每一個li的高度依次送入數組 for(let i = 0 ,l = foodList.length ; i < l ; i++){ let item=foodList[i]; //每一個item都是剛才獲取的food的每一個dom height += item.clientHeight; //獲取每一個foods內部塊的高度 this.listHeight.push(height) // 將獲取的值存放到數組里 }  }

2.我們獲取到區間高度數組后,我們要實時獲取到右側的y值,和左側的索引值做一個對比,定義一個scrollY變量用來存放實時獲取的y值。bs插件為我們提供了一個實時獲取y值的方法,我們在初始化this.foodScroll的時候加一個?屬性probeType: 3,其作用就是實時獲取y值,相當于探針的作用。

goods: [],// goods json 數組listHeight: [],// 存放 foods 內部的每一塊的高度scrollY:0
this.foodScroll=new BScroll(this.$refs.foodsWrapper,{ click:true, //探針作用,實時監測滾動位置 probeType: 3 });

3.我們再添加一個方法this.foodScroll.on('scroll',(pos) => {}),作用是實時滾動的時候把獲取到的位置給暴露出來。代碼如下。

//結合BScroll的接口使用,監聽scroll事件(實時派發的),并獲取鼠標坐標,當滾動時能實時暴露出scroll this.foodScroll.on("scroll",(pos) =>{ // 回調函數 //scrollY接收變量  this.scrollY=Math.abs(Math.round(pos.y)) //滾動坐標會出現負的,并且是小數,所以需要處理一下,實時取得scrollY // console.log(pos.y) })

4.定義一個計算屬性computed,獲取到food滾動區域對應的menu區域的子塊的索引i值,從而定位到左側邊欄的位置。

computed:{ currentIndex (){ //計算到達哪個區域的區間的時候的對應的索引值 // 利用 listHeight 存放 每一塊 對應的高度 for (let i=0,l=this.listHeight.length; i<l ; i++){ let menuHeight_fir = this.listHeight[i] // 當前menu 子塊區域的 高度 let menuHeight_sec = this.listHeight[i + 1] // 下一個menu 子塊區域的 高度 // 當滑到底部時,menuHeight_sec 為 underfined, // 需要確定滑到倆個高度區間  if( !menuHeight_sec || (this.scrollY > menuHeight_fir && this.scrollY < menuHeight_sec) ){ return i; } } },  }

獲取到i后,,然后通過設置一個class來做樣式切換變化 :class="{'current':currentIndex === index}" ,當currentIndex和menu-item對應的index相等時,設置current的樣式。這樣就可以實現左右聯動了。

<li v-for='(item,index) in goods' class="menu-item" :class="index === currentIndex?'menu-item-selected':'menu-item'">...

在樣式里提前設好 選中和正常的樣式

5.最后實現左側點擊的功能。在左側的li下綁定一個selectMenu的點擊事件,并傳入索引值,這樣我們就可以知道點擊的是哪一個li

<li v-for='(item,index) in goods' class="menu-item" @click="selectMenu(index,$event)" :class="index === currentIndex?'menu-item-selected':'menu-item'">...
selectMenu (index, event){ // 點擊左側 ,右側響應 this.foodScroll.scrollTo(0, -this.listHeight[index], 300) }
scrollTo(x, y, time, easing)//滾動到某個位置,x,y 代表坐標,time 表示動畫時間,easing 表示緩動函數scroll.scrollTo(0, 500)

參考: vue使用 better-scroll的參數和方法

6.關于在selectMenu中點擊事件

在selectMenu中點擊,在pc界面會出現兩次事件,在移動端就只出現一次事件的問題

原因 : better-scroll 會監聽事件(例如touchmove,click之類),并且阻止默認事件(prevent stop),并且他只會監聽移動端的,pc端的沒有監聽

在pc頁面上 better-scroll 也派發了一次click事件,原生也派發了一次click事件

// better-scroll 的事件,有_constructed: trueMouseEvent {isTrusted: false, _constructed: true, screenX: 0, screenY: 0, clientX: 0…}//pc的事件MouseEvent {isTrusted: true, screenX: -1867, screenY: 520, clientX: 53, clientY: 400…}

解決 : 針對better-scroll 的事件,有_constructed: true,所以做處理,return掉非better-scroll 的事件

selectMenu(index, event){ if (!event._constructed) { //去掉自帶的click事件點擊,即pc端直接返回 return; } let foodList=this.$refs.foodsWrapper.querySelectorAll(".food-list-hook"); // 獲得監聽元素 let el = foodList[index]; // 獲得 當前 監聽元素的高度  this.foodScroll.scrollToElement(el, 300); //類似jump to的功能,通過這個方法,跳轉到指定的dom }

goods 組件到此差不多了!

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久久久久久亚洲精品| 91wwwcom在线观看| 国产精品久久久久久久久久| 欧美日韩xxxxx| 91精品国产高清久久久久久91| 欧美精品一区二区三区国产精品| 国产精品欧美日韩| 久久久久女教师免费一区| 国产成人精品999| 日韩高清有码在线| 国产精品久久久久久久久免费看| 69av视频在线播放| 精品久久久久久久中文字幕| 日韩av片免费在线观看| 欧美国产精品人人做人人爱| 国产精品久久网| 成人av番号网| 日本伊人精品一区二区三区介绍| 精品无人区太爽高潮在线播放| 欧美亚洲一级片| 久久久免费在线观看| 久久99视频免费| 日本精品免费一区二区三区| 久久久久久久久久婷婷| 欧美日韩中国免费专区在线看| 日韩高清电影免费观看完整| 中文字幕av一区二区三区谷原希美| 成人在线国产精品| 欧美性猛交xxxx富婆弯腰| 中文国产亚洲喷潮| 日韩一区二区三区国产| 国产午夜精品理论片a级探花| 深夜福利国产精品| 亚洲激情久久久| 欧美黄色免费网站| 欧美巨大黑人极品精男| 中文字幕免费国产精品| 91久久国产婷婷一区二区| 亚洲综合中文字幕在线观看| 亚洲一区二区免费| 91久久精品美女高潮| 91av福利视频| 成人激情综合网| 91成人在线视频| 日韩电影在线观看中文字幕| 久久影视电视剧免费网站清宫辞电视| 欧美日韩一区二区三区| 国产美女精品视频免费观看| 亚洲国产精品嫩草影院久久| 国产午夜精品一区理论片飘花| 亚洲国内精品视频| 日本久久久久久久久| 精品国偷自产在线视频| 国产精品福利小视频| 亚洲国产成人精品久久久国产成人一区| 久久精品色欧美aⅴ一区二区| 久久精品久久久久久国产 免费| 欧美精品激情在线观看| 日韩精品在线免费播放| 欧美风情在线观看| 国内精品模特av私拍在线观看| 欧美人与物videos| 精品日韩美女的视频高清| 中文字幕欧美日韩va免费视频| 国产欧美一区二区三区久久人妖| 国产精品自产拍在线观看中文| 亚洲xxx自由成熟| 欧美成人一区二区三区电影| 日韩精品免费在线播放| 秋霞午夜一区二区| 欧美精品在线观看91| 欧美高清一级大片| 久久九九全国免费精品观看| 国产一区二区三区在线免费观看| 欧美国产日韩一区二区三区| 91亚洲精品久久久| 久久香蕉国产线看观看网| 欧美国产日韩在线| 国产精品吹潮在线观看| 欧美精品亚州精品| 美女精品久久久| 狠狠色狠狠色综合日日五| 亚洲女同性videos| 国产一区二区三区直播精品电影| 97免费视频在线播放| 69av视频在线播放| 91av福利视频| 日韩av一区二区在线观看| 国产精品美女久久久久av超清| 久久精品视频在线播放| 久久久www成人免费精品| 精品成人国产在线观看男人呻吟| 国产精品福利片| yellow中文字幕久久| 国产成人精品一区二区三区| 国产女人精品视频| 精品视频久久久| 成人免费观看网址| 在线播放国产一区二区三区| 成人a在线视频| 91探花福利精品国产自产在线| 国产精品电影观看| 久久久这里只有精品视频| 色www亚洲国产张柏芝| 一区二区在线视频播放| 性欧美在线看片a免费观看| 一本一本久久a久久精品综合小说| 国产精品高清在线| 国产美女直播视频一区| 欧美色视频日本版| 狠狠色狠色综合曰曰| 亚洲最大av网站| 亚洲最大的网站| 国产一区二区色| 亚洲欧美在线x视频| 欧美国产日韩一区二区三区| 成人网在线视频| 久久99精品视频一区97| 国产精品激情自拍| 亚洲男人第一av网站| 国产v综合ⅴ日韩v欧美大片| www日韩中文字幕在线看| 尤物yw午夜国产精品视频| 国产精品27p| 91亚洲va在线va天堂va国| 亚洲欧美国产日韩中文字幕| 成人信息集中地欧美| 国产成人精品在线观看| 精品国产依人香蕉在线精品| 91情侣偷在线精品国产| 国产精品久久色| 国产欧美精品一区二区三区-老狼| 亚洲国产一区二区三区四区| 欧美日本精品在线| 国产精品第一第二| 欧美肥婆姓交大片| 91精品国产综合久久男男| 国产视频在线观看一区二区| 国产精品欧美一区二区三区奶水| 色婷婷成人综合| 欧美日韩爱爱视频| 亚洲精品国产免费| 亚洲天堂精品在线| 亚洲最大av在线| 韩剧1988在线观看免费完整版| 91视频免费在线| 色综合伊人色综合网| 激情av一区二区| 久久天天躁狠狠躁夜夜躁2014| 久久综合九色九九| 久久久精品视频在线观看| 日韩欧美国产中文字幕| 国产剧情久久久久久| 国产欧美最新羞羞视频在线观看| 亚洲品质视频自拍网| 这里只有视频精品| 91黄色8090| 在线观看国产欧美| 欧美精品久久久久久久| 69**夜色精品国产69乱| 国产精品视频永久免费播放| 日韩精品中文在线观看| 久久影院中文字幕| 久久中文字幕在线视频|