MBTI 性格测试小程序实战

ops/2025/1/16 4:43:48/

MBTI 性格测试应用介绍

参考项目:16Personalities(https://www.16personalities.com/ch)
image.png
image.png
image.png
image.png

MBTI 实现方案介绍

核心组成:

  • 题目
  • 用户答案
  • 评分规则
题目结构

暂时使用JSON,便于理解,result代表题目对应的结果

[{"title": "你通常更喜欢","options": [{"result": "I","value": "独自工作","key": "A"},{"result": "E","value": "与他人合作","key": "B"}]}
]

优点:灵活、容易排序
相比于用选项作为key,结构更清晰,更易于理解和扩展前后端都可声明类型;缺点是占用空间(可以进行预处理)

{"title": "题目","a": "结果1","b": "结果2","c": "结果3"
}

用户答案结构

用户提交答案的时候,进需要传递一个数组,数组内是选项:["A","B"],按数组顺序匹配对应的题目。
优点:相较于直接将答案放到题目当中一起提交,数组不用再完整的传递题目结构,节省传输体积,提高性能。

["A","A","A","B","A","A","A","B","B","A"]

评分规则

MBTI 评分原理

迈尔斯-布里格斯性格分类法

迈尔斯-布里格斯类型指标(英语:Myers-Briggs Type Indicator,简称MBTI,或译麦布二氏心理类型量表)是一种人格类型的评量工具,由荣格的类型理论发展而来,它表明人们天生在感知和决策的方式上存在不同心理偏好。其理论中最浅显的部分是四组相反的先天偏好:内向与外向(Introversion-Extraversion[i])、实感与直觉(Sensing-iNtuition)、思考与情感(Thinking-Feeling)、判断与感知(Judging-Perceiving),四项偏好可组成16种稳定的人格类型。该指标旨在让健康个体理解自己和彼此的认知与决策倾向,并不反映能力或品格。
MBTI是由两名美国人——凯瑟琳·库克·布里格斯和她的女儿伊莎贝尔·布里格斯·迈尔斯所建构,最早于1944年发表。

MBTI将心理差异分类为4个对立的组合(或称“二分法”),一个人在每个组合中各拥有1个偏好:

  • 内向与外向(I/E)
  • 实感与直觉(S/N)
  • 思考与情感(T/F)
  • 判断与感知(J/P)

四个字母的组合遵循E/I、S/N、T/F、J/P的顺序,由此产生了16种可能的字母组合,如ESTJ、ISFP、INFJ、ENTP等16种独特的类型。在MBTI的理论中,“类型”表达的讯息量不只是“4个偏好”,它代表了功能(S、N、T、F)、能量态度(E、I)以及对外界的态度(J、P)之间的一组复杂的动态关系。

image.png
每道题目都是四个组合的其中之一设定,为了判断找个人属于组合里的哪个偏好。
如,为了判断是I人还是E人(result字段):

[{"title": "你通常更喜欢","options": [{"result": "I","value": "独自工作","key": "A"},{"result": "E","value": "与他人合作","key": "B"}]}
]

按照这个思路,可以统计题目中所有的偏好,比如答完题目,统计一共选了10个I,2个E,很容易判断答题者是I人,同理可判断其他型人格。
所以出题的时候,给每个选项的答案对应设置一个属性。如:

  • 第一题A对应I,B对应E
  • 第二题A对应E,B对应I
  • 第三题A对应S,B对应N
  • 第四题A对应T,B对应F
  • 第五题A对应P,B对应J

如果用户选择了[A,B,A,A,A],两个I,一个S,一个T,一个P,很明显是ISTP人格。

评分结果计算原理
  1. 创建一个评分结果集,预先创建包括MBTI的所有16中角色(人格)

image.png
题目评分结果对应的json结构:

[{"resultProp": ["I","S","T","J"],"resultDesc": "忠诚可靠,被公认为务实,注重细节。","resultPicture": "icon_url_istj","resultName": "ISTJ(物流师)"},{"resultProp": ["I","S","F","J"],"resultDesc": "善良贴心,以同情心和责任为特点。","resultPicture": "icon_url_isfj","resultName": "ISFJ(守护者)"}
]
  1. 如何计算结果

每个结果有一个resultProp字段,是一个元素不重复的数组(属性集合),里面的内容和题目选项的result字段匹配。

[{"title": "你通常更喜欢","options": [{"result": "I","value": "独自工作","key": "A"},{"result": "E","value": "与他人合作","key": "B"}]}
]

如果用户第一题选了A,对应的属性如果是I,那么遍历这16种结果,然后判断角色对应的resultProp里面是否包含I,包含则对应角色就 +1 分,不包含不得分。
最终遍历完所有题目后,可以得出16种结果中,哪个角色得分最高,即最终的评分结果。

MBTI 小程序 Demo 数据

题目列表

每个选项包含了对应的结果,questions.json:

[{"options": [{"result": "I","value": "独自工作","key": "A"},{"result": "E","value": "与他人合作","key": "B"}],"title": "你通常更喜欢"},{"options": [{"result": "J","value": "喜欢有明确的计划","key": "A"},{"result": "P","value": "更愿意随机应变","key": "B"}],"title": "当安排活动时"},{"options": [{"result": "T","value": "认为应该严格遵守","key": "A"},{"result": "F","value": "认为应灵活运用","key": "B"}],"title": "你如何看待规则"},{"options": [{"result": "E","value": "经常是说话的人","key": "A"},{"result": "I","value": "更倾向于倾听","key": "B"}],"title": "在社交场合中"},{"options": [{"result": "J","value": "先研究再行动","key": "A"},{"result": "P","value": "边做边学习","key": "B"}],"title": "面对新的挑战"},{"options": [{"result": "S","value": "注重细节和事实","key": "A"},{"result": "N","value": "注重概念和想象","key": "B"}],"title": "在日常生活中"},{"options": [{"result": "T","value": "更多基于逻辑分析","key": "A"},{"result": "F","value": "更多基于个人情感","key": "B"}],"title": "做决定时"},{"options": [{"result": "S","value": "喜欢有结构和常规","key": "A"},{"result": "N","value": "喜欢自由和灵活性","key": "B"}],"title": "对于日常安排"},{"options": [{"result": "P","value": "首先考虑可能性","key": "A"},{"result": "J","value": "首先考虑后果","key": "B"}],"title": "当遇到问题时"},{"options": [{"result": "T","value": "时间是一种宝贵的资源","key": "A"},{"result": "F","value": "时间是相对灵活的概念","key": "B"}],"title": "你如何看待时间"}
]

题目结果表

question_results.json

[{"resultProp": ["I","S","T","J"],"resultDesc": "忠诚可靠,被公认为务实,注重细节。","resultPicture": "icon_url_istj","resultName": "ISTJ(物流师)"},{"resultProp": ["I","S","F","J"],"resultDesc": "善良贴心,以同情心和责任为特点。","resultPicture": "icon_url_isfj","resultName": "ISFJ(守护者)"},{"resultProp": ["I","N","F","J"],"resultDesc": "理想主义者,有着深刻的洞察力,善于理解他人。","resultPicture": "icon_url_infj","resultName": "INFJ(占有者)"},{"resultProp": ["I","N","T","J"],"resultDesc": "独立思考者,善于规划和实现目标,理性而果断。","resultPicture": "icon_url_intj","resultName": "INTJ(设计师)"},{"resultProp": ["I","S","T","P"],"resultDesc": "冷静自持,善于解决问题,擅长实践技能。","resultPicture": "icon_url_istp","resultName": "ISTP(运动员)"},{"resultProp": ["I","S","F","P"],"resultDesc": "具有艺术感和敏感性,珍视个人空间和自由。","resultPicture": "icon_url_isfp","resultName": "ISFP(艺术家)"},{"resultProp": ["I","N","F","P"],"resultDesc": "理想主义者,富有创造力,以同情心和理解他人著称。","resultPicture": "icon_url_infp","resultName": "INFP(治愈者)"},{"resultProp": ["I","N","T","P"],"resultDesc": "思维清晰,探索精神,独立思考且理性。","resultPicture": "icon_url_intp","resultName": "INTP(学者)"},{"resultProp": ["E","S","T","P"],"resultDesc": "敢于冒险,乐于冒险,思维敏捷,行动果断。","resultPicture": "icon_url_estp","resultName": "ESTP(拓荒者)"},{"resultProp": ["E","S","F","P"],"resultDesc": "热情开朗,善于社交,热爱生活,乐于助人。","resultPicture": "icon_url_esfp","resultName": "ESFP(表演者)"},{"resultProp": ["E","N","F","P"],"resultDesc": "富有想象力,充满热情,善于激发他人的活力和潜力。","resultPicture": "icon_url_enfp","resultName": "ENFP(倡导者)"},{"resultProp": ["E","N","T","P"],"resultDesc": "充满创造力,善于辩论,挑战传统,喜欢探索新领域。","resultPicture": "icon_url_entp","resultName": "ENTP(发明家)"},{"resultProp": ["E","S","T","J"],"resultDesc": "务实果断,善于组织和管理,重视效率和目标。","resultPicture": "icon_url_estj","resultName": "ESTJ(主管)"},{"resultProp": ["E","S","F","J"],"resultDesc": "友善热心,以协调、耐心和关怀为特点,善于团队合作。","resultPicture": "icon_url_esfj","resultName": "ESFJ(尽责者)"},{"resultProp": ["E","N","F","J"],"resultDesc": "热情关爱,善于帮助他人,具有领导力和社交能力。","resultPicture": "icon_url_enfj","resultName": "ENFJ(教导着)"},{"resultProp": ["E","N","T","J"],"resultDesc": "果断自信,具有领导才能,善于规划和执行目标。","resultPicture": "icon_url_entj","resultName": "ENTJ(统帅)"}
]

其他资源

主页背景图片等资源,可以借助AI生成

Taro跨端小程序入门

为什么开发小程序
  • 基于微信生态,易于传播分享
  • 不用下载,直接打开使用即可

小程序开发和网页开发基本一致,都具有在线热更新、调试、版本兼容、打包上线。
小程序开发的真正痛点:可能有一些权限或者功能必须要企业号。

技术选型
  • Taro
  • Taro UI组件库
  • React
  • TypeScript

Taro官方文档:https://taro-docs.jd.com/docs/
做项目建议选用一个组件库,提升开发效率!
推荐使用与Taro官方框架兼容的组件库,否则容易出现跨端后样式丢失的问题。

  • taro-ui:https://taro-ui.jd.com/#/(推荐)
  • nut-ui
开发准备

微信开发者工具:https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html

入门指南

项目初始化

官方文档:https://taro-docs.jd.com/docs/GETTING-STARTED
Taro版本:这里选择3.x
node.js版本:>=16.20(我用的18.18.0)
npm版本:>=8(我用的9.8.1)
1)安装

