阅读视图

发现新文章,点击刷新页面。

【uniapp】小程序实现自由控制组件JSON文件配置

前言

最近在 uniapp ask社区 回答问题,不少开发者都咨询到了如何配置 组件 生成的 json文件 这个问题,在经过跟同事的交流、自己的实践以及开发者的反馈后,我整理了下面的解决思路和方案。

前置知识

uniapp 编译到 小程序,一个 vue 组件编译结束之后会生成四个文件,以微信小程序举例

image.png

生成的 json文件 的内容存储着小程序页面或组件相关的配置,必不可少

方案一 脚本

这个思路是在框架打包结束之后通过 nodejs 或者 shell 去修改产物

以占位组件为例,做分包异步化降低主包体积不可或缺的一个配置项

image.png

开发者只需要事先统计好需要配置的 componentPlaceholder 和 产物路径,在打包结束之后通过脚本把内容写入到对应的 json文件 就可以了

这种思路适合 cli项目,可以很轻松把脚本添加到 package.json 中的 scripts 中,并且不受 nodejs 版本限制;但是有些开发者的项目是 hx项目,就不能通过脚本的形式来操作了。

方案二 插件

这个思路是通过 webpack 或者 vite 插件来解决相关问题

我们以我写的 vite 插件 为例 (github 地址 github.com/uni-toolkit…

插件源码很简单,五十多行代码

import { getOutputJsonPath, isMiniProgram } from '@uni_toolkit/shared';
import type { PluginOption } from 'vite';
import { createFilter, type FilterPattern } from '@rollup/pluginutils';
import path from 'node:path';
import fs from 'node:fs';
import { parseJson } from '@dcloudio/uni-cli-shared';
import { merge } from 'lodash-es';

export interface ComponentConfigPluginOptions {
  include?: FilterPattern;
  exclude?: FilterPattern;
}

export default function vitePluginComponentConfig(
  options: ComponentConfigPluginOptions = {
    include: ['**/*.{vue,nvue,uvue}'],
    exclude: [],
  },
): PluginOption {
  const map: Map<string, Record<string, any>> = new Map();
  return {
    name: 'vite-plugin-component-config',
    enforce: 'pre',
    transform(code, id) {
      if (!isMiniProgram()) {
        return;
      }
      if (!createFilter(options.include, options.exclude)(id)) {
        return;
      }
      const matches = code.match(/<component-config>([\s\S]*?)<\/component-config>/g);
      if (!matches) {
        return;
      }

      matches.forEach((match) => {
        const content = match.replace(/<component-config>|<\/component-config>/g, '');
        const componentConfig = parseJson(content.toString(), true, path.basename(id));
        map.set(getOutputJsonPath(id), componentConfig);
      });

      return code.replace(/<component-config>[\s\S]*?<\/component-config>/g, '');
    },
    closeBundle() {
      if (map.size === 0) {
        return;
      }
      for (const [outputPath, config] of map) {
        if (!fs.existsSync(outputPath)) {
          continue;
        }
        const content = fs.readFileSync(outputPath, 'utf-8');
        const json = JSON.parse(content);
        fs.writeFileSync(outputPath, JSON.stringify(merge(json, config), null, 2));
      }
    },
  };
}

思路就是需要开发者在具体的 vue文件 中添加一个 component-config 代码块,类如

// #ifdef MP
<component-config>
{
  "usingComponents": {
    "custom-button": "/components/custom-button"
  },
  "styleIsolation": "apply-shared",
  "componentPlaceholder": {  
    "test": "view",  
  }  
}
</component-config>
// #endif

在编译期间,会通过正则表达式提取 component-config 代码块中的配置,存储到 hashMap 中,在 bundle 生成结束后遍历 hashMap 中的数据,然后修改对应路径的 json文件

同时还考虑到有些开发者会针对不同的小程序平台添加不同的配置,component-config 代码块中的内容也支持 条件编译

如果你是 vue2 项目,可以使用这个插件 github 地址 github.com/uni-toolkit…

结语

如果这些插件帮助到了你,可以点个 star✨ 支持一下开源工作。

如果你有什么好的想法或者建议,欢迎在 github.com/uni-toolkit… 提 issue 或者 pr;也可以加我的 微信 13460036576 沟通。

Uniapp如何下载图片到本地相册

uniapp如何下载图片到本地相册?

在一些特定的情况下面,我们需要在uniapp开发的小程序中将图片保存到本地相册,比如壁纸小程序其他小程序,这个使用情况还是十分普遍的,现在我来分享一下我的实现方法和思路

实现方案

文档地址: saveImageToPhotosAlbum:uniapp.dcloud.net.cn/api/media/i… getImageInfo: uniapp.dcloud.net.cn/api/media/i…

我们通过查找uniapp官方文档可以发现里面有一个uni.saveImageToPhotosAlbum({})保存图片到系统相册的API接口可以让我们使用,其中最关键的就是filePath参数,这个参数不支持网络地址就是我们服务器返回的图片地址不可以使用

所以我们需要使用另外一个API接口来帮助我们生成一个临时的filePath路径这个api就是uni.getImageInfo 使用这个api就可以将我们接口返回的网络地址生成一个临时的file地址,这样我就可以配合uni.saveImageToPhotosAlbum({})来实现图片保存到本地相册的功能了

实例代码:

uni.getImageInfo({
src: currentInfo.value.picurl,
success: (res) => {
uni.saveImageToPhotosAlbum({
filePath: res.path,
success: (fileRes) => {
console.log(fileRes, "图片");
}
})
}
})

需要注意的问题

我们在小程序实现下载功能的时候我们还需要到小程序的配置当中将downloadFile合法域名行一个配置不然是无法完成下载的,同时还需要在小程序后台配置中进行一个授权不然也是无法实现保存到微信相册的。

1.downloadFile合法域名配置步骤

进入到小程序配置信息页面 点击开发管理 同时在显示中的页面里面下滑到服务器域名位置 可以看见downloadFile合法域名的位置信息 点击右上角修改 然后将我们的downloadFile域名添加就可以了

image.png

image.png

2. 进行授权配置

进入小程序后台设置 鼠标移入到头像上 根据你的小程序信息进行一个填写和备案 后面找到服务内容声明用户隐私保护指引 进入到里面根据信息提示就可以完成下载图片并且保存到手机本地相册的功能了!

一文读懂 Uniapp 小程序登录流程

一、微信小程序登录原理

登录的标准流程如下:

步骤 动作 说明
1 小程序端调用 uni.login() 获取 code(临时登录凭证)
2 小程序端把 code 发给自己的服务器 通常是 /api/login
3 服务器请求微信接口 https://api.weixin.qq.com/sns/jscode2session 用 appid + secret + code 换取 openid 和 session_key
4 服务器生成自己的 token 返回前端 对应平台用户身份
5 小程序保存 token 并登录成功 下次启动可直接使用

二、前端开发(UniApp + Vue3)

登录页面代码

/pages/login/login.vue

<template>
  <view class="container">
    <view class="title">欢迎使用小程序</view>
    <button @click="handleLogin" class="login-btn">微信一键登录</button>
  </view>
</template>

<script setup>
import { ref } from 'vue'

const token = ref('')
const user = ref({})

// 微信登录
const handleLogin = async () => {
  try {
    // 1. 获取 code
    const { code } = await new Promise((resolve, reject) => {
      uni.login({
        provider: 'weixin',
        success: res => resolve(res),
        fail: err => reject(err)
      })
    })
    console.log('小程序登录凭证 code:', code)

    // 2. 发送到后端
    const [err, res] = await uni.request({
      url: 'http://localhost:3000/api/login', // 后端接口地址
      method: 'POST',
      data: { code }
    })
    if (err) throw new Error('请求失败')

    // 3. 处理后端返回数据
    token.value = res.data.token
    user.value = res.data.user

    uni.setStorageSync('token', token.value)
    uni.setStorageSync('userInfo', user.value)

    uni.showToast({ title: '登录成功', icon: 'success' })
    console.log('登录结果:', res.data)
  } catch (e) {
    console.error(e)
    uni.showToast({ title: '登录失败', icon: 'none' })
  }
}
</script>

<style>
.container {
  margin-top: 200rpx;
  text-align: center;
}
.title {
  font-size: 40rpx;
  margin-bottom: 80rpx;
}
.login-btn {
  background-color: #07c160;
  color: #fff;
  width: 80%;
  border-radius: 12rpx;
}
</style>

✅ 点击按钮会自动执行微信登录流程。


三、后端实现(Node.js)

1️⃣ 环境搭建

创建一个 server 文件夹,执行命令:

npm init -y
npm install express axios jsonwebtoken cors

2️⃣ 创建 server.js

const express = require('express')
const axios = require('axios')
const jwt = require('jsonwebtoken')
const cors = require('cors')

const app = express()
app.use(cors())
app.use(express.json())

// 你的微信小程序信息
const APPID = '你的小程序AppID'
const SECRET = '你的小程序AppSecret'

// token密钥
const JWT_SECRET = 'my_secret_key'

// 模拟数据库
const users = {}

// 登录接口
app.post('/api/login', async (req, res) => {
  const { code } = req.body
  if (!code) return res.status(400).json({ message: '缺少code' })

  try {
    // 请求微信API换取openid和session_key
    const response = await axios.get(
      `https://api.weixin.qq.com/sns/jscode2session`, {
        params: {
          appid: APPID,
          secret: SECRET,
          js_code: code,
          grant_type: 'authorization_code'
        }
      }
    )

    const { openid, session_key, errcode, errmsg } = response.data
    if (errcode) {
      return res.status(400).json({ message: '微信登录失败: ' + errmsg })
    }

    console.log('用户openid:', openid)

    // 模拟创建/更新用户
    if (!users[openid]) {
      users[openid] = { openid, createTime: new Date() }
    }

    // 生成自定义 token
    const token = jwt.sign({ openid }, JWT_SECRET, { expiresIn: '7d' })

    return res.json({
      token,
      user: users[openid]
    })
  } catch (err) {
    console.error(err)
    res.status(500).json({ message: '服务器错误' })
  }
})

// 验证 token 接口(示例)
app.get('/api/profile', (req, res) => {
  const auth = req.headers.authorization
  if (!auth) return res.status(401).json({ message: '请先登录' })

  try {
    const decoded = jwt.verify(auth.replace('Bearer ', ''), JWT_SECRET)
    res.json({ user: users[decoded.openid] })
  } catch {
    res.status(401).json({ message: 'token无效' })
  }
})

// 启动服务器
app.listen(3000, () => {
  console.log('✅ Server running on http://localhost:3000')
})

✅ 启动命令:

node server.js

四、运行测试

  1. 启动后端:

    node server.js
    
  2. 打开 HBuilderX → 运行 → 运行到微信开发者工具

  3. 点击 “一键登录”,查看控制台输出

    • 小程序端日志会打印 code
    • 后端会打印 openid
  4. Toast 提示 “登录成功” ✅


五、持久化登录

登录成功后:

  • 将 token 存到 uni.setStorageSync('token', token)
  • 下次启动时判断本地是否有 token,有则不再重复登录。
// 在 App.vue 的 onLaunch 中
onLaunch() {
  const token = uni.getStorageSync('token')
  if (token) {
    console.log('用户已登录:', token)
  } else {
    uni.reLaunch({ url: '/pages/login/login' })
  }
}

六、重点总结

模块 工具 功能
前端 uni.login() 获取 code
前端 uni.request() 调后端登录接口
后端 axios 请求微信接口 用 code 换 openid
后端 jsonwebtoken 生成自定义 token
前端 uni.setStorageSync 保存 token

✅ 最终效果:

  • 点击登录按钮 → 自动通过微信授权登录
  • 后端生成 token 并返回
  • 前端保存登录状态
  • 可扩展为用户注册、绑定手机号等功能。
❌