700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 原生微信小程序基础-分包加载自定义组件项目全流程

原生微信小程序基础-分包加载自定义组件项目全流程

时间:2021-11-21 23:22:31

相关推荐

原生微信小程序基础-分包加载自定义组件项目全流程

小程序基础-分包加载&&自定义组件

小程序分包加载

小程序分包加载-为什么要分包加载

微信平台对小程序单个包的代码体积限制为 2M,超过 2M 的情况下可以采用分包来解决即使小程序代码体积没有超过 2M 时也可以拆分成多个包来实现按需加载配置文件能忽略的只有静态资源,代码无法被忽略

配置忽略文件

project.config.json

{"description": "项目配置文件","packOptions": {"ignore": [{"value": "static/uploads","type": "folder"}],"include": []},

type: 表示要忽略的资源类型

value: 表示具体要忽略的

小程序分包加载-使用分包配置

分类:

主包:

每个小程序必定含有一个主包

默认启动页面、TabBar 页面,以及公共资源/JS 脚本必须放在主包;

2.分包 https://developers./miniprogram/dev/framework/subpackages.html

通过subPackages来配置

所有包的大小之和不超过20M

app.json

{// 省略其他的..."subPackages": [{"root": "subpkg_user", // 分包代码的目录,其实就是一个独立的文件夹"pages": ["pages/profile/profile"]},{"root": "subpkg_order", // 文件夹"pages": ["pages/order_list/index", "pages/order_list/index"]}]}

注意:写完分包之后,如果对应的文件夹和页面不存在,它会自动创建文件夹和页面

小程序分包—预加载

https://developers./miniprogram/dev/framework/subpackages/preload.html

在打开小程序启动的时候只下载主包代码,分包并不会下载,因此能够提升小程序启动时的打开速度,但是分包的代码只有在访问到分包的页面时才去下载,这样用户就需要有一定时间的等待(一般不太影响),通过分包预加载技术可以实现提前去下载分包的代码,这样分包页面的访问速度也会得到提升。

小程序通过 preloadRule 配置需要预加载的分包。

app.json

{......"preloadRule": {"页面地址,进入这个页面就需要预加载分包": {// pages/index/index "network": "网络环境", // "wifi""packages": ["要预加载的包名"] //["goods_pkg"]}}, ......}//当用户访问到 pages/index/index 时,在 wifi 网络前提下预先下载 goods_pkg 分包的代码。

指定某个页面路径做为 key,含义是当访问这个页面时会去预加载一个分包network 预加载分包的网络条件,可选值为 all、wifi,默认为 wifipackages 指定要预下载的分包名或根路径

配置完成之后,访问指定页面时,就会在控制台输出提示。

自定义组件—基本使用

创建组件

通常将项目中的组件都放在一个独立的目录下,并且一般就给这个文件夹取名为:components 。这个目录需要我们手动进行创建。

新建一个目录:components

在components上点击鼠标右键,选择「新建Component」

填入组件的名字。它会自动创建4个同名的文件。(这一点和创建页面是一样的)

组件和页面的结构区别:

组件的配置文件(.json文件)中,有一个配置项:component: true组件的 .js 文件中调用Component函数,页面的.js文件中调用Page函数

注册组件

页面注册是在使用组件的(xxxx.json)中通过 usingComponents 进行注册,只能在当前页面中组件

全局注册是在 app.json 文件中通过 usingComponents 对自定义组件进行注册,可以在任意页面中使用

"usingComponents": {"my-test": "/components/MyTest/index"}

使用组件

在wxml中,直接通过标签的方式使用即可。

自定义组件—组件样式

组件中的样式不要使用标签选择器组件中,样式默认是隔离的: 自定义组件的样式只受到自定义组件 wxss 的影响通过对组件的配置,可以取消这个隔离的状态

样式隔离注意点

app.wxss中的全局样式对组件无效

只有class选择器具有样式隔离效果,id选择器、属性选择器、标签选择器不受样式隔离的影响

建议:在组件和引用组件的页面中建议使用class选择器,不要使用id、属性、标签选择器

修改组件样式的隔离选项

默认情况下,自定义组件的样式隔离特性能够防止组件内外样式互相干扰的问题。但有时,我们希望外界能够控制组件内部的样式,此时,可以通过在组件的.js文件中设置: options → addGlobalClass 为true

XX.js

Component({options: {addGlobalClass: true}})

在页面中设置的同类名的选择器就能作用于子组件内部的元素。但是,组件内的class选择器,不能影响页面的元素。

自定义组件—组件样式-外部样式类

组件希望接受外部传入的样式类。此时可以在 Component 中用 externalClasses 定义若干个外部样式类。

在开发组件时,主动暴露给组件使用者,修改组件内部样式

组件 custom-component.js

/* 组件 custom-component.js */Component({externalClasses: ['my-class']});

组件 custom-component.wxml

<!-- 组件的wxml --><!-- 这里的my-class相当于一个占位符 --><view class="my-class">components/MyTest/index.wxml</view>

页面的 WXML

<!-- 页面的 WXML --><custom-component my-class="red-text" /><custom-component my-class="large-text" />

页面的wxss

.red-text{color: red; }.large-text {font-size: 50px; }

外部样式类相当于用一个类名去当占位符,以便于在后期使用时替换成真实的类名,方便添加额外的样式。

参考:https://vant-contrib.gitee.io/vant-weapp/#/button#wai-bu-yang-shi-lei

自定义组件—数据方法

组件的典型结构

// borderImage.jsComponent({/*** 组件的属性列表*/properties: {},/*** 组件的初始数据*/data: {},/*** 组件的方法列表*/methods: {}})

定义数据

在小程序中,用于组件模板渲染的私有数据,需要定义到data

methods方法

在小程序的组件中,事件处理函数和自定义方法需要定义到methods

自定义组件—组件插槽

单个插槽

在小程序中,默认情况下每个自定义组件中只允许使用一个插槽进行占位。

<!--components/MyTest2/index.wxml--><view><text>components/MyTest2/index.wxml</text><!-- 对于不确定的内容,可以使用slot进行占位,具体内容交给使用者确定 --><slot></slot></view>

使用组件

<my-test2><!-- 这里的内容将被放到组件中<slot>的位置 --><view>这里是slot里的内容</view></my-test2>

多插槽(具名插槽)

组价.js

Component({options: {multipleSlots: true // 在组件定义时的选项中启用多 slot 支持},// ... 省略其他})

此时,可以在这个组件的 wxml 中使用多个 slot ,以不同的 name 来区分。

定义插槽

<view><text>components/MyTest2/index.wxml</text><!-- 对于不确定的内容,可以使用slot进行占位,具体内容交给使用者确定 --><!-- <slot></slot> --><slot name="before"></slot><view>---------这里是分割线--------</view><slot name="after"></slot></view>

使用组件

<my-test2><!-- 这里的内容将被放到组件中<slot>的位置 --><!-- <view>这里是slot里的内容</view> --><view slot="before">这里是before slot里的内容</view><view slot="after">这里是after slot里的内容</view></my-test2>

自定义组件—生命周期

组件生命周期-lifetimes

生命周期函数要写在lifetimes里边

lifetimes: {created() {console.log('组件被created') // 这里使用setData不会引起视图的更新this.setData({msg: 'abc!' })},attached() {this.setData({msg: 'abcd' })}}

自定义组件-属性(父传子)

在小程序中,properties是组件的对外属性,用于接收外界传递到组件中的数据

父组件传入属性值

<my-test isOpen max="9" min="1" />

子组件.js中接收

Component({properties: {isOpen: Boolean,min: Number, // 直接写类型max: {// 写类型 + 初始值type: Number,value: 10 // value用于指定默认值}}})

自定义组件-组件通讯-自定义事件triggerEvent(子传父)

Vant组件库

官方文档:https://vant-contrib.gitee.io/vant-weapp/#/quickstart

步骤一 通过 npm 安装

npm i @vant/weapp -S --production

步骤二 修改 app.json

将 app.json 中的"style": "v2"去除

步骤三 修改 project.config.json

开发者工具创建的项目,miniprogramRoot默认为miniprogrampackage.json在其外部,npm 构建无法正常工作。

需要手动在project.config.json内添加如下配置,使开发者工具可以正确索引到 npm 依赖的位置。

{..."setting": {..."packNpmManually": true,"packNpmRelationList": [{"packageJsonPath": "./package.json","miniprogramNpmDistDir": "./miniprogram/"}]}}

步骤四 构建 npm 包(重点)

开发者工具上 > “工具” > “构建npm”

使用

去app.json(全局注册)或页面.json(局部注册)中注册

"usingComponents": {"van-button": "@vant/weapp/button/index"}

在页面中使用

<van-button type="primary">按钮</van-button>

小程序开发环境-优化目录结构

项目的根目录├── miniprogram // 项目相关的代码夹├── node_modules // npm包目录├── package.json├── project.config.json├── package-lock.json└── sitemap.json

修改project.config.json中的配置项

{// 省略其他......"setting": {// 省略其他......"packNpmManually": true,"packNpmRelationList": [{"miniprogramNpmDistDir": "./miniprogram","packageJsonPath": "package.json"}]},"miniprogramRoot": "miniprogram/"}

启用 less/sass

通过 less/sass 可以更好的管理 css 样式,通过project.config.json可以启用对 less/sass 的支持。

{"setting": {"useCompilerPlugins": ["sass"]}}

然后将.wxss文件后缀改换成.scss即可。

启动项目

拉取代码

导入项目

使用小程序开发者工具导入【项目】的代码

3. 使用小程序开发者工具构建 npm

安装包:npm install手动构建: 【工具】→【构建npm】

project.config.json的几个配置

{"miniprogramRoot": "miniprogram/","setting": {"useCompilerPlugins": ["sass"],"packNpmManually": true,"packNpmRelationList": [{"packageJsonPath": "./package.json","miniprogramNpmDistDir": "./miniprogram"}],}}

miniprogramRoot项目的根目录为miniprogram

setting.useCompilerPlugins启用了sass支持

packNpmRelationList指定了 npm 构建时所需的package.json的位置以及构建后代码的生成位置

4. 改成自己的appid

这个项目中的appid是别人的,如果我们需要改成自己的。

基础封装-消息反馈

将所有通用的工具方法封装到 utils/utils.js 中

/*** 用户消息反馈* @param {string} title 文字提示的内容*/export const toast = (title = '数据加载失败...') => {wx.showToast({title,mask: true,icon: 'none',})}// 挂载到全局对象 wxwx.$toast = toast

app.js

// 在入口中执行 utils.jsimport './utils/utils.js'App({// ...})

使用

wx.$toast('//提示文字', "icon图标")

基础封装-网络请求

安装第三方的包-构建

npm install wechat-http安装完成后还必须要构建 npm后才可以使用

wechat-http用法与axios类似:

http.baseURL配置接口基础路径

http.getGET方法发起请求

http.postPOST方法发起请求

http.putPUT方法发起请求

http.deleteDELETE方法发起请求

http.intercept配置请求和响应拦截器

http本身做为函数调用也能用于发起网络请求

二次封装

新建utils/http.js文件

// 导入 http 模块import http from 'wechat-http'// 基础路径http.baseURL = 'https://live-'// 挂载到全局对象wx.http = http// 普通的模块导出export default http

以全局对象方式调用时需要在入口中执行utils/http.js

// 执行 uitls/http.jsimport './utils/http.js'App({// ...})

配置响应拦截器

// 配置响应拦截器http.intercept.response = function ({data, config }) {// 检测接口是否正常返回结果if (data.code !== 10000) {wx.$toast()return Promise.reject(data)}// 只保留data数据,其它的都过滤掉return data.data}

跳转传参

点击公告列表后将公告的ID通过地址参数传递到公告详情页面,在公告详情页 onLoad 生命周期中读取到公告 ID,然后调用接口获取公告详情的数据。

van-count-down 组件(倒计时)的应用

<van-count-down use-slot time="{{6000}}" bind:change="countDownChange"><text>{{timeData.seconds}}秒后重新获取</text></van-count-down>

time: 指定了倒计时多少毫秒

bind:change每隔一秒的回调,它会传出来当前的倒计时信息

countDownChange(ev) {console.log(ev.detail)this.setData({timeData: ev.detail,getCodeBtnVisible: ev.detail.minutes === 0 && ev.detail.seconds === 0,})},

表单验证插件使用

先在data中设置mobile,再在模板中进行双向绑定

model:value=“{{mobile}}”

安装构建表单验证码插件wechat-validate

npm install wechat-validate

将插件导入到项目中

behaviors将插件注入到页面中

rules由插件提供的属性,用来定义数据验证的规则(类似于 Element UI)

validate由插件提供的方法,根据rules的规则来对数据进行验证

// 导入表单验证插件import validate from 'wechat-validate'Page({data: {mobile: '' // 省略其他},behaviors: [validate], // 将插件注入到页面实例中rules: {mobile: [{required: true, message: '请填写手机号码!'},{pattern: /^1[3-8]\d{9}$/, message: '请填写正确的手机号码!'}]},getSMSCode() {// 获取验证结果const {valid, message } = this.validate('mobile')// 如果验证不合法则不再执行后面的逻辑if (!valid) return wx.$toast(message)console.log('getCode')this.setData({getCodeBtnVisible: false })},})

保存token-跳转

在app.js中设置setToken方法,保存到本地存储

App({// ...setToken(key, token) {// 将 token 记录在应用实例中 this[key] = token// 将 token 存入本地wx.setStorageSync(key, token)}})

2.点击登录 | 注册发送请求成功之后

const app = getApp() //小程序中获取全局的实例对象app.setToken('token', res.token)app.setToken('refreshToken', res.refreshToken)

// 跳转const url = '/pages/profile/index'wx.redirectTo({url })

登录检测-鉴权组件

1.在根目录中创建components文件夹用来存放全局的组件,然后通过小程序开发者工具创建一个名为authorization的组件

2.接下来全局来注册这个组件,保证任何页面中都可以直接应用authorization组件

{"usingComponents": {"authorization": "/components/authorization/index"},}

3.到用户信息页面中应用authorization使用做为页面根节点

<authorization>...</authorization>

4.在authorization中补充插槽和状态

<!--components/authorization/index.wxml--><slot wx:if="{{isLogin}}"></slot>

data: {isLogin: false},

读取本地存储token

读取本地存储的token数据,用于判断是否曾登录过

// app.jsApp({......getToken() {// 将 token 数据记到应用实例中// return this.token = wx.getStorageSync('token')return this.token}})

在组件内读token并处理

data: {isLogin: false},lifetimes: {attached() {const isLogin = !!getApp().getToken() //const app = getApp() const isLogin = !!app.getToken()this.setData({isLogin })if (!isLogin) {wx.redirectTo({url: '/pages/login/index' })}}},

地址重定向,登录成功后跳回到原来的页面

authoirzation组件检测登录时获取当前页面栈实例,并在跳转到登录页面时在 URL 地址上拼凑参数:

// /components/authorization/index.jsComponent({// ...lifetimes: {attached() {// 获取登录状态const isLogin = !!getApp().token// 变更登录状态this.setData({isLogin })// 获取页面栈const pageStack = getCurrentPages()// 获取页面路径const currentPage = pageStack.pop()// 未登录的情况下跳转到登录页面if (!isLogin) {wx.redirectTo({url: '/pages/login/index?redirectURL=/' + currentPage.route,})}},},})

用户管理-显示默认值

app.js中添加初始值

App({globalData: {},userInfo: {avatar: '', nickName: '微信用户1' }}

在onLoad中加载值

data: {avatar: '',nickName: ''},onLoad() {const app = getApp()console.log(app.userInfo)const {avatar, nickName } = app.userInfothis.setData({avatar, nickName })// 用户未登录时不必请求app.token && this.getUserProfile()},

配置请求拦截器

将用户的登录状态通过自定义的头信息Authorization随接口调用时一起发送到服务端。

// 导入 wechat-http 模块import http from 'wechat-http'// 配置接口基础路径http.baseURL = 'https://live-'// 配置请求拦截器http.intercept.request = function (options) {console.log('请求拦截器', options.header)// 扩展头信息const defaultHeader = {}// 身份认证const token = getApp().getToken()if (token) {defaultHeader.Authorization = 'Bearer ' + getApp().getToken()}// 与默认头信息合并options.header = Object.assign({}, defaultHeader, options.header)// 处理后的请求参数return options}

注:传递token时需要拼凑字符串前缀 "Bearer "

文件上传(例:更新用户头像)

获取用户选择的头像地址,通过wx.uploadFile将图片上传到服务端。

wx.uploadFile的基本语法:

url上传接口地址

filePath待上传文件的临时路径(该路径只能用于小程序内部)

name接口接收上传文件的数据名称(由后端指定)

formData除上传文件外的其它数据

header自定义头信息

success上传成功的回调函数

fail上传失败后的回调函数

complete上传完成时的回调(无论成功或失败)

注:该 API 不支持返回 Promise,调用该 API 时,需要提前在小程序管理后台添加服务器域名。

<!-- pages/profile/index.wxml --><authorization><view class="profile"><van-cell center title="头像"><van-icon slot="right-icon" name="arrow" size="16" color="#c3c3c5" /><buttonclass="button"size="mini"hover-class="none"bind:chooseavatar="updateUserAvatar" //事件,事件名全部小写,A千万不要大写,不会触发open-type="chooseAvatar"> //与上边事件对应<image class="avatar" src="{{avatar}}"></image></button></van-cell>...</view></authorization>

// pages/profile/index.jsconst pageStack = getCurrentPages()Page({...// 更新用户头像updateUserAvatar(ev.detail.avatarUrl) {// 调用 API 上传文件wx.uploadFile({// 接口地址url: wx.$http.baseURL + '/upload',// 待上传的文件路径filePath: avatar,name: 'file',// wx.uploadFile 要求必传。header: {Authorization: 'Bearer ' + getApp().getToken() // 用户登录状态},formData: {// 是我们自己的接口文档的要求。可以不传,默认就是avatartype: 'avatar'},success: (result) => {console.log(JSON.parse(result.data))const res = JSON.parse(result.data)// console.log(res.data.url)const avatar = res.data.url// 1. 在页面上显示this.setData({avatar })// 2. 更新全局数据const app = getApp()app.userInfo.avatar = avatar// 3. 通过页面栈找到my/index页面,更新它的avatar信息const pages = getCurrentPages()// pages[0].data.nickName = nickName 直接修改数据不会让视图更新// 调用setData更新pages[0].setData({avatar })}})}})

上述代码中通过wx.http.baseURL获取接口服务器地址,通过应用实例获取token

refresh_token使用

token:

作用:在访问一些接口时,需要传入token,就是它。有效期:2小时(安全)。

refresh_token

作用: 当token的有效期过了之后,可以使用它去请求一个特殊接口(这个接口也是后端指定的,明确需要传入refresh_token),并返回一个新的token回来(有效期还是2小时),以替换过期的那个token。有效期:14天。(最理想的情况下,一次登陆可以持续14天。)

1.用户在首次完成登录时会分别得到 token 和 refresh_token

2.当 token 失效后(例如2小时之后),调用接口A会返回 401 状态码(这是与后端约定好的规则)

3.检测状态码是否为 401**,如果是,则携带refreshToken去调用刷新token的接口

4.刷新 token 的接口后会返回新的 token 和 refreshToken

5.把401的接口A重新发送一遍

注意:

refresh_token也是有过期时间的,只不过一般会比token过期时间更长一些。这就是为啥如果某个应用我们天天打开,则不会提示我们登录,如果是有几周或更长时间去打开时,会再次要求我们登录。

refresh_token一个更常见的名字叫token无感刷新。

refreshToken功能-基本实现

// 响应拦截器http.intercept.response = async ({statusCode, data, config }) => {console.log(statusCode, data, config)// console.log(statusCode) // http 响应状态码// console.log(config) // 发起请求时的参数if (data.code === 401) {const app = getApp()// 调用接口获取新的 tokenconst res = await http({url: '/refreshToken',method: 'POST',header: {Authorization: 'Bearer ' + app.getToken('refreshToken'),}})app.setToken('token', res.token)app.setToken('refreshToken', res.refreshToken)// 获得新的token后需要重新发送刚刚未完成的请求config = Object.assign(config, {header: {// 更新后的 tokenAuthorization: 'Bearer ' + res.token,},})// 重新发请求return http(config)}// 拦截器处理后的响应结果if (data.code === 10000) {return data.data} else {wx.$toast(data.message || '请求失败')return Promise.reject(data.message)}}

refreshToken也过期的特殊处理

完整版响应拦截器

// 响应拦截器http.intercept.response = async ({statusCode, data, config }) => {console.log(statusCode, data, config)// console.log(statusCode) // http 响应状态码// console.log(config) // 发起请求时的参数if (data.code === 401) {++ if (config.url.includes('/refreshToken')) {++console.log('/refreshToken过期了')++// 获取当前页面的路径,保证登录成功后能跳回到原来页面++const pageStack = getCurrentPages()++const currentPage = pageStack.pop()++const redirectURL = currentPage.route++// 跳由跳转(登录页面)++wx.redirectTo({++ url: '/pages/login/index?redirectURL=/' + redirectURL,++})++return Promise.reject('refreshToken也过期了,就只能重新登录了')++ }const app = getApp()// 调用接口获取新的 tokenconst res = await http({url: '/refreshToken',method: 'POST',header: {Authorization: 'Bearer ' + app.getToken('refreshToken'),}})app.setToken('token', res.token)app.setToken('refreshToken', res.refreshToken)config = Object.assign(config, {header: {// 更新后的 tokenAuthorization: 'Bearer ' + res.token,},})// 重新发请求return http(config)}// 拦截器处理后的响应结果else if (data.code === 10000) {return data.data} else {wx.$toast(data.message || '请求失败')return Promise.reject(data.message)}}

腾讯位置服务-需要提前注册

文档地址:/miniProgram/jsSdk/jsSdkGuide/jsSdkOverview

使用步骤(共4步)

申请开发者密钥(key):申请密钥(地址:/dev/console/application/mine)开通webserviceAPI服务:控制台 ->应用管理 -> 我的应用->添加key-> 勾选WebServiceAPI -> 保存(小程序SDK需要用到webserviceAPI的部分服务,所以使用该功能的KEY需要具备相应的权限)

3.下载微信小程序JavaScriptSDK,微信小程序JavaScriptSDK v1.1(/web/miniprogram/JSSDK/qqmap-wx-jssdk1.1.zip)JavaScriptSDK v1.2(/web/miniprogram/JSSDK/qqmap-wx-jssdk1.2.zip) js文件

4.安全域名设置,在小程序管理后台-> 开发 -> 开发管理 -> 开发设置 -> “服务器域名” 中设置request合法域名,添加https://apis.

地理定位-wx.getLocation

获取用户所在位置的经纬度。在小程序中调用这个接口时必须先在 app.json 中申请调用权限(开发环境可以省略)。

//app.json{"requiredPrivateInfos": [++ "getLocation"],"permission": {"scope.userLocation": {"desc": "你的位置信息将用于小程序位置接口的效果展示"}},}

Page({onLoad() {this.getLocation()},async getLocation() {const res = await wx.getLocation() // 要提前申请权限console.log(res)},})

wx.getLocation返回的结果格式大致如下:

accuracy: 65errMsg: "getLocation:ok"horizontalAccuracy: 65latitude: 30.88131longitude: 114.37509speed: -1verticalAccuracy: 65

wx.getLocation 只能得到经纬度信息

逆地址解析-reverseGeocoder

由坐标 → 坐标所在位置的文字描述的转换,输入坐标返回地理位置信息和附近poi列表

文档地址:/miniProgram/jsSdk/jsSdkGuide/methodReverseGeocoder

1. 导入 QQMapWX 并设置好 key

2.在代码中补充getPoint方法:

调用接口把经纬度转换成对应位置的文字保存文字到address

// 导入位置服务实例import QQMap from '../../../utils/qqmap'Page({......onLoad() {this.getLocation()},async getLocation() {// 调用小程序API获取经纬度等信息const {latitude, longitude } = await wx.getLocation() //获取用户经纬度this.getPoint(latitude, longitude) },getPoint(latitude, longitude) {// 逆地址解析(根据经纬度来获取地址)QQMap.reverseGeocoder({location: [latitude, longitude].join(','),success: (result) => {const address = res.addressthis.setData({address })},})}})

3.渲染页面

<van-cell-group border="{{false}}" title="当前地点"><van-cell title="{{address}}" border="{{false}}"> //border="{{false}}"设置无边框样式<text bind:tap="chooseLocation" class="enjoy-icon icon-locate">重新定位</text></van-cell></van-cell-group>

QQMap地点搜索—search

根据当前的定位,调用 QQMap.search() 找到周边的信息。

搜索周边poi(Point of Interest),比如:“酒店” “餐饮” “娱乐” “学校” 等等

文档地址:/miniProgram/jsSdk/jsSdkGuide/methodSearch

在小程序中调用这个接口时必须要在 app.json 中申请调用权限

//app.json{"requiredPrivateInfos": [++ "chooseLocation"]}

// 选择新的位置async chooseLocation() {// 调用小程序 API 获取新的位置const {latitude, longitude } = await wx.chooseLocation()this.getPoint(latitude, longitude) // 获取新的位置经纬度},getPoint(latitude, longitude) {wx.showLoading({title: '正在加载...',// 显示loading提示})// 逆地址解析(根据经纬度来获取地址)QQMap.reverseGeocoder({location: [latitude, longitude].join(','),success: ({result: {address } }) => {this.setData({address })},})QQMap.search({keyword: '住宅小区', //搜索关键词location: [latitude, longitude].join(','), //设置周边搜索中心点page_size: 5, //只显示5条信息,不设置此项默认为10success: (result) => {//success 是一个回调函数,表示搜索成功后的处理逻辑。const points = result.datathis.setData({points }) // 渲染数据},fail: (err) => {//fail 是一个回调函数,表示搜索失败后的处理逻辑。console.log(err.message)},complete: () => {//complete 是一个回调函数,表示搜索结束后的处理逻辑(无论搜索成功还是失败)wx.hideLoading() // 隐藏loading提示},})},

重新定位-wx.chooseLocation

申请权限

获取用户指定位置的经纬度。在小程序中调用这个接口时必须要在 app.json 中申请调用权限

{"requiredPrivateInfos": ["chooseLocation"]}

示例代码:

// 选择新的位置async chooseLocation() {// 调用小程序 API 获取新的位置const {latitude, longitude } = await wx.chooseLocation()// 获取新的位置附近的小区this.getPoint(latitude, longitude)console.log('起点位置:', latitude, longitude)},getPoint(latitude, longitude) {// 显示loading提示wx.showLoading({title: '正在加载...',})// 逆地址解析(根据经纬度来获取地址)QQMap.reverseGeocoder({location: [latitude, longitude].join(','),success: ({result: {address } }) => {// console.log(address)// 数据数据this.setData({address })},})QQMap.search({keyword: '住宅小区', //搜索关键词location: [latitude, longitude].join(','), //设置周边搜索中心点page_size: 5,success: (result) => {// console.log(result)// 过滤掉多余的数据const points = result.data.map(({id, title, _distance }) => {return {id, title, _distance }})// console.log(points)// 渲染数据this.setData({points })},fail: (err) => {console.log(err.message)},complete: () => {// 隐藏loading提示wx.hideLoading()},})},

图片收集(收集身份证信息)

小程序没有input type="file"用于选择文件,要实现类似功能,用以下api:

wx.chooseMedia**:**拍摄或从手机相册中选择图片或视频。

低版本请用wx.chooseImage。

1.绑定事件选择身份证图片上传。

2.发送请求上传图片,拿到上传后的图片地址。

Page({...async uploadPicture(ev) {// 获取图片临时地址const res = await wx.chooseMedia({count: 1,mediaType: ['image'],sizeType: ['compressed'],})const tempPath = res.tempFiles[0].tempFilePathconst type = ev.mark.type// 上传图片到服务器wx.uploadFile({url: wx.$http.baseURL + '/upload',filePath: tempPath,name: 'file',header: {Authorization: 'Bearer ' + getApp().getToken(),},success: (res) => {const res = JSON.parse(result.data)console.log(res.data.url) // 上传成功的回调this.setData({[type]: res.data.url })},})},})

校验表单信息

获取了全部的表单数据后再对数据进行验证,说明如下:

房屋的信息是通过url地址获取的不需要验证性别可以指定默认值也不需要验证剩下的数据通过wechat-validate插件进行验证:

// house_pkg/pages/form/index.js// 导入表单验证插件import wxValidate from 'wechat-validate'Page({behaviors: [wxValidate],data: {point: '',building: '',room: '',name: '',gender: 1,mobile: '',idcardFrontUrl: '',idcardBackUrl: '',},rules: {name: [{required: true, message: '业主姓名不能为空!' },{pattern: /^[\u4e00-\u9fa5]{2,5}$/, message: '业主姓名只能为中文!' },],mobile: [{required: true, message: '业主手机号不能为空!' },{pattern: /^1[3-8]\d{9}$/, message: '请填写正确的手机号!' },],idcardFrontUrl: [{required: true, message: '请上传身份证国徽面!' }],idcardBackUrl: [{required: true, message: '请上传身份证照片面!' }],},})

表单收集—收集预约日期

1.时间选择控件:van-datetime-pickerhttps://vant-contrib.gitee.io/vant-weapp/#/datetime-picker

2.弹出层控件:van-popuphttps://vant-contrib.gitee.io/vant-weapp/#/popup

给选择日期单元绑定事件——显示选择日期弹层(van-popup)

2.给日期控件绑定确认事件confirm

3.在确认回调中获取时间戳

4.将时间戳格式化并显示

selectDate(ev) {// console.log(ev)this.setData({currentDate: ev.detail,appointment: wx.$utils.formatDate(ev.detail), // 格式化日期})this.closeDateLayer()},

补充格式化日期的函数

formatDate(time) {const d = new Date(time)const year = d.getFullYear()let month = d.getMonth() + 1 // 获取月份,月份从0开始,所以加1let day = d.getDate()month = month < 10 ? '0' + month : monthday = day < 10 ? '0' + day : dayreturn `${year}-${month}-${day}`},

wxml

<van-cell title-width="100" title="预约日期" value-class="{{appointment && 'active-cell'}}" bind:click="openDateLayer"is-link value="{{appointment || '请选择上门维修日期'}}" />...省略<van-popup bind:close="closeDateLayer" round show="{{ dateLayerVisible }}" position="bottom"><van-datetime-picker bind:cancel="closeDateLayer" bind:confirm="selectDate" type="date" value="{{ currentDate }}"min-date="{{ 1664582400000 }}" /></van-popup>

加载更多

在scroll-view上添加 bindscrolltolower=“loadMore”

<scroll-view bindscrolltolower="loadMore"show-scrollbar="{{false}}" enhanced scroll-y><view class="repairs"><view class="repairs-title">我的报修</view>

loadMore() {// if(是否有更多的数据)if (this.data.total <= this.data.list.length)returnconsole.log('更多的数据')// 把页码+1,发请求,请求回来的数据要 追加 到原数组// [5] → [10]this.data.page++this.getList()},async getList() {// 发请求const {pageTotal, total, rows: list } = await wx.$http.get('/repair', {current: this.data.page, pageSize: this.data.pageSize })console.log(list, pageTotal, total)// 渲染数据// 在原来的基础上添加数据this.setData({total, list: [...this.data.list, ...list] })},

路线规划

路线规划是常见的一个功能,它用来在地图上展示两点间路线,要使用这个功能需要用到两部分的知识:

小程序提供的 map 组件用来在页面渲染地图

map | 微信开放文档https://developers./miniprogram/dev/component/map.html)

腾讯位置服务计算两点路线的所有坐标点(经纬度)

首先来看小程序提供的地图组件 map

latitude 指定地图中心点的纬度longitude 指定地图中心点的经功scale 指定地图初始的缩放比例,取值范围 3 - 20markers 地图上的标记点polyline 地图上的路线

latitude、longitude、scale 相对容易理解,重点来看一下 markers 的使用:

repqir_pkg/pages/detail/index.js

Page({data: {markers: [{id: 1,latitude: 40.22077,longitude: 116.23128,width: 24,height: 30,},{id: 2,latitude: 40.225857999999995,longitude: 116.23246699999999,iconPath: '/static/images/marker.png',width: 40,height: 40,},],}})

在定义标记点时每个标记点必须要指定 ID 属性,否则会有错误产生,通过 iconPath 可以自定义标记点的图片,width/height 定义标记点的大小尺寸。

polyline

polyline 用来在在图上展示两点间的行进路线,需要传递给它路线对应的坐标点(很多个点组成的线),获取这些坐标点需要通过位置服务计算得到。

计算两点间路线的坐标点需要用到位置服务的[路线规划]/miniProgram/jsSdk/jsSdkGuide/methodDirection方法

repqir_pkg/pages/detail/index.js

// repqir_pkg/pages/detail/index.jsPage({data: {},onLoad() {// 生成路线this.getPolyline()},// 调用位置服务(路线规划)getPolyline() {qqMap.direction({mode: 'bicycling',from: '40.227978,116.22998',to: '40.22077,116.23128',success: ({result }) => {const coors = result.routes[0].polylineconst points = []//坐标解压(返回的点串坐标,通过前向差分进行压缩)for (let i = 2; i < coors.length; i++) {coors[i] = Number(coors[i - 2]) + Number(coors[i]) / 1000000}// 获取经纬度for (let i = 0; i < coors.length; i += 2) {points.push({latitude: coors[i], longitude: coors[i + 1] })}// 渲染数据this.setData({latitude: points[30].latitude,longitude: points[30].longitude,polyline: [{points, color: '#5591af', width: 4},],})},})},})

计算出来的坐标点是经过压缩的,需要按着官方指定的方式对数据进行解压才可以获取真正的坐标点,并且为了适应小程序地图组件的用法,还需要对数据进行二次的加工。

关于数据的处理大家只需要参考文档来实现就可以,可以说之所这么操作是腾讯位置服务规订好的,做为开发者按着官方提从的方法来应用即可。

自定义分享

[onShareAppMessage]https://developers./miniprogram/dev/reference/api/Page.html#onShareAppMessage-Object-object

监听用户点击页面内转发按钮(button 组件 open-type=“share”)或右上角菜单“转发”按钮的行为,并自定义转发内容。

注意:只有定义了此事件处理函数,右上角菜单才会显示“转发”按钮

Page({onLoad({id, encryptedData }) {this.getPassport(id)this.getPassportShare(encryptedData)},// 获取访客详情(通行证)async getPassport(id) {// 检测是否存在 idif (!id) return// 调用接口const passport = await wx.$http.get('/visitor/' + id)// 渲染数据this.setData({...passport })}async getPassportShare(encryptedData) {// 检测是否存在 idif (!encryptedData) return// 调用接口const passport = await wx.$http.get('/visitor/share/' + this.data.encryptedData)// 渲染数据this.setData({passport })},onShareAppMessage() {return {title: '查看通行证',path: '/visitor_pkg/pages/passport/index?encryptedData=' + encryptedData,imageUrl: 'https://enjoy-plus.oss-cn-/images/share_poster.png',}},})

保存到本地api介绍

[saveImageToPhotosAlbum]https://developers./miniprogram/dev/api/media/image/wx.saveImageToPhotosAlbum.html

保存图片到系统相册。

[getImageInfo]https://developers./miniprogram/dev/api/media/image/wx.getImageInfo.html

获取图片信息。网络图片需先配置 download 域名才能生效。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UyIG4FD7-1687267141879)(C:\Users\ZhengKaiYa\Desktop\个人笔记\3\21.png)]

保存到本地实现

1.给按钮绑定事件,调用getImageInfo获取图片临时路径

2.调用saveImageToPhotosAlbum传入临时路径完成保存功能

// 保存图片async saveQRCode() {try {// 读取图片信息const {path } = await wx.getImageInfo({src: this.data.url,})// 保存图片到相册wx.saveImageToPhotosAlbum({filePath: path })} catch (err) {wx.$toast('保存图片失败,稍后重试!')}},

gram/dev/component/button.html) 组件 open-type=“share”)或右上角菜单“转发”按钮的行为,并自定义转发内容。

注意:只有定义了此事件处理函数,右上角菜单才会显示“转发”按钮

Page({onLoad({id, encryptedData }) {this.getPassport(id)this.getPassportShare(encryptedData)},// 获取访客详情(通行证)async getPassport(id) {// 检测是否存在 idif (!id) return// 调用接口const passport = await wx.$http.get('/visitor/' + id)// 渲染数据this.setData({...passport })}async getPassportShare(encryptedData) {// 检测是否存在 idif (!encryptedData) return// 调用接口const passport = await wx.$http.get('/visitor/share/' + this.data.encryptedData)// 渲染数据this.setData({passport })},onShareAppMessage() {return {title: '查看通行证',path: '/visitor_pkg/pages/passport/index?encryptedData=' + encryptedData,imageUrl: 'https://enjoy-plus.oss-cn-/images/share_poster.png',}},})

保存到本地api介绍

[saveImageToPhotosAlbum]https://developers./miniprogram/dev/api/media/image/wx.saveImageToPhotosAlbum.html

保存图片到系统相册。

[getImageInfo]https://developers./miniprogram/dev/api/media/image/wx.getImageInfo.html

获取图片信息。网络图片需先配置 download 域名才能生效。

保存到本地实现

1.给按钮绑定事件,调用getImageInfo获取图片临时路径

2.调用saveImageToPhotosAlbum传入临时路径完成保存功能

// 保存图片async saveQRCode() {try {// 读取图片信息const {path } = await wx.getImageInfo({src: this.data.url,})// 保存图片到相册wx.saveImageToPhotosAlbum({filePath: path })} catch (err) {wx.$toast('保存图片失败,稍后重试!')}},

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。