随着互联网开发技术的不断发展,小程序和APP的使用率也越来越高。微信小程序曾经还因为跳一跳这个小游戏火了一把,后来就在我们的生活中越来越普及了,比如使用小程序点单付款、在线填单邮寄快递、线上商城小程序等。
很多客户在咨询我们做软件开发的过程中,不太了解APP和小程序的区别,也不知道这两者该如何选择更好。下面喜妹就以喜望软件过往的开发经验来解决这个问题,好好讲讲APP和小程序的区别,方便各位更加清晰地做产品开发的决策。
一丨基础框架
移动端产品的设计规范和原则大致是相同的,但微信小程序由于受制于微信的框架,就与App在部分版块的表现形式上存在一些差异,主要体现在以下几个方面:
1顶部导航栏
小程序:导航栏右侧有个无法去除和编辑的胶囊(titlebar),原生的导航栏支持更改颜色,但字体颜色仅支持黑/白两种,设计时也不能在导航上增加其他功能。所以一些原本可安置在导航栏的定位、搜索、消息等模块的内容也自动下移,banner也是处于导航栏的下方。
虽然微信也提供自定义导航栏,支持加入搜索,将背景色、等跟导航栏融合在一起,但可能会需要重新调整界面和元素,量级大的话也会导致工作量增加。
App:通常在app的界面中,整个界面都是可以自定义,所以顶部的导航区域不受限制,可拓展性强,灵活性高。
2底部标签栏
底部标签栏是移动端产品的主要导航方式,主要表示用户当前所在的位置,会有选中与未选中两种切换方式。
App的标签栏高度和图标大小都可以自定义,也会有很多不同的表达形式,比如采用自由的、冲破边界的异形元素,在Tab切换时会有动效,容易吸引用户的注意力。
而小程序通常使用原生控件,icon的尺寸一般都是8181px。Tab切换形式通常比较单一、常规,没有动态效果。
二丨功能模块
小程序是在微信的框架里面的,大小受微信的控制。目前小程序调整了开发可以用分包加载的方式将大小扩至12m,但跟原生APP比起来还是相差很大的。app一般可以达到几十兆,不受限制。
正因为内存的限制,再加上小程序仅限微信提供的接口功能,所以功能模块会跟APP有所不同。
一般小程序在功能架构上设置较为简单、轻量,适合一些工具属性的应用,符合“快速打开、用完即走”的理念,更贴近于生活中的吃喝玩乐。
小程序也能实现很多功能,比如消息通知、线下扫码、公众号关联等,但对于一些需要大量计算的功能类应用,如处理、文档编辑等,小程序是无法满足的。
原生App的内存就不受控制,功能模块可以根据产品定位随意增添,视觉效果的设计也更加人性化和绚丽丰富。
APP可以发挥的空间非常大,直播、电商、社区等比较复杂的应用都能实现,也能够在交互、视觉等用户体验上满足用户的高要求。你想要丰富、细化、个性化的功能,需要更大的容量来实现,就在APP上承载吧~
三丨引流推广
小程序因为背靠微信,可以与微信公众号进行互通跳转,活跃指数高,引流效果好。微信自带的「附近的小程序」功能,自带免费推广,帮助小程序被五公里范围内的微信用户搜索到。小程序是根据距离来排名,与品牌大小无关,离用户越近就排得越前。
但是微信对小程序进行了诸多限制,特别是流量获取方面,很多小程序的营销策略被腾讯禁止,比如三级分销等,严重的还会下架封号,且很难申述。
而APP内部的功能和内容由运营者全权把控,虽受制于内存大小和流量成本,但好在营销策略可以灵活运用,推广方式和渠道很多,自由性更高。
四丨下载安装
App需要用户去应用市场下载,虽然下载渠道多,但对网络环境的依赖性强,占用手机空间较大。
而小程序可以通过二维码、微信搜索等方式立即加载使用,响应速度很快,占用手机内存空间可以忽略不计(只是部分微信缓存数据)。对于手机内存较小的用户,微信小程序就是一个福音。
五丨用户群
小程序:基于微信平台的应用,仅限微信用户,月活跃用户10亿+。
APP:上架在AppStore及Android应用市场,面向全球拥有智能手机的用户,也就是33亿+的用户量。
从精准度来讲,App大部分都是用户在应用商店中搜索下载的,用户的下载行为首先是基于对APP有兴趣,那么这样的用户群相对小程序而言更加精准。
六丨用户体验
1使用习惯
用户下载App后,是直接存在用户的手机桌面,要使用的时候打开手机,找到APP点击进入就能使用,打开方式更快速更方便。
小程序的入口比较深,需要打开微信进行查找或下拉获取,至少需要3步才能打开对应的小程序。而且现在小程序很多,用户很难想起之前使用过的小程序,大都是需要使用时才会去搜索。
2消息广告
App可以给用户推送消息,提示用户打开软件,增加启动和使用软件的频率,提升软件的活跃度。但有些app隔三差五的推送消息,甚至还有很多d窗广告,会给用户产生干扰,太多的未读提示逼死强迫症用户。
而小程序不允许主动给用户推送广告,只能回复模版消息,站在不打扰用户的角度来说,用户体验感比APP好。
七丨开发成本
1发布
App一般会向多个应用商店提交审核,根据每个应用商店不同的审核标准准备资料、调整修改和打包安装包,较为繁琐;而小程序只需要提交到微信公众平台审核即可。
2开发时间
做APP普遍都会开发安卓系统和iOS系统两种版本,这两个系统所用到的开发语言不同,安卓是Java和Koplin,iOS是Swift和Objective-C。现在苹果又出了暗黑模式,要设计2套UI图,同时还需要适配市场上的多款主流手机,开发时间相对较长。
小程序是基于腾讯的微信小程序开发框架进行开发的,开发技术类似HTML。一次开发就可以自动适配所有手机,所以开发时间会比APP短一点。
3开发费用
一个软件的开发一般都有原型UI设计、框架搭建、数据库设计、接口开发、第三方对接、PC管理系统开发、用户端安卓版开发、用户端苹果版开发、小程序开发等收费项目。
如果只做APP的话,就会减掉小程序开发的费用,反之只做小程序,就少了app前端的开发费用。
总的来说,小程序比APP少了一个前端的开发,费用是APP三分之二左右。
总结
小程序和App各有特色,两者的关系既可以相互补充,又可以完全独立。
小程序的开发难度、时间和成本相对较低,后期维护更容易,迭代更新的速度更快,用户运营更有优势。但小程序的用户体验方面略逊APP,内容体积有限制,总的来讲还是源于命名中的一个“小”字。小程序对于预算较低的初创公司不失为一个不错的选择。
而APP的开发难度较高,后期维护难,迭代更新相对慢,用户运营成本高,但是用户体验感更好、更丰富、原生。对于预算较高的中大型公司,可以通过大型APP沉淀用户数据,提升企业价值。
其实就两种技术而言,并不能完全肯定哪一种更好,只是适用于不同需求的客户。
APP
1适合相对成熟的公司
2充裕的开发时间
3足够的资金预算
4对交互设计和界面效果要求较高
5已经经过实际运营检测的商业模式
VS
小程序
1适合初创公司、中小企业、个体户
2相对较少的资金和时间
3创业、创新商业模式试水
4适合快速场景化服务
5需要向APP引流
最后,喜妹想说,大家在考虑选择小程序还是App时,还是需要分析它们的优劣势,选择适合自己的。
rem由来 :font size of the root element,那么rem是个单位,单位大小由它第一代老祖宗的 font-size 的大小决定。现在前端码农们为了能在各个屏幕上看到一个健康的网页在默默的牺牲着自己的健康,因为不仅要知道rem是个单位,更重要的是要知道怎么能在不同分辨率下呈现的页面都很NB。
事故造成原因:
1px单位在PC上很流行,在手机屏幕上一看,MLGB的,同样的12px却小的跟蚂蚁似的。
2好不容易在iPhone4上调的正常了,换个菊花牌手机,MBD不堪入目了。
3知道了rem的用法,但是html的font-size到底是多少才合适啊啊啊,妈蛋~。
好了,那么现在来解决这些问题。
在解决之前,麻烦各位大婶要了解一些你可能不想了解的东东(警告:不了解这些就不能知道真相哟~):
1 物理像素(physical pixel)
我们看到的每个屏幕都是由一颗颗我们肉眼难以看到的小颗粒(物理像素)组成的。
2逻辑像素
是计算机坐标系统中的一个点,这个点代表一个可以由程序使用的虚拟像素(比如说CSS像素)。
3设备的像素比(device pixel ratio)简称DPR
它的数值体现了物理像素和逻辑像素之间的关系,用公式可以计算出该设备的DPR的大小:
DPR= 物理像素 / 逻辑像素
那么了解了上面这些概念,就可以知道,为什么css在pc上写着font-size=12px;但是换到手机上却变小了?因为DPR啊啊啊,大哥~。
没错,我们在电脑屏幕上的DPR是1,但是手机却不同,可能是它可能是2,也可能是3。获取设备DPR的方法还是有的:
1在JavaScript中,通过windowdevicePixelRatio来获取
2在css中,可以通过-webkit-device-pixel-ratio,-webkit-min-device-pixel-ratio和 -webkit-max-device-pixel-ratio进行媒体查询,对不同DPR的设备,做一些样式适配(这里只针对webkit内核的浏览器和webview)。
本人也在网上看了不少动态设置rem的文章,下面把几个常用的列举出来:
一,用媒体查询来设置html的font-size:
@mediascreen and (min-width:320px) {html{font-size:14px;}} @mediascreen and (min-width:360px) {html{font-size:16px;}} @mediascreen and (min-width:400px) {html{font-size:18px;}} @mediascreen and (min-width:440px) {html{font-size:20px;}} @mediascreen and (min-width:480px) {html{font-size:22px;}} @mediascreen and (min-width:640px) {html{font-size:28px;}}
二、利用js来动态设置
!(function(doc, win){vardocEle = docdocumentElement, evt ="onorientationchange"inwindow"orientationchange":"resize", fn =function(){varwidth = docEleclientWidth; width && (docElestylefontSize =20 (width /320) +"px"); }; winaddEventListener(evt, fn,false); docaddEventListener("DOMContentLoaded", fn,false); }(document,window));
我要说的是最后一种,也是我认为目前比较好的实现方法:
利用js计算当前设备的DPR,动态设置在html标签上,并动态设置html的font-size,利用css的选择器根据DPR来设置不同DPR下的字体大小(这个方法很不错哦~)
!function(win, lib){vartimer, doc = windocument, docElem = docdocumentElement, vpMeta = docquerySelector('meta[name="viewport"]'), flexMeta = docquerySelector('meta[name="flexible"]'), dpr =0, scale =0, flexible = libflexible || (libflexible = {});// 设置了 viewport metaif(vpMeta) {consolewarn("将根据已有的meta标签来设置缩放比例");varinitial = vpMetagetAttribute("content")match(/initial\-scale=([\d\]+)/);if(initial) { scale =parseFloat(initial[1]);// 已设置的 initialScaledpr =parseInt(1/ scale);// 设备像素比 devicePixelRatio} }// 设置了 flexible Metaelseif(flexMeta) {varflexMetaContent = flexMetagetAttribute("content");if(flexMetaContent) {varinitial = flexMetaContentmatch(/initial\-dpr=([\d\]+)/), maximum = flexMetaContentmatch(/maximum\-dpr=([\d\]+)/);if(initial) { dpr =parseFloat(initial[1]); scale =parseFloat((1/ dpr)toFixed(2)); }if(maximum) { dpr =parseFloat(maximum[1]); scale =parseFloat((1/ dpr)toFixed(2)); } } }// viewport 或 flexible// meta 均未设置if(!dpr && !scale) {// QST// 这里的 第一句有什么用 // 和 Android 有毛关系 varu = (winnavigatorappVersionmatch(/android/gi), winnavigatorappVersionmatch(/iphone/gi)), _dpr = windevicePixelRatio;// 所以这里似乎是将所有 Android 设备都设置为 1 了dpr = u ( (_dpr >=3&& (!dpr || dpr >=3)) 3: (_dpr >=2&& (!dpr || dpr >=2)) 2:1) :1; scale =1/ dpr; } docElemsetAttribute("data-dpr", dpr);// 插入 viewport metaif(!vpMeta) { vpMeta = doccreateElement("meta"); vpMetasetAttribute("name","viewport"); vpMetasetAttribute("content","initial-scale="+ scale +", maximum-scale="+ scale +", minimum-scale="+ scale +", user-scalable=no");if(docElemfirstElementChild) { docElemfirstElementChildappendChild(vpMeta) }else{vardiv = doccreateElement("div"); divappendChild(vpMeta); docwrite(divinnerHTML); } }functionsetFontSize(){varwinWidth = docElemgetBoundingClientRect()width;if(winWidth / dpr >540) { (winWidth =540 dpr); }// 根节点 fontSize 根据宽度决定varbaseSize = winWidth /10; docElemstylefontSize = baseSize +"px"; flexiblerem = winrem = baseSize; }// 调整窗口时重置winaddEventListener("resize",function(){ clearTimeout(timer); timer = setTimeout(setFontSize,300); },false);// 这一段是我自己加的// orientationchange 时也需要重算下吧winaddEventListener("orientationchange",function(){ clearTimeout(timer); timer = setTimeout(setFontSize,300); },false);// pageshow// keyword: 倒退 缓存相关winaddEventListener("pageshow",function(e){if(epersisted) { clearTimeout(timer); timer = setTimeout(setFontSize,300); } },false);// 设置基准字体if("complete"=== docreadyState) { docbodystylefontSize =12 dpr +"px"; }else{ docaddEventListener("DOMContentLoaded",function(){ docbodystylefontSize =12 dpr +"px"; },false); } setFontSize(); flexibledpr = windpr = dpr; flexiblerefreshRem = setFontSize; flexiblerem2px =function(d){varc =parseFloat(d) thisrem;if("string"==typeofd && dmatch(/rem$/)) { c +="px"; }returnc; }; flexiblepx2rem =function(d){varc =parseFloat(d) /thisrem;if("string"==typeofd && dmatch(/px$/)) { c +="rem"; }returnc; }}(window,windowlib || (windowlib = {}));
忘了说了,手机淘宝很多页面用的就是这种方法来适配终端的。
先上一图,这个是最终效果:
再看看闪耀效果:
1、先将文字画在canvas;
2、利用getImageData()获取图像数据;
3、将图像数据中黑色(你可以用其他颜色)按一定间隔取值(获取坐标);
4、在获取的坐标画矩形(你画其他形状也是可以的);
5、使用requestAnimationFrame,变换矩形颜色。
这样就闪烁起来了~~
var i = 0
Page({
/ 页面的初始数据/data: {hideNav: false,colors: ["#fff", "#FF6E40", "#FFAB40", "#FFFF00", "#EEFF41", "#B2FF59", "#69F0AE", "#64FFDA", "#18FFFF", "#40C4FF", "#E040FB", "#FF4081", "#ff5252"],
text: '肖战',scroll: false,setting: false},
/ 生命周期函数--监听页面加载/onLoad: function (options) {let that = this, text = wxgetStorageSync('blinkText') || thisdatatext;thissetData({text})thisinit()},
init() {wxcreateSelectorQuery()select('#canvas')fields({node: true,size: true,})exec((res) => {let that = this,text = thisdatatextconst width = res[0]widthconst height = res[0]height
const canvas = res[0]nodeconst ctx = canvasgetContext('2d')const dpr = 1 //wxgetSystemInfoSync()pixelRatiocanvaswidth = width dprcanvasheight = height dprctxscale(dpr, dpr)i = (canvaswidth - thatgetByteLen(text) 100) / 2ctxfillStyle = "#ffffff";ctxfillRect(0, 0, canvaswidth, canvasheight);ctxfont = "bolder 200px Arial";ctxfillStyle = 'black';ctxtextBaseline = 'top';ctxfillText(text, 0, 100);// ctxlineWidth = 5;// ctxstrokeText(text, 0, 100);let imageData = ctxgetImageData(0, 0, canvaswidth, canvasheight)data;// consolelog(imageData)
ctxfillStyle = "#ffffff";ctxfillRect(0, 0, canvaswidth, canvasheight);
thisdatacanvas = canvasthisdatactx = ctxthisdataimageData = imageDataconsolelog(canvaswidth, canvasheight)// thisdrawText()const renderLoop = () => {thisdrawText()
canvasrequestAnimationFrame(renderLoop)}// canvascancelAnimationFrame(renderLoop)canvasrequestAnimationFrame(renderLoop)})},drawText() {var gap = 7,{imageData,canvas,ctx,text,scroll} = thisdataif (scroll) {if (i >= canvaswidth) {i = -canvaswidth}i += 2}
ctxclearRect(0, 0, canvaswidth, canvasheight)for (var h = 0; h < canvasheight; h += gap) {for (var w = 0; w < canvaswidth; w += gap) {var position = (canvaswidth h + w) 4;var r = imageData[position],g = imageData[position + 1],b = imageData[position + 2];
if (r + g + b == 0) {ctxfillStyle = thisdatacolors[Mathfloor(Mathrandom() thisdatacolorslength)];ctxfillRect(w + i, h, 5, 5);}}}
},toggleSetting() {thissetData({setting: thisdatasetting false : true})},setText(e) {
let that = thiswxcloudcallFunction({name: 'msgSecCheck',data: {op: 'textCheck',content: edetailvalue},success(res) {consolelog('ContentCheck-res', res)if (resresultcode == 300) {consolelog(resresultmsg)wxshowToast({icon: 'none',title: resresultmsg,})thatsetData({'text': ''})} else {thatsetData({setting: false,'text': edetailvalue})thatinit()}},fail(err) {consolelog('ContentCheck-errxxxx', err)
}})
},getByteLen(str) {var len = 0;for (var i = 0; i < strlength; i++) {var length = strcharCodeAt(i);if (length >= 0 && length <= 128) {len += 1;} else {len += 2;}}consolelog('文字长度',len)return len;},donothing() {
},/ 生命周期函数--监听页面初次渲染完成/onReady: function () {
},
/ 生命周期函数--监听页面显示/onShow: function () {
},
/ 生命周期函数--监听页面隐藏/onHide: function () {
},
/ 生命周期函数--监听页面卸载/onUnload: function () {wxsetStorage({data: thisdatatext,key: 'blinkText',})},
/ 页面相关事件处理函数--监听用户下拉动作/onPullDownRefresh: function () {
},
/ 页面上拉触底事件的处理函数/onReachBottom: function () {
},
/ 用户点击右上角分享/onShareAppMessage: function () {
}})
wxml是编写小程序的骨架页面
“/”根目录下
只有用text组件包围的文字才可以长按选中在小程序中。
<view></view>没有什么实质性的功能,就跟div一样是用来布局的。
pt:逻辑分辨率,与长度有关
px:物理分辨率,与长度无关,跟点有关
为什么模拟器下ip6的分辨率是375px;而设计图给的是750px
小程序模拟器给的是逻辑分辨率,设计图是物理分辨率,两个之间是2倍关系。所以设计图的尺寸要除以2,如果是用px做单位的话。
再增加物理像素点人眼已经分辨不出来
rpx: 是微信小程序独有的,解决屏幕自适应的尺寸单位
可以根据屏幕宽度进行自适应,不论屏幕大小,规定屏幕宽为 750rpx,通过rpx设置元素和字体大小,小程序在 不同尺寸 的屏幕上可以 自适应适配
以 iPhone6 为例,iPhone6 的屏幕宽度为 375px ,共有 750 个物理像素,则 750rpx = 375px = 750 物理像素
1rpx=05px=1物理像素
以上就是关于开发小程序和开发APP的区别,那个好全部的内容,包括:开发小程序和开发APP的区别,那个好、小程序开发-基础-html+css、小程序:利用canvas制作文字特效等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)