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

01. 用户登录-什么是 token

什么是 Token

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

**Token的具体流程 **

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

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

业务介绍:

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

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

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

小程序登录图示:


登录流程说明:

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

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

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

  3. 开发者的后台接收 临时登录凭证code ,同时在微信公众后台拿到 AppId 和 AppSecret ,向微信服务器发送请求,

    请求参数合法的话,微信服务器会给开发者后台返回 openid(微信用户的唯一标识) 以及 session_key(会话密钥) 等

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

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

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

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

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

  6. 客户端每次向开发者后台发送请求的时候,需要携带自定义登录态 Token ,开发者后台收到请求后,对 Token 进行验证识别用户身份,同时拿自定义登录态 Token 查询 openid 和 session_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

js 复制代码
import http from '../utils/http'

/**
 * @description 授权登录
 * @param {*} code 临时登录凭证code
 * @returns Promise
 */
export const reqLogin = (code) => {
  return http.get(`/mall-api/weixin/wxLogin/${code}`)
}

➡️ /pages/login/login.js

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: '授权失败,请稍后再试~~~' })
        }
      }
    })
  }
})

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

shell 复制代码
npm i mobx-miniprogram mobx-miniprogram-bindings

➡️ /store/index.js

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
  })
})

➡️ /pages/login/login.js

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: '授权失败,请重新授权' })
          }
        }
      })
    }
+   }
})

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

js 复制代码
/**
 * @description 获取用户信息
 * @returns Promise
 */
export const reqUserInfo = () => {
  return http.get(`/mall-api/weixin/getuserInfo`)
}

➡️ /store/userstore.js

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
+   })
})

➡️/pages/login/login.js

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)
    }
  }
})

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

思路分析:

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

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

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

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

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

实现步骤:

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

落地代码:

➡️/pages/info/info.js

js 复制代码
+ import { ComponentWithStore } from 'mobx-miniprogram-bindings'

+ ComponentWithStore({
    
+   storeBindings: {
+     store: userStore,
+     fields: ['token', 'userInfo']
+   }

})

➡️/pages/info/info.wxml

html 复制代码
<!--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">
      <!-- coding... -->
    </view>

    <!-- 底部面板 -->
    <view class="info-footer">
      尚硅谷技术支持
    </view>
  </view>
</view>

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

思路分析:

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

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

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

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

📌 注意事项:

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

实现步骤:

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

落地代码:

➡️ app.json

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"]
  }
}

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

思路分析:

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

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

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

实现步骤:

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

落地代码:

js 复制代码
// behavior.js

import { BehaviorWithStore } from 'mobx-miniprogram-bindings'
// 导入 store 对象
import { userStore } from '../../stores/userstore'

export const userBehavior = BehaviorWithStore({
  storeBindings: {
    store: userStore,
    fields: ['userInfo']
  }
})

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

js 复制代码
import { userBehavior } from './behavior'

Page({
    
  behaviors: [userBehavior],
    
  // 页面的初始数据
  data: {
    isShowPopup: false // 控制更新用户昵称的弹框显示与否
  },

  // 其他代码略...
})

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

html 复制代码
<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>

  
  <!-- coding... -->
</view>

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

思路分析:

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

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

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

实现步骤:

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

落地代码:

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

html 复制代码
<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>

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

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
+     })
+   },

  // 略....
})

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

思路分析:

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

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

js 复制代码
wx.uploadFile({
  url: '开发者服务器地址',
  filePath: '要上传文件资源的路径 (本地路径)',
  name: '文件对应的 key',
  header: 'HTTP 请求 Header',
  // 接口调用成功的回调函数
  success: (res) => {},
  // 接口调用失败的回调函数
  fail: (err) => {}
})

实现步骤:

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

落地代码:

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

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'
      })
    }
  })

}

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

思路分析:

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

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

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

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

实现步骤:

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

落地代码:

➡️/api/user.js

js 复制代码
import http from '../utils/http'

/**
 * @description 更新用户信息
 * @param {*} updateUserVo 用户头像和用户昵称
 */
export const reqUpdateUserInfo = (updateUser) => {
  return http.post('/mall-api/weixin/updateUser', updateUser)
}

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

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...
}

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

思路分析:

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

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

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

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

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

当用户点击了确定以后,我们将新的的用户信息赋值给 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

html 复制代码
<van-dialog
  custom-style="position: relative"
  use-slot
  title="修改昵称"
  show="{{ isShowPopup }}"
  showConfirmButton="{{ false }}"
  showCancelButton="{{ false }}"
  transition="fade"
>
+   <form bindsubmit="getNewName">
    <!-- type 设置为 nickname 是为了获取微信昵称 -->
    <input
      class="input-name"
+       type="nickname"
+       bindinput="getNewName"
      name="nickname"
      value="{{ userInfo.nickname }}"
    />
    <view class="dialog-content">
+       <button class="cancel" bindtap="cancelForm">取消</button>
+       <!-- 将 formType 设置为 submit 当用户点击确定后,触发 form 表单的 bindsubmit 事件 -->
+       <button class="confirm" type="primary" formType="submit">确定</button>
    </view>
  </form>
</van-dialog>

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

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
    })
  }
})
相关推荐
派小心.9 小时前
小程序分享链路中来源参数的传递校验
大数据·前端·数据库·人工智能·小程序·数据分析
一木 之林13 小时前
微信小程序开发全攻略·文章版|00 总览:74集学习路径与知识地图
人工智能·学习·计算机视觉·微信小程序·小程序
m0_5873830016 小时前
无人自助拼豆系统的全栈开发方案
java·后端·struts·小程序·架构
AI源码16 小时前
雷山苗韵 - 非物质文化遗产传承平台
小程序·非遗小程序
CRMEB系统商城16 小时前
CRMEB开源商城系统(PHP)v8.0,打造全新AI二开商城底座!
开发语言·人工智能·小程序·开源·php
一木 之林16 小时前
微信小程序开发全攻略·文章版|01 入门与环境搭建
人工智能·学习·计算机视觉·微信小程序·notepad++
StevenLdh17 小时前
第八期 · 情绪闯关挑战盒:一个「无惩罚」成就系统的数据建模
java·微信小程序
眨眼猫会务智能体18 小时前
眨眼猫会务智能体会务系统的服务响应怎么样?出问题多久有人接?
安全·小程序·会务
微订校园外卖平台18 小时前
校园跑腿小程序上线:四端架构与校园外卖系统履约链路拆解
小程序·架构·外卖系统·本地生活·微订