这篇文章主要介绍了Vue框架之goodvs组件开发详解,现在分享给大家,也给大家做个参考。

一、 布局 Flex

Flex 布局,可以简便、完整、响应式地实现各种页面布局,Flex 是 Flexible Box 的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性。任何一个容器都可以指定为 Flex 布局。

// 指定为 Flex 布局 display: flex;flex : 等分 内容缩放 展位空间; flex : 0 0 80px

// 主要属性
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),则项目将占据固定空间

二、图标组件

子组件 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> <p class="wrapper" ref="wrapper"> <ul class="content"> <li v-for="item in data">{{item}}</li> </ul> </p> </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 元素; 如果用在子组件上,引用就指向组件实例:

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

在ajax内执行_initScroll() 函数

在此之前我们要做一些准备和 注意事项

(1) dom结构完全加载完再调用_initScroll()方法才会生效

(2) 因为要监听内容区域的高度,所以初始化应在created过程中去监听dom结构是否完全加载,这里是在$nextTick对象中进行触发检测