Maison >Applet WeChat >Développement de mini-programmes >Résumé des problèmes rencontrés lors du développement d'un mini programme
Questions d'entretien pour le mini-programme
1. Quelle est la différence entre bindtap et catchtap ?
bindLa liaison d'événement n'empêchera pas les événements bouillonnants de bouillonner catchLiaison d'événement Cela peut. empêcher définitivement les événements bouillonnants de bouillonner
2. Convertir le tableau Js en chaîne, forcer la conversion en entier et la conversion en nombre à virgule flottante Quelles sont les fonctions ?
js fournit deux fonctions de conversion : parseInt() et parseFloat(). Le premier convertit la valeur en nombre entier et le second convertit la valeur en nombre à virgule flottante. Ce n'est qu'en appelant ces méthodes sur le type String que ces deux fonctions peuvent s'exécuter correctement ; pour les autres types, NaN (Not a Number) est renvoyé.
Recommandations d'apprentissage gratuites associées : Développement de mini-programmes WeChat
1. Fonction de conversion :
Avant de déterminer si une chaîne est une valeur numérique, parseInt() et parseFloat() analyseront soigneusement la chaîne. La méthode parseInt() vérifie d'abord le caractère à la position 0 pour déterminer s'il s'agit d'un nombre valide ; sinon, la méthode renverra NaN et ne continuera pas à effectuer d'autres opérations ; Mais si le caractère est un nombre valide, la méthode examinera le caractère en position 1 et effectuera le même test. Ce processus se poursuivra jusqu'à ce qu'un caractère qui n'est pas un nombre valide soit trouvé, moment auquel parseInt() convertira la chaîne avant le caractère en nombre.
parseInt("1234blue"); //returns 1234 parseInt("0xA"); //returns 10 parseInt("22.5"); //returns 22 parseInt("blue"); //returns NaN
2. Conversion de type forcée
Vous pouvez également utiliser la conversion de type pour gérer la conversion du type de valeurs. Utilisez un cast pour accéder à une valeur spécifique, même si elle est d'un autre type.
Les trois types de conversions disponibles dans ECMAScript sont les suivants :
Boolean(value) - Convertit la valeur donnée en type booléen
Number(value) - Convertit la valeur donnée en nombre (peut être un nombre entier ou à virgule flottante)
String(value) - Convertit la valeur donnée en chaîne de caractères.
3. Utiliser la conversion de type faible des variables js
Un petit exemple, vous le comprendrez d'un coup d'œil .
<script> var str= '012.345 '; var x = str-0; x = x*1; </script>
L'exemple ci-dessus profite des caractéristiques de type faibles de js et effectue uniquement des opérations arithmétiques pour obtenir une chaîne en nombre conversion de type, mais cette méthode n'est pas recommandée.
3. Décrivez brièvement les types de fichiers associés à l'applet WeChat .
Mini programme : pages ——index : index.js(Logique de la page) /index.wxml (Structure de la page)/index.wxss (Page Feuille de style)/index.json (Configuration de la page)
App.js Logique du mini programme
App.json Paramètres publics du mini programme
App.wxss Feuille de style publique du mini programme
4, Le mini programme has Quelles sont les méthodes pour transmettre les valeurs des paramètres ?
1. La méthode de définition de l'identifiant identifie la valeur du paramètre transmise après le saut
2. Utilisez la méthode data - xxxx pour identifier la valeur à transmettre
. 🎜 >L'applet WeChat définit l'identifiant de la méthode id pour transmettre la valeur
Au niveau de l'élément à sauter, définissez un identifiant et attribuez la valeur correspondante à l'élément actuel id La valeur clé, telle que l'identifiant d'un film (puis passer à la page suivante avec l'identifiant pour demander des informations détaillées) telle que :
Ensuite, nous l'obtenons dans l'événement de réponse de bindtap en js et transmettez-le à la page suivante Dans une interface ;Obtenez la valeur transmise par id
Obtenez la valeur d'identifiant définie via e.currentTarget. id; et définissez la valeur id en définissant la méthode d'objet global pour transmettre les valeurs,
Obtenez l'objet global var app=getApp(); l'accès global aux requêtes app.requestDetailid=id;
Astuce : En fait, nous pouvons également afficher la valeur id de chaque élément que nous définissons dans wxml
通过使用data - xxxx 的方法标识来传值
通过使用data - xxxx 的方法标识来传值,xxxx可以自定义取名 比如data-key等等都可以。
如何获取data-xxxx传递的值?
在js的bindtap的响应事件中:
通过数据解析一层层找到数据,var id=e.target.dataset.id(根据你的data-id的取名)
微信小程序如何跨页面获取值?
依据上面的方式设置要传递的值,页面跳转后,我们就需要在下一个页面拿到传递的数据(这个数据在传递前,就已经被设置成全局变量)
在跳转后的js页面,接收传递过来的数据detail.js
同样通过全局额方式取值出来,(即和app.js中取某个变量的值是一样的)
var movieid=getApp().MovieDetailid;
console.log(movieid);
5、简述下wx.navigateTo(), wx.redirectTo(), wx.switchTab(), wx.navigateBack(), wx.reLaunch()的区别?
微信小程序 跳转页面
小程序页面有2种跳转,可以在wxml页面或者js中:
1,在wxml页面中:
<navigator url="../index/index">跳转到新页面</navigator> <navigator url="../index/index" open-type="redirect">在当前页打开</navigator> <navigator url="../index/index" open-type="switchTab">切换到首页Tab</navigator>
2,在js页面中:
【注意】此处注意两个关键词 “应用内的页面” 和 “tabBar页面”。 app.json文件中tabBar中注册过的tab页,即为“tabBar页面”,非tabBar中注册占用的页面即为“应用内的页面” 。 如下图:home页面为“应用内的页面”,index和logs页面则为 “tabBar页面”。
3,如果上述跳转遇到跳转失败或无效的问题,请访问下面链接:
wx.navigateTo/wx.redirectTo 无效
6、如果需要用户授权,用户选择拒绝授权,此时应该如何处理?
在微信小程序开发时,当我们调用API wx.getUserInfo(OBJECT) 时,需要用户授权。但如果用户拒绝授权,我们如何兼容用户拒绝授权状态,拥有更好的用户体验呢?
先看看这个接口的官方文档:
wx.getUserInfo(OBJECT)
获取用户信息,需要先调用 wx.login 接口。
OBJECT参数说明:
参数名 |
类型 |
必填 |
说明 |
withCredentials |
Boolean |
否 |
是否带上登录态信息 |
success |
Function |
否 |
接口调用成功的回调函数 |
fail |
Function |
否 |
接口调用失败的回调函数 |
complete |
Function |
否 |
接口调用结束的回调函数(调用成功、失败都会执行) |
1. tip: wx.getUserInfo 接口需要用户授权,请兼容用户拒绝授权的场景。
我们就是要在用户点击拒绝的时候,弹出提示框,提示用户以提升用户体验。像下面这样的。
用具体代码实现就是,将弹窗写在 wx.getUserInfo 的fail回调函数中,像下面这样:
wx.getUserInfo({ success: function (resuser) { console.log(success) }, fail: function () {// 调用微信弹窗接口 wx.showModal({ title: '警告', content: '您点击了拒绝授权,将无法正常使用******的功能体验。请10分钟后再次点击授权,或者删除小程序重新进入。', success: function (res) { if (res.confirm) { console.log('用户点击确定') } } }) } })
这样用户就获得了提示信息,但此时,用户还是停留在页面的,如果某些展示信息,还是给要给用户展示的,只是在进行某些操作的时候要对授权进行验证的话,那就得继续修改我们的代码,保存用户的登录态,在其他地方做验证使用。
第一种思路:
保存登录态这里是这样的,将用户的登录信息传给后台,后台保存用户信息,同时用 open_id 在后台换取一个SessionId 用换取的这个SessionId 存在缓存,做为登录态验证。
wx.getUserInfo({ success: function (resuser) { let userInfo = resuser.userInfo that.healthApi.login(code, userInfo).then(logindata => { // 这里将微信的请求封装成Promiese 风格 if (logindata.code === 0) { var sessionId = logindata.data// 调用微信wechat.setStorage将换回来的 SessionId 存在本地缓存 that.wechat.setStorage('sessionId', sessionId).then(() => { that.globalData.userInfo = userInfo typeof cb == "function" && cb(that.globalData.userInfo) }) } }) }, fail: function () { wx.showModal({ title: '警告', content: '您点击了拒绝授权,将无法正常使用*****的功能体验。请10分钟后再次点击授权,或者删除小程序重新进入。', success: function (res) { if (res.confirm) { console.log('用户点击确定') } } }) } })
这样我们将登录态保存在了 SessionId 中,在每次登录的时候我们只需要再调用一个 检查 SessionId的接口就行,检查不通过再调微信登录接口。此处不做延伸了。
第二种思路:
在3.29微信小程序更新的版本中,加入了这样一条属性
withCredentials 字段基础库版本 1.1.0 开始支持,低版本需做兼容处理
这个字段的意思就是调用 wx.getUserInfo(OBJECT) 是否带上 登录态 的信息。
官方文档是这样解释的:
withCredentials 字段基础库版本 1.1.0 开始支持,低版本需做兼容处理
注:当 withCredentials 为 true 时,要求此前有调用过 wx.login 且登录态尚未过期,此时返回的数据会包含 encryptedData, iv 等敏感信息;当 withCredentials 为 false 时,不要求有登录态,返回的数据不包含 encryptedData, iv 等敏感信息。
success返回参数说明:
参数 |
类型 |
说明 |
userInfo |
OBJECT |
用户信息对象,不包含 openid 等敏感信息 |
rawData |
String |
不包括敏感信息的原始数据字符串,用于计算签名。 |
signature |
String |
使用 sha1( rawData + sessionkey ) 得到字符串,用于校验用户信息。 |
encryptedData |
String |
包括敏感数据在内的完整用户信息的加密数据,详细见加密数据解密算法 |
iv |
String |
加密算法的初始向量,详细见加密数据解密算法 |
注:需要兼容微信低版本,向后兼容。
那么利用这个接口,我们可以直接拿到 登录状态,在其他需要验证登录的地方进行提示,而在不需要授权的地方还可以让用户浏览小程序。
回到前面的问题,在用户点击拒绝授权后,在某些操作时需要验证用户是否授权过,弹出交互信息,那么就利用上面的 SessionId或者 withCredentials 登录态进行下面的操作:
applyIn: function applyIn() { if (wx.getStorageSync('sessionId')) { // 根据储存的sessionId 进行验证 wx.navigateTo({ url: 'familyDoctorApply/familyDoctorApply?Oid=' + this.data.params.Oid + '&title=' + this.data.params.title + '&serviceCity=' + this.data.array[this.data.index].name + '&productPrice=' + this.data.product.productPrice }); } else { wx.showModal({ title: '警告', content: '您点击了拒绝授权,无法使用此功能。', success: function (res) { if (res.confirm) { console.log('用户点击确定') } } }) }
效果像这样:
这样一个简单完整的登录及授权,登录态保存等前端微信小程序解决方案就完成了,还可以继续扩展到登录有效期,退出登录,用户权限等跟多扩展的地方。
7、你平时封装可以复用的方法吗?你会把可以复用的方法写在哪个文件里?
其实可以模拟一些框架的,比如bootsrap,写个demo出来,抽出css和js,js最好抽象成对象(构造函数)或者是带参数的方法,然后你只要声明对像,或者参数指定某个class或id,就可以了
写在html文件里有什么优点吗?
独立出来会有什么问题吗?尤其是载入页面的时候,应该会多发很多http请求吧,会不会造成加载变慢?
8、分析下小程序的优劣势?
小程序是在微信生态发展过程中新出现的一种应用形态,小程序的小,从某种程度上已经说明了它的体量不会很大,但是可以实现一些功能相对简单、交互相对简单的服务需求,同时解决了App长期以来多平台适配、多应用市场分发、开发成本居高不下等诸多方面的问题。所以小程序【密件】依靠微信平台和自身“阅后即焚”的功能,获得众多年轻人的好评
优势:
1)容易上手,只要之前有HTML+CSS+JS基础知识,写小程序基本上没有大问题;当然如果了解ES6+CSS3则完全可以编写出即精简又动感的小程序;
2)基本上不需要考虑兼容性问题,只要微信可以正常运行的机器,就可以运行小程序;
3)基本组件库已经比较齐全:Toast,Loading框,Picker,定位及地图,Image,Input,Checkbox,Text,TextArea,ScrollView等常用的组件都有,而且使用也挺简单、方便;
4)发布、审核高效,基本上上午发布审核,下午就审核通过,升级简单,而且支持灰度发布;
5 ) 微信官方提供使用人数、频率等数据统计,小程序js脚本执行错误日志;
6)开发文档比较完善,开发社区比较活跃;
7)最近刚开放的牛x功能,新增webview组件,可以展示网页啦,这个比较爽;
8)支持插件式开发,一些基本功能可以开发成插件,供多个小程序调用;
劣势:
1)后台调试麻烦,因为API接口必须https请求,且公网地址,也就是说后台代码必须发布到远程服务器上;当然我们可以修改host进行dns映射把远程服务器转到本地,或者开启tomcat远程调试;不管怎么说终归调试比较麻烦。
2)前台测试有诸多坑,最头疼莫过于模拟器与真机显示不一致(之前碰到一个案例,后续单独讲解)
3)真机测试,个别功能安卓和苹果表现迥异,我们的小程序里有很多页面有定位功能,模拟器和iphone定位瞬间完成,然而安卓手机就蛋疼了,老显示“定位中...”要很久才能定位好。后来没办法只能优化,减少定位次数。
4)native组件,展示很不好,比如textarea,不能在滚动页面出现,而且至于顶层,经常其它组件会被它遮挡,点击其它组件时,就进入textarea输入框;画布组件也是如此;
5)页面跳转深度不能超过5个页面,这个比较麻烦,有些复杂的页面跳转没法实现,不过太复杂的话也有悖小程序简单易用的原则啦;
6)小程序升级问题,官方文档说会自动更新,实际情况往往是要先把原来的小程序删除掉,重新搜索添加,才能加载最新版本;
7)页面渲染稳定性有待提高,已经好几次出现部分用户的页面显示异常,整个页面被放大了好几倍,先删除原来小程序再添加回来,如此重复好几次,才能显示正常;
8)js引用只能使用绝对路径,很蛋疼;基于安全性及MINA框架实现原理,小程序中对js使用做了很多限制,不能使用:new Function,eval,Generator,不能操作cookie,不能操作DOM;
9)开发工具bug比较多且效率比较低,三天两头升级,解决老问题的同时又出现问题;文件查找、资源定位、代码编辑较eclipse有一定差距。经常出现把a.js当做b.js来修改
9、设置值到页面暂存区(即data)里面的方法有几种?分别是什么?有什么区别?
1. 使用QueryString变量
QueryString是一种非常简单的传值方式,他可以将传送的值显示在浏览器的地址栏中。如果是传递一个或多个安全性要求不高或是结构简单的数值时,可以使用这个方法。但是对于传递数组或对象的话,就不能用这个方法了。下面是一个例子:
a.aspx的C#代码
private void Button1_Click(object sender, System.EventArgs e) { string s_url; s_url = "b.aspx?name=" + Label1.Text; Response.Redirect(s_url); } b.aspx中C#代码 private void Page_Load(object sender, EventArgs e) { Label2.Text = Request.QueryString["name"]; }
2. 使用Application 对象变量
Application对象的作用范围是整个全局,也就是说对所有用户都有效。其常用的方法用Lock和UnLock。
a.aspx的C#代码
private void Button1_Click(object sender, System.EventArgs e) { Application["name"] = Label1.Text; Server.Transfer("b.aspx"); } b.aspx中C#代码 private void Page_Load(object sender, EventArgs e) { string name; Application.Lock(); name = Application["name"].ToString(); Application.UnLock(); }
3. 使用Session变量
想必这个肯定是大家使用中最常见的用法了,其操作与Application类似,作用于用户个人,所以,过量的存储会导致服务器内存资源的耗尽。
a.aspx的C#代码
private void Button1_Click(object sender, System.EventArgs e) { Session["name"] = Label.Text; } b.aspx中C#代码 private void Page_Load(object sender, EventArgs e) { string name; name = Session["name"].ToString(); }
4. 使用Cookie对象变量
这个也是大家常使用的方法,与Session一样,其是什对每一个用户而言的,但是有个本质的区别,即Cookie是存放在客户端的,而session是存放在服务器端的。而且Cookie的使用要配合ASP.NET内置对象Request来使用。
a.aspx的C#代码
private void Button1_Click(object sender, System.EventArgs e) { HttpCookie cookie_name = new HttpCookie("name"); cookie_name.Value = Label1.Text; Reponse.AppendCookie(cookie_name); Server.Transfer("b.aspx"); } b.aspx中C#代码 private void Page_Load(object sender, EventArgs e) { string name; name = Request.Cookie["name"].Value.ToString(); }
5. 使用Server.Transfer方法
这个才可以说是面象对象开发所使用的方法,其使用Server.Transfer方法把流程从当前页面引导到另一个页面中,新的页面使用前一个页面的应答流,所以这个方法是完全面象对象的,简洁有效。
a.aspx的C#代码
public string Name { get{ return Label1.Text;} } private void Button1_Click(object sender, System.EventArgs e) { Server.Transfer("b.aspx"); } b.aspx中C#代码 private void Page_Load(object sender, EventArgs e) { a newWeb; //实例a窗体 newWeb = (source)Context.Handler; string name; name = newWeb.Name; }
微信小程序--data的赋值与取值
通过小程序官方文档可知:
Page() 函数用来注册一个页面。接受一个 object 参数,其指定页面的初始数据、生命周期函数、事件处理函数等。其中的参数data用来设置初始数据,WXML 中的动态数据均来自对应 Page 的 data。
所以如果页面需要显示动态数据必须要把数据更新到data中对应的变量中。
页面js文件中这么写:
Page({ data: { message: 'Hello MINA!' } }) · wxml中这么写: <view> {{ message }} </view>
如果该数据在操作过程中发生变化,需要将新数据重新绑定到该变量中,写法如下:
function setData(){ var that = this; that.setData({ message: '新消息' }) }
如果想在js文件中使用data中的数据写法如下:
function getData(){ var that = this; console.log(that.data.message) }
10、如何检测用户的微信版本是否支持某项功能?
Les interfaces ouvertes dans la première phase ne sont pas inutilisables, mais ne nécessitent pas de tests, et sont toutes supportées.
Seules les dernières interfaces ouvertes doivent être vérifiées pour la prise en charge.
Toutes les interfaces actuellement ouvertes :
onMenuShareTimeline
onMenuShareAppMessage
onMenuShareQQ
onMenuShareWeibo
onMenuShareQZone
startRecord
stopRecord
onVoiceRecordEnd
playVoice
pauseVoice
stopVoice
onVoicePlayEnd
uploadVoice
téléchargerVoice
choisirImage
previewImage
téléchargerImage
téléchargerImage
translateVoice
getNetworkType
openLocation
getLocation
hideOptionMenu
showOptionMenu
hideMenuItems
showMenuItems
hideAllNonBaseMenuItem
showAllNonBaseMenuItem
fermer la fenêtre
scanQRCode
choisirWXPay
ouvrirProductSpecificView
ajouter une carte
choisissezCard
openCard
11. Comment sous-packager le chargement ? Quels sont les avantages du chargement de sous-packages ?
Introduction au chargement de sous-paquets
La plupart des petits programmes sont composés de certaines fonctions, généralement ces quelques fonctions sont indépendantes les unes des autres, mais reposent sur une logique commune, et ces fonctions correspondent généralement à plusieurs pages indépendantes. Ensuite, le package du code du mini-programme n'a pas besoin d'être regroupé dans un seul package. Il peut être divisé en plusieurs sous-packages selon la division des fonctions. Lorsqu'une certaine fonction est nécessaire, le sous-package correspondant à cette fonction est. chargé.
Pour les utilisateurs, le processus de chargement du mini programme devient :
1 Lors du premier démarrage, téléchargez d'abord le package principal du mini programme et affichez le. pages dans le package principal ;
2. Si l'utilisateur entre dans une certaine page de sous-package, téléchargez le sous-package correspondant Une fois le téléchargement terminé, la page du sous-package s'affiche.
En utilisant le chargement de sous-packages, pour les développeurs, le mini-programme peut avoir une taille de code plus grande et transporter plus de fonctions et de services ; pour les utilisateurs, il peut être ouvert plus rapidement. Le mini-programme, tout en utilisant plus de fonctions sans affectant la vitesse de démarrage.
Répartition des sous-traitants
Avant la configuration, les développeurs doivent d'abord planifier le contenu que chaque sous-traitant doit accueillir. Nous recommandons aux développeurs de suivre le. Le principe de la division des fonctions est de placer les pages et la logique sous la même fonction dans le même répertoire. Pour une logique commune entre les fonctions, placez-la sous le package principal. Cela garantit que lors de la sous-traitance des références à cette partie de la fonction, cette partie. de la logique doit exister.
Lors de la répartition des sous-contrats, vous devez faire attention aux points suivants :
1. Évitez le couplage de références entre sous-contrats. Étant donné que le chargement des sous-packages est déclenché par les opérations de l'utilisateur, il n'y a aucune garantie que lorsqu'un certain sous-package est chargé, un autre sous-package existera définitivement. Cela peut provoquer des anomalies logiques JS, telles que le signalement de ""xxx.js. " n'est pas défini" ;
2. Certains composants personnalisés à usage public doivent être placés dans le package principal.
Configuration de la sous-traitance
Après avoir clarifié le partage de la sous-traitance, vous pouvez configurer la sous-traitance Cette étape n'est pas compliquée.
假设支持分包的小程序目录结构如下:
开发者通过在 app.json subPackages 字段声明项目分包结构:
分包加载的低版本兼容问题
微信 6.6.0 版本开始支持分包加载,而对于低于这个版本的客户端,我们做了兼容处理,开发者不需要对老版本微信客户端做兼容。对于老版本的客户端,编译后台会将所有的分包打包成一个整包,老版本的客户端依然按照整包的方式进行加载。
所以在老版本的微信客户端下,是依然采取整包加载的方式加载的,建议开发者尽量控制代码包的大小。
目前小程序分包大小的限制:
整个小程序所有分包大小不超过 4M
单个分包/主包大小不能超过 2M
随着时间推移,老版本覆盖率降低,我们会考虑进一步扩大代码包的大小。
12、在你开发小程序的过程中遇到过什么坑? 你是怎么解决的?
1.我们使用app.json文件来对微信小程序进行全局配置,决定页面文件的路径、窗口表现、设置网络超时时间、设置多 tab 的时候在pages中写注释的时候回报错。
例如:
{ "pages":[ //这是首页面 "pages/welcome/welcome" ]}
此时就会报错
2.在json文件中没有写内容的时候也要加一对大括号{ },不然的话也会报错
3. ①在开发微信小程序的时候,我们使用app.json文件来对微信小程序进行全局配置,决定页面文件的路径,窗口表现,设置网络超时时间,设置多Tab等。
以下是一个包含了所有配置选项的简单配置,app.json :
{ //设置页面路径 "pages": [ "pages/index/index", "pages/logs/index" ], //设置默认页面的窗口表现 "window": { "navigationBarTitleText": "Demo" }, //设置底部 tab 的表现 "tabBar": { "list": [{ "pagePath": "pages/index/index", "text": "首页" }, { "pagePath": "pages/logs/logs", "text": "日志" }] }, //设置网络超时时间 "networkTimeout": { "request": 10000, "downloadFile": 10000 }, //设置是否开启 debug 模式 "debug": true }
②但是在对页面json文件进行配置的时候只可以配置设置默认页面的窗口表现(即只能对window进行配置),但是在此时可以直接省略window,如果加window则没有效果,也不会报错。
以下是一个包含了window配置选项的简单配置,post.json :
注意:这是错误的写法
{ "window":{ "navigationBarBackgroundColor": "#ffffff", "navigationBarTextStyle": "black", "navigationBarTitleText": "微信接口功能演示", "backgroundColor": "#eeeeee", "backgroundTextStyle": "light" }}
注意:正确的写法
{ "navigationBarBackgroundColor": "#ffffff", "navigationBarTextStyle": "black", "navigationBarTitleText": "微信接口功能演示", "backgroundColor": "#eeeeee", "backgroundTextStyle": "light"}
4.此前一直没有注意vertical-align: middle和height:40rpx;line-height:40rpx进行设置垂直剧中的区别,这次主要说一下vertical-align: middle
代码如下:
<view class="post-author-date"> <image class="post-author" src="../../images/avatar/1.png"> </image> <text class="post-date">Nov 15 2016</text> </view> .post-author{ width: 60rpx; height: 60rpx; vertical-align: middle; } .post-date{ margin-top: 5rpx; vertical-align: middle; /*height: 40rpx; line-height: 40rpx;*/ }
总结:
①vertical-align: middle;把此元素放在父元素的中部
②当一个父元素里面有多个子元素,需要把几个子元素水平对齐,并且每个子元素都垂直剧中的时候,对每一个子元素进行设置 vertical-align: middle
③height: 40rpx; line-height: 40rpx;可以对文本进行垂直居中
相关学习推荐:小程序开发教程
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!