Skip to content

Vant Weapp 组件库使用

安装

可参考 https://youzan.github.io/vant-weapp/#/quickstart#bu-zou-yi-tong-guo-npm-an-zhuang

  • 打开编译器在资源管理器空白处右键点击 “ 在外部中断窗口中打开 ”
bash
npm i @vant/weapp

起步使用

发送数据请求

推荐使用 @escook/request-miniprogram 发送数据请求

使用 npm 包

构建 npm 包

  • 在小程序中每次安装一个新的包时必须重新构建依次 npm 包

uniapp 开发

  • 开发时如果使用了 less、sass 等预编译语言建议先在 HBuilder 中安装对应插件

新建项目

项目目录

将项目运行到小程序开发工具中

填写 appid

配置微信开发工具路径

  • 依次点击 HBuilder 顶部的 “工具” => "设置"

开启微信开发工具服务端口

运行

取消 sitemap 警告

在 manifest.json 文件中添加如下代码即可

创建 tabBar 导航

  • 先在 page 文件夹下创建需要展示的 tabBar 页面文件

  • 然后打开 pages.json 在 pages 节点下引入对应页面,在创建 tabBar 节点对页面进行配置

json
"pages": [{
		"path": "pages/home/home",
		"style": {}

	}, {
		"path": "pages/cate/cate",
		"style": {}

	}, {
		"path": "pages/cart/cart",
		"style": {}

	}, {
		"path": "pages/my/my",
		"style": {}

	}],
"tabBar": {
		"selectedColor": "#C00000", // 表示底部 tabBar 显示文字颜色
		"list": [{
				"pagePath": "pages/home/home",
				"text": "首页",
				"iconPath": "static/tab_icons/home.png", // 表示该页面未被选中的图标
				"selectedIconPath": "static/tab_icons/home-active.png"
			},
			{
				"pagePath": "pages/cate/cate",
				"text": "分类",
				"iconPath": "static/tab_icons/cate.png",
				"selectedIconPath": "static/tab_icons/cate-active.png"
			},
			{
				"pagePath": "pages/cart/cart",
				"text": "购物车",
				"iconPath": "static/tab_icons/cart.png",
				"selectedIconPath": "static/tab_icons/cart-active.png"
			},
			{
				"pagePath": "pages/my/my",
				"text": "我的",
				"iconPath": "static/tab_icons/my.png",
				"selectedIconPath": "static/tab_icons/my-active.png"
			}
		]
	}

tabBar 页面跳转

调用 switchTab 即可跳转到指定 tabBar 页面

js
navClickHandler(item) {
    if (item.name === '分类') {
        // switchTab 函数用于跳转底部 tabbar 页面
        uni.switchTab({
            url: '/pages/cate/cate'
            // 跳转完成调用
            complete: () => {
            this.updataRedirectInfo(null)
        	}
        })
    }
},

可使用高度

js
export default {
  data() {
    return {
      wh: 0
    }
  },
  onLoad() {
    // getSystemInfoSync 可以获取当前设备的详细信息
    const sysInfo = uni.getSystemInfoSync()
    // windowHeight 可以获取当前设备可使用的高度(整个屏幕除去头部标题区和底部 tabBar 区域就是剩余可使用高度)
    this.wh = sysInfo.windowHeight
  }
}

重置页面滚动位置

vue
<!-- scroll-top 可以动态设置滚动的位置 -->
<scroll-view
  scroll-y="true"
  :style="{ height: wh + 'px' }"
  :scroll-top="scrollTop"
>
    <view class="cate-lv2" v-for="(item2,i2) in cateLevel2" :key="i2">
        <view class="cate-lv2-title">/ {{item2.cat_name}} /</view>
        <view class="cate-lv3-list">
            <view class="cate-lv3-item" v-for="(item3,i3) in item2.children" :key="i3">
                <image :src="item3.cat_icon"></image>
                <text>{{item3.cat_name}}</text>
            </view>
        </view>
    </view>
