• 微信小程序 ---- 慕尚花坊 用户管理


    01. 用户登录-什么是 token

    什么是 Token

    Token服务器生成的一串字符串,用作客户端发起请求的一个身份令牌。当第一次登录成功后,服务器生成一个 Token 便将此 Token 返回给客户端,客户端在接收到 Token 以后,会使用某种方式将 Token 保存到本地。以后客户端发起请求,只需要在请求头上带上这个 Token ,服务器通过验证 Token 来确认用户的身份,而无需再次带上用户名和密码。

    **Token的具体流程 **

    1. 客户端向服务器发起登录请求,服务端验证用户名与密码
    2. 验证成功后,服务端会签发一个 Token,并将 Token 发送到客户端
    3. 客户端收到 token 以后,将其存储起来,比如放在 localStoragesessionStorage
    4. 客户端每次向服务器请求资源的时候需要带着服务端签发的 Token,服务端收到请求,然后去验证客户端请求里面带着的 Token ,如果验证成功,就向客户端返回请求的数据

    在这里插入图片描述

    02. 用户登录-小程序登录流程介绍

    业务介绍:

    传统的登录功能,需要用户先注册,注册完成以后,使用注册的账号、密码进行登录。

    小程序的登录操作则比较简单,小程序可以通过微信提供的登录能力,便捷地获取微信提供的用户身份标识进行登录。

    免去了注册和输入账号密码的步骤,从而提高了用户体验。

    小程序登录图示:

    在这里插入图片描述
    登录流程说明:

    1. 用户访问小程序,点击 [登录] ,调用 wx.login() 方法获取 临时登录凭证code

      临时登录凭证 code,就像是一个会过期的临时身份证一样,有效时间仅为 5分钟

    2. 使用 wx.request() 方法将 临时登录凭证code 传递给开发者服务器,方便后续可以换取微信用户身份 id

    3. 开发者的后台接收 临时登录凭证code,同时在微信公众后台拿到 AppIdAppSecret ,向微信服务器发送请求,
      请求参数合法的话,微信服务器会给开发者后台返回 openid(微信用户的唯一标识) 以及 session_key(会话密钥) 等

      openid 是微信用户的唯一标识,也就是微信用户身份 id,可以用这个 id 来区分不同的微信用户

      session_key 则是微信服务器给开发者服务器颁发的身份凭证,

      开发者可以用session_key请求微信服务器其他接口来获取一些其他信息

    4. 开发者后台在接收到微信服务器返回的数据以后,会执行一些业务逻辑的处理,例如:将用户标识和其他信息进行加密处理,生成自定义登录态,这个登录态可以理解为就是 Token ,然后让 Tokenopenidsession_key 进行关联

    5. 开发者后台处理好逻辑后,会将 自定义登录态 Token 返回给微信小程序客户端,客户端收到 token 以后,将其存储起来,比如放在 localStorage 中。

    6. 客户端每次向开发者后台发送请求的时候,需要携带自定义登录态 Token ,开发者后台收到请求后,对 Token 进行验证识别用户身份,同时拿自定义登录态 Token 查询 openidsession_key,从而获取用户请求的数据,进行返回。

    03. 用户登录-实现小程序登录功能

    思路分析:

    当用户没有登录的时候,需要点击个人中心的头像,跳转到登录页面进行登录。在登录成功以后,需要再次返回到个人中心页面

    在登录页面我们使用了 Vant 提供的两个组件来进行页面结构的绘制

    1. empty 组件:空状态时的占位提示
    2. button 组件:按钮组件

    给登录按钮绑定点击事件,在事件处理程序中,调用 wx.login 获取 临时登录凭证code

    然后调用后端接口,将 临时登录凭证code 传递给后端

    熟悉接口文档:微信登录

    根据接口文档封装接口 API 函数,当点击授权登录按钮的时候调用 API 函数,在获取到 token 以后,将 token 存储到本地,然后跳转到登录之前的页面。

    实现步骤:

    1. /api/user.js 文件中根据接口文档,创建登录的 API 函数 login
    2. 给登录按钮绑定点击事件,对应 login 回调函数
    3. login 回调函数中调用 wx.login() 方法,获取临时登录凭证code
    4. /pages/login/login.js 中导入封装好的 API 函数,传入 临时登录凭证code 然后调用
    5. 在登录成功以后将 token 存储到本地

    落地代码:

    ➡️ /api/user.js

    import http from '../utils/http'
    
    /**
     * @description 授权登录
     * @param {*} code 临时登录凭证code
     * @returns Promise
     */
    export const reqLogin = (code) => {
      return http.get(`/mall-api/weixin/wxLogin/${code}`)
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    ➡️ /pages/login/login.js

    import { reqLogin } from '../../api/user'
    import { toast } from '../../utils/extendApi'
    
    Page({
      // 点击登录
      login() {
        // 调用 wx.login 获取用户信息
        wx.login({
          success: async ({ code }) => {
            if (code) {
              // 调用接口 API,传入 code 进行登录
              const res = await reqLogin(code)
    
              // 登录成功以后将 token 存储到本地
              wx.setStorageSync('token', res.data.token)
    
              // 返回之前的页面
              wx.navigateBack()
            } else {
              // 登录失败后给用户进行提示
              toast({ title: '授权失败,请稍后再试~~~' })
            }
          }
        })
      }
    })
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    04. 用户登录-token 存储到 Store

    思路分析:

    在上一节,我们已经将token存储到了本地,但是将 Token 直接存储到本地不方便对数据进行操作,要先从本地存储取出,然后在使用,关键的一点,存储到本地的数据不是响应式的,当本地存储里面的内容发生改变,页面不会发生改变。这时候我们就需要将 token 也存储到 Store 中,这一节,我们需要做的就是将 Token 存储到 Mobx 中。

    Mobx允许开发人员在应用程序中统一管理所有组件之间的公共数据。通过使用 Mobx,开发人员可以轻松地将 token 存储到全局状态中,并实现在整个应用程序中的共享。并且,存储到Mobx中的数据是响应式的,数据发生了变化,使用的地方也会发生变化

    首先我们先安装Mobx,然后进行实例化,在实例化的时候,创建共享的数据 Token,以及对 Token 修改的方法

    然后使用 Component 构造页面,并导入ComponentWithStore 方法,并配置 storeBindings 方法让页面和 Store 对象关联

    实现步骤:

    1. 安装Mobx两个包,在安装好包以后,对包进行构建,点击 构建 npm
    2. 在项目的根目录下创建 store 文件夹,然后在该文件夹下新建 userstore.js
    3. 导入核心的observable action 方法,创建Store,同时声明数据和方法
    4. 在登录页面,导入ComponentWithStore 方法,并配置 storeBindings 方法让页面和 Store 对象关联

    落地代码:

    安装依赖,安装完成后构建 npm

    npm i mobx-miniprogram mobx-miniprogram-bindings
    
    • 1

    ➡️ /store/index.js

    // 导入 observable 函数用于创建可观察对象
    // 导入 action 修改 store 中的可观察状态
    import { observable, action } from 'mobx-miniprogram'
    import { getStorage } from '../utils/storage'
    
    // 创建 store 对象,存储应用的状态
    export const userStore = observable({
      // 创建可观察状态 token
      token: getStorage('token') || '',
    
      // 对 token 进行修改
      setToken: action(function (token) {
        this.token = token
      })
    })
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    ➡️ /pages/login/login.js

    import { reqLogin } from '../../api/user'
    + import { userStore } from '../../api/userstore'
    
    + import { ComponentWithStore } from 'mobx-miniprogram-bindings'
    
    + ComponentWithStore({
        
    +   storeBindings: {
    +     store: userStore,
    +     fields: ['token'],
    +     actions: ['setToken']
    +   }
    
    +   methods: {
        // 授权登录
        login() {
          // 使用 wx.login 获取用户的临时登录凭证 code
          wx.login({
            success: async ({ code }) => {
              if (code) {
                // 在获取到临时登录凭证 code 以后,需要传递给开发者服务器
                const { data } = await reqLogin(code)
    
                // 登录成功以后,需要将服务器响应的自定义登录态存储到本地
                setStorage('token', data.token)
                  
    +             // 将数据存储到 store 对象中
    +             this.setToken(data.token)
              } else {
                toast({ title: '授权失败,请重新授权' })
              }
            }
          })
        }
    +   }
    })
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    05. 用户信息-用户信息存储到 Store

    思路分析:

    在这一节,我们需要调用接口获取用户的信息,在获取到数据以后,我们需要存储用户信息数据到本地,

    用户信息可能会在多个地方使用到,为了方便对用户信息的获取和使用,我们依然将用户信息存储到store

    我们首先在 store/index.js 中新增userInfo可观测字段,同时创建赋值和删除的action方法

    然后熟悉接口文档:获取用户信息

    在熟悉了接口文档以后,根据接口文档封装接口 API 函数

    获取用户信息的接口需要使用 token,所以我们需要在登录成功以后,调用获取用户信息的接口

    登录成功以后,将用户信息存储到本地,然后调用action方法,将用户信息存储到 Store

    实现步骤:

    1. store/userstore.js 中新增userInfo字段,同时创建修改的action方法

    2. login.js 中使用映射 userInfo 数据和 setUserInfo 方法

    3. /api/user.js 文件中根据接口文档,创建获取用户信息的 API 函数 reqUserInfo

    4. /pages/login/login.js 中导入封装好的获取商品列表的 API 函数

    5. 创建 getUserInfo 方法,在 getUserInfo 方法中调用接口 API 函数 reqUserInfo

    6. 在登录成功以后,调用getUserInfo 方法获取用户,然后将用户信息存到本地以及 Store

    落地代码:

    ➡️ /api/user.js

    /**
     * @description 获取用户信息
     * @returns Promise
     */
    export const reqUserInfo = () => {
      return http.get(`/mall-api/weixin/getuserInfo`)
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    ➡️ /store/userstore.js

    // 导入 observable 函数用于创建可观察对象
    // 导入 action 修改 store 中的可观察状态
    import { observable, action } from 'mobx-miniprogram'
    import { getStorage } from '../utils/storage'
    
    // 创建 store 对象,存储应用的状态
    export const userStore = observable({
      // 创建可观察状态 token
      // token,登录令牌
      token: getStorage('token') || '',
    +   // 用户信息
    +   userInfo: wx.getStorageSync('userInfo') || {},
    
      // 对 token 进行修改
      setToken: action(function (token) {
        this.token = token
      }),
        
    +   // 设置用户信息
    +   setUserInfo: action(function (userInfo) {
    +     this.userInfo = userInfo
    +   })
    })
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    ➡️/pages/login/login.js

    // pages/login/login.js
    
    // 导入封装通用模块方法
    import { toast } from '../../utils/extendApi'
    // 导入本地存储 api
    import { setStorage } from '../../utils/storage'
    // 导入接口 API 函数
    + import { reqLogin, reqUserInfo } from '../../api/user'
    
    // 导入 ComponentWithStore 方法
    import { ComponentWithStore } from 'mobx-miniprogram-bindings'
    // 导入 store 对象
    import { userStore } from '../../stores/userstore'
    
    // 使用 ComponentWithStore 方法替换 Component 方法构造页面
    ComponentWithStore({
      // 让页面和 Store 对象建立关联
      storeBindings: {
        store: userStore,
    +     fields: ['token', 'userInfo'],
    +     actions: ['setToken', 'setUserInfo']
      },
    
      methods: {
        // 授权登录
        login() {
          // 使用 wx.login 获取用户的临时登录凭证 code
          wx.login({
            success: async ({ code }) => {
              if (code) {
                // 在获取到临时登录凭证 code 以后,需要传递给开发者服务器
                const { data } = await reqLogin(code)
    
                // 登录成功以后,需要将服务器响应的自定义登录态存储到本地
                setStorage('token', data.token)
    
                // 将自定义登录态 token 存储到 Store 对象
                this.setToken(data.token)
                  
    +           // 获取用户信息
    +           this.getUserInfo()
              } else {
                toast({ title: '授权失败,请重新授权' })
              }
            }
          })
        },
            
        // 获取用户信息
        async getUserInfo() {
          const { data } = await reqUserInfo()
          // 将用户信息存储到本地
          setStorage('userInfo', data)
    +     // 将用户信息存储到 Store
    +     this.setUserInfo(data)
        }
      }
    })
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    06. 用户信息-使用数据渲染用户信息

    思路分析:

    在获取到数据以后,我们已经将用户信息数据存储到本地和Store

    这一节我们需要从 Store 中取出用户信息数据,并渲染到页面上

    个人中心页面展示用于展示个人信息

    如果用户没有登录的时候,展示没有登录的头像、提示用户登录的文案信息,不展示设置按钮

    如果用户已经登录,展示用户的头像和昵称,并且展示设置按钮,方便用户对收货地址、头像、昵称进行更改

    实现步骤:

    1. 在个人中心页面导入ComponentWithStore 方法构建页面
    2. 配置 storeBindings 让组件和 Store 建立关联
    3. 渲染页面

    落地代码:

    ➡️/pages/info/info.js

    + import { ComponentWithStore } from 'mobx-miniprogram-bindings'
    
    + ComponentWithStore({
        
    +   storeBindings: {
    +     store: userStore,
    +     fields: ['token', 'userInfo']
    +   }
    
    })
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    ➡️/pages/info/info.wxml

    
    <view class="container bg">
      
      <view class="top-show">
        <image mode="widthFix" class="top-show-img" src="/static/images/banner.jpg">image>
      view>
      <view class="wrap">
    
        
    +     <view class="user-container section" wx:if="{{ !token }}" bindtap="toLoginPage">
          <view class="avatar-container">
            <image src="/static/images/avatar.png">image>
            <view class="no-login">
              <text class="ellipsis">未登录text>
              <text>点击授权登录text>
            view>
          view>
        view>
    
    +     
    +     <view wx:else class="user-container section">
    +       <view class="avatar-container">
    +         <image src="{{ userInfo.headimgurl }}">image>
    +         <view class="no-login">
    +           <text class="ellipsis">{{ userInfo.nickname }}text>
    +         view>
    +       view>
    +       <view class="setting">
    +         设置
    +       view>
    +     view>
    
        
        <view class="order section">
          <view class="order-title-wrap">
            <text class="title">我的订单text>
            <text class="more">查看更多>text>
          view>
          <view class="order-content-wrap">
            <view class="order-content-item">
    +           <navigator wx:if="{{ !token }}" url="/pages/login/login">
    +             <view class="iconfont icon-dingdan">view>
    +             <text>商品订单text>
    +           navigator>
    +           <navigator wx:else url="/pages/order/list/index">
    +             <view class="iconfont icon-dingdan">view>
    +             <text>商品订单text>
    +           navigator>
            view>
            <view class="order-content-item">
              <view class="iconfont icon-lipinka">view>
              <text>礼品卡订单text>
            view>
            <view class="order-content-item">
              <view class="iconfont icon-tuikuan">view>
              <text>退款/售后text>
            view>
    
          view>
        view>
    
        
        <view class="after-scale section">
          
        view>
    
        
        <view class="info-footer">
          尚硅谷技术支持
        view>
      view>
    view>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73

    07. 分包处理-配置分包以及预下载

    思路分析:

    随着项目功能的增加,项目体积也随着增大,从而影响小程序的加载速度,影响用户的体验。

    因此我们需要将 更新个人资料收货地址 功能配置成一个分包,

    当用户在访问设置页面时,还预先加载 更新个人资料收货地址 所在的分包

    在分包后,通过查看代码依赖查看是否分包完成

    📌 注意事项

    1. 在配置好商品详情和商品列表的分包以后,需要更改页面中的跳转路径 !
    2. PS:可以利用项目全局搜索的功能,进行批量更改

    实现步骤:

    1. app.json 新增 subpackages 进行分包配置,新增 preloadRule 进行分包预下载配置
    2. subpackages 设置分包的 根目录 root 、别名 name 、页面路径 pages
    3. preloadRule 设置预下载。

    落地代码

    ➡️ app.json

    "subpackages": [
      {
        "root": "modules/settingModule",
        "name": "settingModule",
        "pages": [
          "pages/address/add/index",
          "pages/address/list/index",
          "pages/profile/profile"
        ]
      }
    ],
    "preloadRule": {
      "pages/settings/settings": {
        "network": "all",
        "packages": ["settingModule"]
      }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    08. 更新用户信息-渲染用户信息

    思路分析:

    点击个人中心的设置,然后点击修改个人资料,就可以对用户的头像和昵称进行修改

    在这个页面中,我们需要先渲染信息用户,用户信息目前是存储到 Store 中的,因此我们需要先从 Store 中取出用户信息的数据,进行渲染的渲染。

    让页面和 Store 数据建立关联,可以使用 mobx-miniprogram-bindings 提供的 BehaviorWithStore 方法

    实现步骤:

    1. 新建 behavior.js 文件,从 mobx-miniprogram-bindings 库中导入 BehaviorWithStore 方法
    2. BehaviorWithStore 方法中配置 storeBindings 配置项从 Store 中映射数据和方法
    3. Page 方法中导入创建的 behavior ,然后配置 behavior 属性,并使用导入的 behavior

    落地代码:

    // behavior.js
    
    import { BehaviorWithStore } from 'mobx-miniprogram-bindings'
    // 导入 store 对象
    import { userStore } from '../../stores/userstore'
    
    export const userBehavior = BehaviorWithStore({
      storeBindings: {
        store: userStore,
        fields: ['userInfo']
      }
    })
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    ➡️ modules/settingModule/pages/profile/profile.js

    import { userBehavior } from './behavior'
    
    Page({
        
      behaviors: [userBehavior],
        
      // 页面的初始数据
      data: {
        isShowPopup: false // 控制更新用户昵称的弹框显示与否
      },
    
      // 其他代码略...
    })
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    ➡️ modules/settingModules/pages/profile/profile.wxml

    <view class="container">
    
      <view class="setting-list avatar-container">
        <text>头像text>
        <view class="avatar">
          <button hover-class="none">
            <image src="{{ userInfo.headimgurl }}" mode="" />
          button>
        view>
      view>
    
      <view class="setting-list nickname">
        <text>昵称text>
        <text>{{ userInfo.nickname }}text>
      view>
    
      
      
    view>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    09. 更新用户信息-获取头像临时路径

    思路分析:

    当用户点击头像时,可以对头像进行更新操作,我们使用通过微信提供的头像昵称填写能力快速完善

    如果需要使用小程序提供的头像填写能力,需要两步:

    1. button 组件 open-type 的值设置为 chooseAvatar
    2. 当用户选择需要使用的头像之后,可以通过 bindchooseavatar 事件回调获取到头像信息的临时路径

    实现步骤:

    1. button 按钮绑定 open-type 属性,值为 chooseAvatar
    2. 用户点击了头像后,在 bindchooseavatar 事件回调获取到头像信息的临时路径

    落地代码:

    ➡️ modules/settingModules/pages/profile/profile.wxml

    <view class="avatar">
      <button
        class="avatar-btn"
        hover-class="none"
    +     open-type="chooseAvatar"
    +     bindchooseavatar="chooseAvatar"
      >
        <image src="{{ userInfo.headimgurl || '/assets/images/avatar.png' }}" />
      button>
    view>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    ➡️ modules/settingModules/pages/profile/profile.js

    // pages/profile/profile.js
    import { userBehavior } from './behavior'
    
    Page({
      // 注册 behavior
      behaviors: [userBehavior],
    
      // 页面的初始数据
      data: {
        isShowPopup: false // 控制更新用户昵称的弹框显示与否
      },
    
    +   // 更新用户头像
    +   chooseAvatar(event) {
    +     // console.log(event)
    + 
    +     // 获取头像的临时路径
    +     // 临时路径具有失效时间,需要将临时路径上传到公司的服务器,获取永久的路径
    +     // 在获取永久路径以后,需要使用永久路径更新 headimgurl
    +     // 用户点击 保存按钮,才算真正的更新了头像和昵称
    +     const { avatarUrl } = event.detail
    + 
    +     this.setData({
    +       'userInfo.headimgurl': avatarUrl
    +     })
    +   },
    
      // 略....
    })
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    10. 更新用户信息-头像上传到服务器

    思路分析:

    通过 bindchooseavatar 事件回调获取到头像信息的临时路径。

    当临时文件超过一定的容量的时候,小程序就会将临时文件清理掉,也就是说临时文件可能会随时失效,为了解决这个问题,我们需要将获取到头像信息的临时路径上传到自己的服务器。如果需要将本地资源上传到服务器,需要使用到小程序提供的 API 方法: wx.uploadFile ,语法如下:

    wx.uploadFile({
      url: '开发者服务器地址',
      filePath: '要上传文件资源的路径 (本地路径)',
      name: '文件对应的 key',
      header: 'HTTP 请求 Header',
      // 接口调用成功的回调函数
      success: (res) => {},
      // 接口调用失败的回调函数
      fail: (err) => {}
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    实现步骤:

    1. 在获取到用户的临时头像路径以后,调用 wx.uploadFile() 方法,同时设置好基本的参数,
    2. 在上传成功后,获取到服务器返回的永久地址
    3. 将地址赋值给 data 中的数据

    落地代码:

    ➡️ modules/settingModules/pages/profile/profile.js

    // 获取用户头像信息
    getAvatar(e) {
    
      // 获取选中的头像
      const { avatarUrl } = e.detail
    
      wx.uploadFile({
        url: 'https://gmall-prod.atguigu.cn/mall-api/fileUpload',
        filePath: avatarUrl,
        name: 'file',
        header: {
          token: wx.getStorageSync('token'),
        },
        success: (res) => {
          // 将获取到的头像赋值给 data 中变量同步给页面结构
          const uploadRes = JSON.parse(res.data)
          this.setData({
            'userInfo.headimgurl': uploadRes.data
          })
        },
        fail(err) {
          wx.showToast({
            title: '头像更新失败,请稍后再试',
            icon: 'none'
          })
        }
      })
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    11. 更新用户信息-完成头像更新

    思路分析:

    当用户点击保存时,就需要实现头像的更新功能,既然需要同步到服务器,依然需要调用接口

    首先熟悉接口文档:更新用户信息

    熟悉了接口文档以后,根据接口文档封装接口 API 函数,点击保存的时候调用接口函数,然后将最新的用户信息同步到服务器。

    在同步到服务器以后,我们需要将用户信息存储到本地同时同步到 Store

    实现步骤:

    1. /api/user.js 文件中根据接口文档,创建获取用户信息的 API 函数 reqUpdateUserInfo
    2. 给修改个人资料的保存按钮绑定点击事件,触发 updateUserInfo 回调函数
    3. 在回调函数中调用接口 API 函数 reqUpdateUserInfo ,同时传入用户的信息
    4. 更新用户信息以后,将用户信息存储到本地同时同步到 Store

    落地代码:

    ➡️/api/user.js

    import http from '../utils/http'
    
    /**
     * @description 更新用户信息
     * @param {*} updateUserVo 用户头像和用户昵称
     */
    export const reqUpdateUserInfo = (updateUser) => {
      return http.post('/mall-api/weixin/updateUser', updateUser)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    ➡️ modules/settingModule/pages/profile/profile.js

    // pages/profile/profile.js
    import { reqUpdateUserInfo, reqUserInfo } from '../../../../api/user'
    
    Page({
    
      // coding...
    
      // 更新用户信息
      async updateUserInfo() {
        // 调用 API,更新用户信息
        await reqUpdateUserInfo(this.data.userInfo)
    
        // 将用户信息存储到本地
        wx.setStorageSync('userInfo', this.data.userInfo)
    
        // 将用户信息存储到 Store
        this.setUserInfo(this.data.userInfo)
    
        // 给用户提示头像更新成功
        wx.showToast({
          title: '头像更新成功',
          icon: 'none'
        })
      }
    
     
      // coding...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    12. 更新用户信息-更新用户昵称

    思路分析:

    在这一节,我们需要实现将用户昵称更改的功能

    更新用户昵称的接口和更新用户头像的接口是同一个,因此不需要再次封装,直接复用即可

    当点击更新用户昵称时,弹出弹框,当用户将在输入框光标聚焦到输入框时,可以通过两种方式更新用户昵称操作

    1. 使用微信昵称
    2. 用户输入最新的昵称

    当用户提交表单时,我们将最新的昵称,同步到 userInfonickname字段中

    当用户点击了确定以后,我们将新的的用户信息赋值给 data 中的 userInfo 字段

    当用户点击保存时,更新用户信息

    实现步骤:

    1. form 表单绑定 bindsubmit 事件,用来获取输入框最新的值
    2. input 组件绑定 type 属性,属性值为 nickname,获取微信昵称
    3. input 组件绑定 bindinput 事件,获取用户输入最新的昵称
    4. formType 设置为 submit 当用户点击确定后,触发 form 表单的 bindsubmit 事件
    5. form 表单的 bindsubmit 事件中进行赋值
    6. form 表单的取消按钮绑定事件,取消弹框

    落地代码:

    ➡️ modules/settingModule/pages/profile/profile.wxml

    <van-dialog
      custom-style="position: relative"
      use-slot
      title="修改昵称"
      show="{{ isShowPopup }}"
      showConfirmButton="{{ false }}"
      showCancelButton="{{ false }}"
      transition="fade"
    >
    +   <form bindsubmit="getNewName">
        
        <input
          class="input-name"
    +       type="nickname"
    +       bindinput="getNewName"
          name="nickname"
          value="{{ userInfo.nickname }}"
        />
        <view class="dialog-content">
    +       <button class="cancel" bindtap="cancelForm">取消button>
    +       
    +       <button class="confirm" type="primary" formType="submit">确定button>
        view>
      form>
    van-dialog>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    ➡️ modules/settingModule/pages/profile/profile.js

    import { reqUpdateUserInfo, reqUserInfo } from '../../../../api/user'
    import { createStoreBindings } from 'mobx-miniprogram-bindings'
    import store from '../../../../stores/index'
    
    Page({
      // 页面的初始数据
      data: {
        avatarUrl: '/static/images/avatar.png',
        isShowPopup: false,
        userInfo: {
          nickname: '',
          headimgurl: ''
        }
      },
    
      // 生命周期函数--监听页面加载
      onLoad(options) {
        createStoreBindings(this, {
          store,
          fields: ['userInfo'],
          actions: ['setUserInfo']
        })
      },
    
      getAvatar(e) {
        // coding...
      },
    
      // 更新用户信息
      async updateUserInfo() {
        // coding...
      },
    
      // 显示修改昵称弹框
      onUpdateNickName() {
        this.setData({
          isShowPopup: true
        })
      },
    
      // 获取最新的用户昵称
      getNewName(e) {
        // 获取用户输入的最新的昵称
        const { nickname } = e.detail.value
    
        this.setData({
          'userInfo.nickname': nickname,
          isShowPopup: false
        })
      },
    
      // 取消更新用户昵称
      cancelForm() {
        this.setData({
          isShowPopup: false
        })
      }
    })
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
  • 相关阅读:
    RabbitMQ 入门系列:4、基础编码:官方SDK的引用、链接创建、单例改造、发送消息、接收消息。
    3.2 网络协议
    MySQL8.0忘记密码
    string和stringbuilder
    单词规律(C++解法)
    Structured Streaming
    爬虫逆向实战(31)-某花顺行情中心(cookie、补环境)
    iwebsec靶场 文件包含漏洞通关笔记8-php://input伪协议利用
    【证明】若向量组线性相关,则向量组的线性映射也线性相关
    SAS 字符串函数-SCAN
  • 原文地址:https://blog.csdn.net/qq_63358859/article/details/136364109