# 使用 npm 安装 CLI
$ npm install -g @tarojs/cli# OR 使用 yarn 安装 CLI
$ yarn global add @tarojs/cli# OR 安装了 cnpm,使用 cnpm 安装 CLI
$ cnpm install -g @tarojs/cli

这样会默认安装最新的版本,我们可以指定版本安装(如果安装了最新版本,直接再次安装指定版本即可):

npm install -g @tarojs/cli@3.6.28

使用taro -v查看版本信息:
image.png
2)新建目录question-craft,初始化git项目
image.png
3)执行命令,初始化小程序项目

taro init mbti-test-mini

image.png

项目运行

使用WebStorm打开项目,进入终端执行npm install,发现依赖下载失败:

PS E:\E\IDEAWorkSpace\question-craft\mbti-test-mini> npm install
npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!                                           
npm ERR! While resolving: mbti-test-mini@1.0.0     
npm ERR! Found: react@18.2.0                       
npm ERR! node_modules/react
npm ERR!   react@"^18.0.0" from the root project
npm ERR!   peer react@">=16.13.0" from taro-ui@3.3.0
npm ERR!   node_modules/taro-ui
npm ERR!     taro-ui@"^3.2.1" from the root project
npm ERR!   2 more (@tarojs/taro-rn, react-native)
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer react@"^18.3.1" from react-dom@18.3.1
npm ERR! node_modules/react-dom
npm ERR!   react-dom@"^18.0.0" from the root project
npm ERR!   peer react-dom@">=16.13.0" from taro-ui@3.3.0
npm ERR!   node_modules/taro-ui
npm ERR!     taro-ui@"^3.2.1" from the root project
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
npm ERR!
npm ERR!
npm ERR! For a full report see:
npm ERR! C:\Users\ada\AppData\Local\npm-cache\_logs\2024-08-10T03_43_08_487Z-eresolve-report.txtnpm ERR! A complete log of this run can be found in: C:\Users\ada\AppData\Local\npm-cache\_logs\2024-08-10T03_43_08_487Z-debug-0.log
PS E:\E\IDEAWorkSpace\question-craft\mbti-test-mini>