</scroll-view>
<script>
export default {
    data() {
        return {
            scrollTop:0
        }
    },
    methods: {
		// 切换分类时改变选中项
		activeChange(i){
            // 重置滚动时不能赋相同的值
			this.scrollTop = this.scrollTop === 0 ? 1 : 0
		},
    }
</script>

跳转指定分包地址页面

js
gotoGoodsList(item){
    // 跳转指定分包地址页面
    uni.navigateTo({
        url:'/subpkg/goods_list/goods_list?cid=' + item.cat_id
    })
},

自定义组件

  • 在 components 目录中创建自定义组件,在页面中使用

uni-app 组件

vue
<!-- 使用 uni-app 提供的图标组件 -->
<uni-icons type="search" size="30"></uni-icons>
<text class="placeholder">搜索</text>

计数组件

vue
<!-- min 表示最小值 value 表示当前显示的数量 change 表示当数值发生变化时 -->
<uni-number-box
  :min="1"
  :value="goods.goods_count"
  @change="numChangeHandler"
></uni-number-box>

<script>
methods: {

    numChangeHandler(val) {
        console.log(val); // val 可以拿到改变后的值
    }
}
</script>
  • 解决计数组件输入非数字数据时出现 NaN
  • 打开组件源代码 找到 _onBlur 函数并作出如下改动
js
_onBlur(event) {
    this.$emit('blur', event)
    // let value = event.detail.value;
    let value = parseInt(event.detail.value);
    if (!value) {
        this.inputValue = 1;
        return;
    }
},

滑动删除组件

vue
<!-- 使用滑动删除组件之前的代码 -->
<!-- <block v-for="(goods, i) in cart" :key="i">
<my-goods :goods="goods" :showRadio="true" @radio-change="radioChangeHandler" :showNum="true" @num-change="numberChangeHandler"></my-goods>
</block> -->

<!-- 滑动删除组件 -->
<!-- 使用滑动删除组件之后的代码 -->
<uni-swipe-action>
    <block v-for="(goods, i) in cart" :key="i">
        <uni-swipe-action-item :right-options="options">
            <my-goods :goods="goods" :showRadio="true" @radio-change="radioChangeHandler" :showNum="true" @num-change="numberChangeHandler"></my-goods>
        </uni-swipe-action-item>
    </block>
</uni-swipe-action>
<script>
data() {
    return {
        // 滑动删除配置项
        options: [
            {
                text: '删除', // 指定滑动组件显示的文本内容
                style: {
                    backgroundColor: '#C00000' // 指定滑动组件的背景颜色
                }
            }
        ]
    }
},
</script>

为自定义组件添加点击事件

  • 这样页面在使用组件时就可以触发点击事件

定义过滤器

  • 在 data 平级定义过滤器
js
data() {
    return {
        // 定义默认图片
        defaultPic: 'https://img3.doubanio.com/f/movie/8dd0c794499fe925ae2ae89ee30cd225750457b4/pics/movie/celebrity-default-medium.png'
    }
},
    // 定义过滤器实现数字精确到百分位
    filters:{
        tofixed(num) {
            return Number(num).toFixed(2)
        }
    }
  • 在页面中使用
vue
<!-- 调用定义好的过滤器 -->
<view class="goods-price">¥{{ goods.goods_price | tofixed}}</view>

持久化存储

onload

  • 在 onLoad 函数形参里可以拿到其他页面跳转过来所携带的参数

实现上拉加载功能

  • 先在 pages.json 中配置那个需要该功能的页面添加上拉触底距离
json
"path": "goods_list/goods_list",
"style":{
    "onReachBottomDistance":150
}
  • 在 methods 节点下添加上拉加载事件,并添加节流阀控制请求频率
js
data() {
    return {
        // 请求参数对象
        queryObj: {
            query: '',
            cid: '',
            pegenum: 1,
            pagesize: 10
        },
        goodsList: [],
        total: 0,
        // 定义上拉加载节流阀
        isloading:false
    }
},
    onLoad(options) {
        this.queryObj.query = options.query || ''
        this.queryObj.cid = options.cid || ''
        this.getGoodsList() // 获取商品列表数据
    },
        methods: {
            // 获取商品列表数据
            async getGoodsList() {
                this.isloading = true // 开启节流阀
                const { data: res } = await uni.$http.get('/api/public/v1/goods/search', this.queryObj)
                this.isloading = false // 关闭节流阀
                if (res.meta.status !== 200) return uni.$showMsg()
                this.goodsList = [...this.goodsList, ...res.message.goods]
                this.total = res.message.total
            },
                // 上拉加载
                onReachBottom() {
                    // 判断数据是否加载完毕
                    if(this.queryObj.pegenum * this.queryObj.pagesize >= this.total) return
                    if(this.isloading) return
                    this.queryObj.pegenum++
                    this.getGoodsList()
                }
        }

下拉刷新

  • 先在 pages.json 中配置
json
"style":{
    "onReachBottomDistance":150, // 上拉加载触发时距离底部距离
    "enablePullDownRefresh":true, // 开启上拉刷新
    "backgroundColor":"#F8F8F8" // 上拉刷新时的背景颜色
}
  • 在 methods 节点下添加下拉刷新事件
js
// 获取商品列表数据
async getGoodsList(cb) {
    const { data: res } = await uni.$http.get('/api/public/v1/goods/search', this.queryObj)
	//////////////////
    cb && cb() // 调用关闭下拉刷新的函数
	//////////////////
    if (res.meta.status !== 200) return uni.$showMsg()
    this.goodsList = [...this.goodsList, ...res.message.goods]
    this.total = res.message.total
},
    // 下拉刷新
    onPullDownRefresh(){
        // 重置关键数据
        this.queryObj.pagenum = 1
        this.total = 0
        this.isloading = false
        this.goodsList = []
        // 重新获取数据
        // uni.stopPullDownRefresh() 关闭下拉刷新
        this.getGoodsList(() => uni.stopPullDownRefresh())
    }

图片预览

  • 为需要预览的地方添加点击事件
vue
<swiper-item v-for="(item, i) in goods_info.pics" :key="i" @click="preview(i)">
    <image :src="item.pics_big"></image>
</swiper-item>
  • 在 methods 节点下定义这个点击事件
js
// 图片预览功能
preview(i) {
    // uni.previewImage 图片预览功能
    uni.previewImage({
        current: i, // 当前预览哪一张图片
        urls: this.goods_info.pics.map(item => item.pics_big) // 需要预览的图片的 url 地址,是一个数组
    })
}

渲染 html 代码片段

  • rich-text 组件能快速帮我们把一段富文本 html 字符串渲染为 html 代码
vue
<!-- rich-text 组件渲染后端返回的一段富文本 html 代码  nodes 节点传递一个 html 代码片段-->
<rich-text :nodes="goods_info.goods_introduce"></rich-text>
  • webp 格式的图片在 IOS 端支持度不好,可能无法正常显示图片

底部购物车组件

vue
<!-- fill 表示按钮是否是圆角的  options 表示配置对象 buttonGroup 表示右侧按钮配置 -->
<!-- click 表示左侧点击事件  buttonClick 表示右侧按钮点击事件-->
<uni-goods-nav
  :fill="true"
  :options="options"
  :buttonGroup="buttonGroup"
  @click="onclick"
  @buttonClick="buttonClick"
></uni-goods-nav>
<script>
data() {
    return {
        options: [
            {
                icon: 'shop',
                text: '店铺',
                infoBackgroundColor: '#007aff',
                infoColor: 'red'
            },
            {
                icon: 'cart',
                text: '购物车',
                info: 2
            }
        ],
        buttonGroup: [
            {
                text: '加入购物车',
                backgroundColor: '#ff0000',
                color: '#fff'
            },
            {
                text: '立即购买',
                backgroundColor: '#ffa200',
                color: '#fff'
            }
        ]
    }
},
</script>

点击左侧按钮事件

修改 tabBar 右上角图标

js
// 当该页面刚显示时触发
onShow() {
    this.setBadge()
},
    methods: {
        // 更改购物车页面商品数量图标
        setBadge() {
            // uni.setTabBarBadge 可以设置 tabBar 的信息
            uni.setTabBarBadge({
                index: 2, // 修改的索引 (要修改哪个 tabBar )
                text: this.total + '' // 更改 tabBar 右上角的徽标 text 必须是字符串
            })
        }
    }

mixins 代码混入

  • 借助 mixins 能把一些重复的代码抽离出去,其他页面按需引入即可

  • 先创建文件和编写代码

  • 在其他页面使用
js
// 引入 mixins 代码
import badgeMix from '@/mixins/tabbar-badge.js'
export default {
  // 挂载 mixins
  mixins: [badgeMix]
}

选择地址 API

js
// 当点击选择收货地址按钮时
async chooseAddress() {
    // chooseAddress uniapp 提供的选择地址API 返回值是一个 promise err 代表调用api时的错误对象,succ代表成功调用的对象
    const [err, succ] = await uni.chooseAddress().catch(err => err)
    // 判断是否在调用 API 期间发生错误
    if(err === null && succ.errMsg === 'chooseAddress:ok') {
        console.log(succ)
    }
}
  • 解决用户第一次未能给小程序授权访问地址信息,下一次不再提示,就不能再选择地址问题
js
// 当点击选择收货地址按钮时
async chooseAddress() {
    // chooseAddress uniapp 提供的选择地址API 返回值是一个 promise err 代表调用api时的错误对象,succ代表成功调用的对象
    const [err, succ] = await uni.chooseAddress().catch(err => err)
    // 判断是否在调用 API 期间发生错误
    if (err === null && succ.errMsg === 'chooseAddress:ok') {
        this.updateAddress(succ)
    }
    // 解决方案///////////////////////////////////////////////////////
    if (err && (err.errMsg === 'chooseAddress:fail auth deny' || err.errMsg === 'chooseAddress:fail authorize no response')) {
        // 当用户再次点击填写地址时调用 reAuth 进行重新授权
        this.reAuth()
    }
    /////////////////////////////////////////////////
}
async reAuth() {
    // showModal 可以打开一个提示框
    const [err2, confirmResult] = await uni.showModal({
        content: '检测到您没有打开地址权限,是否去设置打开?',
        confirmText: '确认',
        cancelText: '取消'
    })
    // 如果发生错误时
    if (err2) return
    if (confirmResult.cancel) return uni.$showMsg('您取消的地址授权')
    // 当点击确定时
    // openSetting uniapp 提供的API 可以打开设置面板
    if (confirmResult.confirm)
        return uni.openSetting({
            success: settingResult => {
                // 用户未开启授权地址按钮
                if (!settingResult.authSetting['scope.address']) return uni.$showMsg('您取消的地址授权')
                uni.$showMsg('授权成功!')
            }
        })
}
  • 开启提示框
js
// showModal 可以打开一个提示框
const [err2, confirmResult] = await uni.showModal({
  content: '检测到您没有打开地址权限,是否去设置打开?',
  confirmText: '确认',
  cancelText: '取消'
})
  • 调用 openSetting 方法打开设置
js
uni.openSetting({
  success: settingResult => {
    // 用户未开启授权地址按钮
    if (!settingResult.authSetting['scope.address'])
      return uni.$showMsg('您取消的地址授权')
    uni.$showMsg('授权成功!')
  }
})

一键登录

vue
<!-- open-type 表示希望获取用户的基本信息 open-type="getUserInfo" 是固定写法 -->
<!-- 能在 @getuserinfo 事件的形参中获取到用户的基本信息 @getuserinfo="" 是固定写法 -->
<button
  type="primary"
  class="btn-login"
  open-type="getUserInfo"
  @getuserinfo="getUserInfo"
>一键登录</button>
<script>
// 用户授权后,获取用户的基本信息
	getUserInfo(e) {
		console.log(e) // 获取用户基本信息
	}
}
</script>

获取登录信息

js
getUserInfo(e) {
    // 判断用户是否授权
    if (e.detail.errMsg === 'getUserInfo:fail auth deny') return uni.$showMsg('您取消的登录授权!')
    this.updataUserInfo(e.detail.userInfo)
    this.getToken(e.detail)
},
    // 获取 token
    async getToken(info) {
        // uni.login() 获取登录信息
        const [err,res] = await uni.login().catch(err=>err)
        // 判断调用 uni.login() 时是否出错
        if(err || res.errMsg !== 'login:ok') return uni.$showMsg('登录失败!')
        console.log(res);
    }

订单支付

具体步骤

支付接口所需参数

发布

打开微信公众平台小程序后台,点击提交审核即可

打包为 app

依次选择 ‘’使用公共测试证书“ => ”打正式包“ 然后点击打包即可

耐心等待打包完成控制台会返回 app 下载链接