可以查阅资料,或者问问AI,执行npm install --force,强制安装成功(不要使用魔法上网)
执行npm run dev:weapp,或者打开package.json文件,点击对应脚本运行:
image.png
dev:weapp:开发测试使用,即时编译,自动更新
build:weapp:打包上线使用,体积更小
运行之后使用微信开发者工具打开项目:
image.png
image.png

配置开发规范
  • eslint:代码规范
  • prettier:代码美化(格式)

image.png
image.png
eslint补充配置,关闭双引号校验:

{"extends": ["taro/react"],"rules": {"react/jsx-uses-react": "off","react/react-in-jsx-scope": "off","jsx-quotes": "off"}
}

image.png

测试组件引入

官网文档:https://taro-ui.jd.com/#/docs/quickstart
在src/app.ts中全局引入taro-ui:

import 'taro-ui/dist/style/index.scss' // 引入组件样式 - 方式一

随便找个组件复制进项目进行测试,查看是否成功引入。

开发示例页面
  1. 在全局配置文件src/app.config.ts,新增页面路由
  2. 复制已有页面,创建新页面
  3. 根据自己的需要,复制组件,拼出完整页面
  4. 按照需求,定制开发
  5. 页面跳转

MBTI 跨端小程序实战

全局规范和配置

遵循函数式组件写法:

export default () => {return (<View className="index"><Text>Hello world!</Text></View>);
};

修改应用标题src/app.config.ts:

export default defineAppConfig({pages: ['pages/index/index'],window: {backgroundTextStyle: 'light',navigationBarBackgroundColor: '#fff',navigationBarTitleText: 'MBTI 性格测试',navigationBarTextStyle: 'black'}
})

再将src/pages/index/index.config.ts下的标题注释掉:
相当于每个页面可以有自己的标题,在对应页面的.config.ts中声明即可,这里我们直接注释掉

export default definePageConfig({// navigationBarTitleText: '首页'
})

image.png

主页

效果图

image.png

主页src/pages/index/index.tsx
import { View, Image } from "@tarojs/components";
import { AtButton } from "taro-ui";
import headerBg from "../../assets/headerBg.png";
import "./index.scss";
import GlobalFooter from "../../components/GlobalFooter";/*** 主页*/
export default () => {return (<View className="indexPage"><View className="at-article__h1 title">MBTI 性格测试</View><View className="at-article__h2 subTitle">只需2分钟,就能“惊人般准确”地描述出你是谁,以及你为何以这样的方式行事。</View><AtButton type="primary" circle className="enterBtn">开始测试</AtButton><Image className="headerBg" src={headerBg} /><GlobalFooter /></View>);
};

主页样式src/pages/index/index.scss
.indexPage {background: #5DBFD8;.title {color: white;padding-top: 48px;text-align: center;}.subTitle {color: white;margin-top: 48px;}.enterBtn {margin-top: 150px;width: 60vw;}.headerBg {margin-top: 100px;height: 300px;}
}

全局底部栏组件src/components/GlobalFooter/index.tsx
import { View } from "@tarojs/components";
import "./index.scss";/*** 全局底部栏组件*/
export default () => {return <View className="globalFooter">作者:十六</View>;
};

全局底部栏组件样式src/components/GlobalFooter/index.scss
.globalFooter {position: fixed;bottom: 16px;left: 0;right: 0;text-align: center;
}

全局统一样式src/app.scss
.at-button--primary {background-color: dodgerblue;boilder-color: dodgerblue;
}

答题页面

效果图

image.png
开发步骤:

  1. 先写组件HTML(Radio组件)
  2. 再调整样式
  3. 最后写逻辑(上一题、下一题)
页面src/pages/doQuestion/index.tsx
import { View, Image } from "@tarojs/components";
import { AtButton } from "taro-ui";
import headerBg from "../../assets/headerBg.png";
import "./index.scss";
import questionResults from "../../data/question_results.json";
import GlobalFooter from "../../components/GlobalFooter";
import Taro from "@tarojs/taro";/*** 测试结果页面*/
export default () => {const result = questionResults[0];return (<View className="resultPage"><View className="at-article__h1 title">{result.resultName}</View><View className="at-article__h2 subTitle">{result.resultDesc}</View><AtButton type="primary" circle className="enterBtn" onClick={() => {// 关闭所有页面,打开到应用内的某个页面Taro.reLaunch({url: '/pages/index/index'})}}>返回主页</AtButton><Image className="headerBg" src={headerBg} /><GlobalFooter /></View>);
};

样式src/pages/doQuestion/index.scss
.doQuestionPage {.title {margin-bottom: 48px;}.options-wrapper {margin-bottom: 48px;}.controlBtn {margin: 24px 48px;}
}

结果页面

效果图

image.png

页面src/pages/result/index.tsx

使用Taro.reLaunch关闭所有页面,打开到应用内的某个页面,防止页面无限叠加

import { View, Image } from "@tarojs/components";
import { AtButton } from "taro-ui";
import headerBg from "../../assets/headerBg.png";
import "./index.scss";
import questionResults from "../../data/question_results.json";
import GlobalFooter from "../../components/GlobalFooter";
import Taro from "@tarojs/taro";/*** 测试结果页面*/
export default () => {const result = questionResults[0];return (<View className="resultPage"><View className="at-article__h1 title">{result.resultName}</View><View className="at-article__h2 subTitle">{result.resultDesc}</View><AtButton type="primary" circle className="enterBtn" onClick={() => {// 关闭所有页面,打开到应用内的某个页面Taro.reLaunch({url: '/pages/index/index'})}}>返回主页</AtButton><Image className="headerBg" src={headerBg} /><GlobalFooter /></View>);
};

样式src/pages/result/index.scss
.resultPage {background: #5DBFD8;.title {color: white;padding-top: 48px;text-align: center;}.subTitle {color: white;margin-top: 48px;}.enterBtn {margin-top: 150px;width: 60vw;}.headerBg {margin-top: 100px;height: 300px;}
}

页面配置src/pages/result/index.config.ts

设置页面标题

export default definePageConfig({navigationBarTitleText: '查看结果', // 设置页面标题
})

路由配置src/app.config.ts
export default defineAppConfig({pages: ['pages/index/index','pages/doQuestion/index','pages/result/index'],window: {backgroundTextStyle: 'light',navigationBarBackgroundColor: '#fff',navigationBarTitleText: 'MBTI 性格测试',navigationBarTextStyle: 'black'}
})

评分模块

CodeGeex生成对应评分算法代码

AI Prompt
请根据我下面的题目评分算法原理,帮我用 js 获取到得分最高的题目评分结果,要求算法清晰易懂,性能要求高,多补充一些注释。
用户提交的答案 answerList: [“A”]
题目列表 questions:

[{"title": "你通常更喜欢","options": [{"result": "I","value": "独自工作","key": "A"},{"result": "E","value": "与他人合作","key": "B"}]}
]

题目评分结果 question_results:

[{"resultProp": ["I","S","T","J"],"resultDesc": "忠诚可靠,被公认为务实,注重细节。","resultPicture": "icon_url_istj","resultName": "ISTJ(物流师)"},
]

评分原理:答案数组的每个元素和题目数组中每个元素的某个选项的key对应,从而获取到对应的 result 属性;题目评分结果的 resultProp 集合中如果包含该属性,就+1分,最后计算哪个评分结果(question_result)分数最高。
AI 结果
这个函数首先遍历题目列表和答案列表,统计每个选项的计数。然后遍历评分结果列表,计算每个评分结果的分数,最后返回最高分数和最高分数对应的评分结果。

function getMaxScore(answerList, questions, question_results) {// 初始化一个对象,用于存储每个选项的计数const optionCount = {};// 遍历题目列表for (const question of questions) {// 遍历答案列表for (const answer of answerList) {// 遍历题目中的选项for (const option of question.options) {// 如果答案和选项的key匹配if (option.key === answer) {// 获取选项的result属性const result = option.result;// 如果result属性不在optionCount中,初始化为0if (!optionCount[result]) {optionCount[result] = 0;}// 在optionCount中增加计数optionCount[result]++;}}}}// 初始化最高分数和最高分数对应的评分结果let maxScore = 0;let maxScoreResult = null;// 遍历评分结果列表for (const result of question_results) {// 计算当前评分结果的分数const score = result.resultProp.reduce((count, prop) => {return count + (optionCount[prop] || 0);}, 0);// 如果分数高于当前最高分数,更新最高分数和最高分数对应的评分结果if (score > maxScore) {maxScore = score;maxScoreResult = result;}}// 返回最高分数和最高分数对应的评分结果return maxScoreResult;
}const answerList = ["A"];
const questions = [{title: "你通常更喜欢",options: [{result: "I",value: "独自工作",key: "A",},{result: "E",value: "与他人合作",key: "B",},],},
];
const question_results = [{resultProp: ["I", "S", "T", "J"],resultDesc: "忠诚可靠,被公认为务实,注重细节。",resultPicture: "icon_url_istj",resultName: "ISTJ(物流师)",},
];console.log(getMaxScore(answerList, questions, question_results));

注意:AI结果不稳定,可以持续优化

代码整合

修改代码并新建src/utis/bitUtils.ts

/*** 获取最佳题目评分结果* @param answerList* @param questions* @param question_results*/
function getBestQuestionResult(answerList, questions, question_results) {// 初始化一个对象,用于存储每个选项的计数const optionCount = {};// 遍历题目列表for (const question of questions) {// 遍历答案列表for (const answer of answerList) {// 遍历题目中的选项for (const option of question.options) {// 如果答案和选项的key匹配if (option.key === answer) {// 获取选项的result属性const result = option.result;// 如果result属性不在optionCount中,初始化为0if (!optionCount[result]) {optionCount[result] = 0;}// 在optionCount中增加计数optionCount[result]++;}}}}// 初始化最高分数和最高分数对应的评分结果let maxScore = 0;let maxScoreResult = question_results[0];// 遍历评分结果列表for (const result of question_results) {// 计算当前评分结果的分数const score = result.resultProp.reduce((count, prop) => {return count + (optionCount[prop] || 0);}, 0);// 如果分数高于当前最高分数,更新最高分数和最高分数对应的评分结果if (score > maxScore) {maxScore = score;maxScoreResult = result;}}// 返回最高分数和最高分数对应的评分结果return maxScoreResult;
}const answerList = ["B","B","B","A"];
const questions = [{title: "你通常更喜欢",options: [{result: "I",value: "独自工作",key: "A",},{result: "E",value: "与他人合作",key: "B",},],},{options: [{result: "S",value: "喜欢有结构和常规",key: "A",},{result: "N",value: "喜欢自由和灵活性",key: "B",},],title: "对于日常安排",},{options: [{result: "P",value: "首先考虑可能性",key: "A",},{result: "J",value: "首先考虑后果",key: "B",},],title: "当遇到问题时",},{options: [{result: "T",value: "时间是一种宝贵的资源",key: "A",},{result: "F",value: "时间是相对灵活的概念",key: "B",},],title: "你如何看待时间",},
];
const question_results = [{resultProp: ["I", "S", "T", "J"],resultDesc: "忠诚可靠,被公认为务实,注重细节。",resultPicture: "icon_url_istj",resultName: "ISTJ(物流师)",},{resultProp: ["I", "S", "F", "J"],resultDesc: "善良贴心,以同情心和责任为特点。",resultPicture: "icon_url_isfj",resultName: "ISFJ(守护者)",},
];console.log(getBestQuestionResult(answerList, questions, question_results));

可以修改测试用例,进入\src\utis目录终端进行测试node .\bizUtils.ts
image.png
导出函数,以便外部引用(src/utis/bitUtils.ts):

export function getBestQuestionResult(answerList, questions, question_results) {

页面间数据传递

需求:题目结果页面需要得到做题页面用户选择的答案列表,才能进行评分。

  • 方法 1:url params
    • https://taro-docs.jd.com/docs/apis/route/navigateTo
    • 比如:result?answerList=[A,B,C]
  • 方法 2:全局状态
    • https://taro-docs.jd.com/docs/context#contextprovider
  • 方法 3:本地数据存储(推荐,较为简单)
    • https://taro-docs.jd.com/docs/apis/storage/setStorageSync
做题页面传递数据src/pages/doQuestion/index.tsx
      {current == questions.length && (<AtButtontype="primary"circleclassName="controlBtn"disabled={!currentAnswer}onClick={() => {// 传递答案列表Taro.setStorage({key:"answerList",data:answerList});// 跳转结果页面Taro.navigateTo({url: "/pages/result/index",});}}>查看结果</AtButton>)}

结果页面使用数据src/pages/result/index.tsx
  // 获取从答题页面传递过来的答案列表const answerList = Taro.getStorageSync("answerList");if (!answerList || answerList.length < 0) {Taro.showToast({title: "答案为空!",icon: "error",duration: 2000});}// 根据答案列表获取对应的测试结果const result = getBestQuestionResult(answerList, questions, questionResults);

MBTI 性格测试小程序测试

image.png

注意事项

出现问题在排除代码问题的情况下:

  • 清理开发工具缓存
  • 重启项目
  • 重启微信开发者工具

扩展

  • 完善MBTI性格测试小程序(参考http://sssch.net/ArticleDetail.aspx?ArticleID=13188130318)
  • 做题进度条
  • 优化结果样式(结合每种性格和用户性别展示不同的图片)
  • 将数据放进后端管理
进度条

在答题页面src/pages/doQuestion/index.tsx添加taro-ui的进度条组件,使用用户的答题数除以题目数计算即可:

      <AtProgressclassName="progress"// 进度条的百分比percent={(answerList.length / questions.length) * 100}// 进度条的宽度strokeWidth={10}// 进度条的颜色activeColor="#1aad19"/>

image.png


http://www.ppmy.cn/ops/93035.html

相关文章

Linux服务管理-Nginx配置

静态解析主要解析html、css动态解析需要解析php 动态资源通过轮询分配到后端的Apache服务器处理 apache是同步阻塞&#xff0c;nginx是异步非阻塞

2024最新Mysql锁机制与优化实践以及MVCC底层原理剖析

锁机制详解 锁是计算机协调多个进程或线程并发访问某一资源的机制。 在数据库中&#xff0c;除了传统的计算资源&#xff08;如CPU、RAM、I/O等&#xff09;的争用以外&#xff0c;数据也是一种供需要用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解…

Kotlin 值类(Value Class)

在 Java 中&#xff0c;像 Integer、Double 等都是 包装类&#xff0c;都需要创建对象 装箱 数值。 很显然 创建对象是 消耗额外内存的&#xff0c;而 对于优化这种问题&#xff0c;Kotlin 引入了 value class&#xff0c;尽量避免装箱和脱箱。 一、声明语法 JvmInline value…

【数据结构与算法 | 力扣+二叉搜索树篇】力扣450, 98

1. 力扣450&#xff1a;删除二叉搜索树的节点 1. 题目&#xff1a; 给定一个二叉搜索树的根节点 root 和一个值 key&#xff0c;删除二叉搜索树中的 key 对应的节点&#xff0c;并保证二叉搜索树的性质不变。返回二叉搜索树&#xff08;有可能被更新&#xff09;的根节点的引…

第二章 部署LVS-DR

DR模式的调度器和节点服务器都有VIP地址&#xff0c;但节点服务器的VIP在回环网卡&#xff0c;回环网卡的地址只能本机看到&#xff0c;外部主机看不到&#xff0c;所以不会冲突。 一、DR模式的简单过程 DR模式的具体过程&#xff1a;首先客户端.135向目标vip发出请求&#x…

2-17、18 HC06蓝牙模块(meArm机械臂)

2-17、18 HC06蓝牙模块&#xff08;meArm机械臂&#xff09; 2-17 HC06蓝牙模块-1RX引脚分压电路HC06连接与arduino的电路HC06蓝牙模块应用程序测试程序1&#xff1a;使用Arduino通过无线蓝牙控制Arduino引脚11的LED点亮&#xff0f;熄灭测试程序2&#xff1a;使用Arduino通过无…

67、ceph

一、ceph 1.1、ceph概念 ceph是一个开源的&#xff0c;用c语言写的分布式的存储系统。存储文件数据。 /dev/sdb fdisk /dev/sdb gdisk /dev/sdb lvm 逻辑卷 可以扩容 raid 磁盘阵列 高可用 基于物理意义上的单机的存储系统。 分布式有多台物理磁盘组成一个集群&…

编程-设计模式 23:模板方法模式

设计模式 23&#xff1a;模板方法模式 定义与目的 定义&#xff1a;模板方法模式定义了一个操作中的算法骨架&#xff0c;而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。目的&#xff1a;该模式的主要目的是封装算法的…