UNIAPP:图片显示问题以及mode值

以下示例是不借助官方mode值时,用css控制,不过效果上与aspectFill类似。

<template>
	<view class="container">
		<view class="intro">本项</view>
		<view class="image-container">
			<image src="@/static/000.jpg" mode="aspectFill" class="ig" :style="bgimg(imageUrl)"/>
		</view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				imageUrl: '/static/000.jpg',
			}
		},
		methods: {
			bgimg(param) {
				return {
					'background-image': `url(${param})`,
					'background-repeat': 'no-repeat',
					'background-position': 'center',
					'background-size': 'cover',
					'width': '100px',
					'height': '100px',
				};
			}
		}
	}
</script>

<style>
	@import "/uni.scss";

	.container {
		display: flex;
	}

	.image-container {
		width: 100%;
		height: 100px;
		overflow: hidden;
	}
	
	.ig {
		width: 100px;
		height: 100px;
	}
</style>

 

mode有效值

mode有14种模式,其中5种是缩放模式,9种是裁剪模式。

模式说明
缩放scaleToFill不保持纵横比缩放图片,使图片的宽高完全拉伸至填满image元素
缩放aspectFit保持纵横比缩放图片,使图片的长边能完全显示出来。也就是说,可以完整地将图片显示出来。
缩放aspectFill保持纵横比缩放图片,只保证图片的短边能完全显示出来。也就是说,图片通常只在水平或垂直方向是完整的,另一个方向将会发生截取。
缩放widthFix宽度不变,高度自动变化,保持原图宽高比不变
缩放heightFix高度不变,宽度自动变化,保持原图宽高比不变 App和H5平台HBuilderX 2.9.3+ 支持、微信小程序需要基础库2.10.3
裁剪top不缩放图片,只显示图片的顶部区域
裁剪bottom不缩放图片,只显示图片的底部区域
裁剪center不缩放图片,只显示图片的中间区域
裁剪left不缩放图片,只显示图片的左边区域
裁剪right不缩放图片,只显示图片的右边区域
裁剪top left不缩放图片,只显示图片的左上边区域
裁剪top right不缩放图片,只显示图片的右上边区域
裁剪bottom left不缩放图片,只显示图片的左下边区域
裁剪bottom right不缩放图片,只显示图片的右下边区域

#示例

<template>
    <view class="page">
        <view class="image-list">
            <view class="image-item" v-for="(item,index) in array" :key="index">
                <view class="image-content">
                    <image style="width: 200px; height: 200px; background-color: #eeeeee;" :mode="item.mode" :src="src"
                        @error="imageError"></image>
                </view>
                <view class="image-title">{{item.text}}</view>
            </view>
        </view>
    </view>
</template>

原图

uniapp

scaleToFill:不保持纵横比缩放图片,使图片完全适应

uniapp

aspectFit:保持纵横比缩放图片,使图片的长边能完全显示出来

uniapp

aspectFill:保持纵横比缩放图片,只保证图片的短边能完全显示出来

uniapp

top:不缩放图片,只显示图片的顶部区域

uniapp

bottom:不缩放图片,只显示图片的底部区域

uniapp

center:不缩放图片,只显示图片的中间区域

uniapp

left:不缩放图片,只显示图片的左边区域

uniapp

right:不缩放图片,只显示图片的右边边区域

uniapp

top left:不缩放图片,只显示图片的左上边区域

uniapp

top right:不缩放图片,只显示图片的右上边区域

uniapp

bottom left:不缩放图片,只显示图片的左下边区域

uniapp

bottom right:不缩放图片,只显示图片的右下边区域

uniapp

UNIAPP:页面生命周期

uni-app页面除支持Vue组件生命周期外还支持下方页面生命周期函数,当以组合式API使用时,在Vue2和Vue3中存在一定区别,请分别参考:Vue2组合式API使用文档Vue3组合式API使用文档

函数名说明平台差异说明最低版本
onInit监听页面初始化,其参数同onLoad参数,为上个页面传递的数据,参数类型为Object(用于页面传参),触发时机早于onLoad百度小程序3.1.0+
onLoad监听页面加载,该钩子被调用时,响应式数据、计算属性、方法、侦听器、props、slots已设置完成,其参数为上个页面传递的数据,参数类型为Object(用于页面传参),参考示例  
onShow监听页面显示,页面每次出现在屏幕上都触发,包括从下级页面点返回露出当前页面  
onReady监听页面初次渲染完成,此时组件已挂载完成,DOM树($el)已可用,注意如果渲染速度快,会在页面进入动画完成前触发  
onHide监听页面隐藏  
onUnload监听页面卸载  
onResize监听窗口尺寸变化App、微信小程序、快手小程序 
onPullDownRefresh监听用户下拉动作,一般用于下拉刷新,参考示例  
onReachBottom页面滚动到底部的事件(不是scroll-view滚到底),常用于下拉下一页数据。具体见下方注意事项  
onTabItemTap点击tab时触发,参数为Object,具体见下方注意事项微信小程序、QQ小程序、支付宝小程序、百度小程序、H5、App、快手小程序、京东小程序 
onShareAppMessage用户点击右上角分享微信小程序、QQ小程序、支付宝小程序、抖音小程序、飞书小程序、快手小程序、京东小程序 
onPageScroll监听页面滚动,参数为Objectnvue不支持 
onNavigationBarButtonTap监听原生标题栏按钮点击事件,参数为ObjectApp、H5 
onBackPress监听页面返回,返回event = {from:backbutton、 navigateBack} ,backbutton表示来源是左上角返回按钮或android返回键;navigateBack表示来源是uni.navigateBack;详见app、H5、支付宝小程序 
onNavigationBarSearchInputChanged监听原生标题栏搜索输入框输入内容变化事件App、H51.6.0
onNavigationBarSearchInputConfirmed监听原生标题栏搜索输入框搜索事件,用户点击软键盘上的"搜索"按钮时触发。App、H51.6.0
onNavigationBarSearchInputClicked监听原生标题栏搜索输入框点击事件(pages.json中的searchInput配置disabled为true时才会触发)App、H51.6.0
onShareTimeline监听用户点击右上角转发到朋友圈微信小程序2.8.1+
onAddToFavorites监听用户点击右上角收藏微信小程序、QQ小程序2.8.1+
UNIAPP:目录结构

一个uni-app工程,默认包含如下目录及文件:


┌─uniCloud云空间目录,阿里云为uniCloud-aliyun,腾讯云为uniCloud-tcb(详见uniCloud)
│─components符合vue组件规范的uni-app组件目录
│  └─comp-a.vue可复用的a组件
├─utssdk存放uts文件
├─pages业务页面文件存放的目录
│  ├─index
│  │  └─index.vue       index页面
│  └─list
│     └─list.vue        list页面
├─static存放应用引用的本地静态资源(如图片、视频等)的目录,注意:静态资源都应存放于此目录
├─uni_modules存放[uni_module](/uni_modules)。
├─platforms存放各平台专用页面的目录,详见
├─nativeplugins         App原生语言插件 详见
├─nativeResources       App端原生资源目录
│  ├─android            Android原生资源目录 详见
|  └─ios                iOS原生资源目录 详见
├─hybrid                App端存放本地html文件的目录,详见
├─wxcomponents存放小程序组件的目录,详见
├─unpackage非工程代码,一般存放运行或发行的编译结果
├─AndroidManifest.xml   Android原生应用清单文件 详见
├─Info.plist            iOS原生应用配置文件 详见
├─main.js               Vue初始化入口文件
├─App.vue应用配置,用来配置App全局样式以及监听 应用生命周期
├─manifest.json配置应用名称、appid、logo、版本等打包信息,详见
├─pages.json配置页面路由、导航条、选项卡等页面类信息,详见
└─uni.scss这里是uni-app内置的常用样式变量
	

Tips

  • HbuilderX 1.9.0+ 支持在根目录创建ext.json、sitemap.json等小程序需要的文件。

#static目录

  • 为什么需要static这样的目录?

uni-app编译器根据pages.json扫描需要编译的页面,并根据页面引入的js、css合并打包文件。
对于本地的图片、字体、视频、文件等资源,如果可以直接识别,那么也会把这些资源文件打包进去,但如果这些资源以变量的方式引用, 比如:<image :src="url"></image>,甚至可能有更复杂的函数计算,此时编译器无法分析。\

那么有了static目录,编译器就会把这个目录整体复制到最终编译包内。这样只要运行时确实能获取到这个图片,就可以显示。

当然这也带来一个注意事项,如果static里有一些没有使用的废文件,也会被打包到编译包里,造成体积变大。

另外注意,static目录支持特殊的平台子目录,比如web、app、mp-weixin等,这些目录存放专有平台的文件,这些平台的文件在打包其他平台时不会被包含。详见条件编译

非static目录下的文件(vue组件、js、css等)只有被引用时,才会被打包编译。

css、less/scss等资源不要放在static目录下,建议这些公用的资源放在自建的common目录下。

  • static目录和App原生资源目录有关系吗?

uni-app支持App原生资源目录nativeResources,下面有assets、res等目录,详见。但和static目录没有关系。

static目录下的文件,在app第一次启动时,解压到了app的外部存储目录(external-path)。

所以注意控制static目录的大小,太大的static目录和太多文件,会造成App安装后第一次启动变慢。

UNIAPP:什么是 uni ext api

uni ext api,是一种需要下载uni_modules插件才能使用的、uni.开头的js API。

它是uni对象的方法,但不预置在uni-app的runtime中,需要单独下载对应的uni_modules。

示例:

uni.getBatteryInfo,这个API就是一个ext api,需要下载插件才能使用。详见

  • 背景1,uni-app runtime越来越大

uni对象的api,如uni.navigateTo,之前都是内置在uni-app的runtime中的,跟随uni-app/HBuilder的升级而变化。

随着各家小程序和uni-app的演进,uni-app的api越来越多,而很多api又不常用,这会增加uni-app的runtime体积,尤其是在web和app平台。

比如很多小程序都内置有getBatteryInfo获取电量的API,在uni-app中理应拉齐各端实现,但在uni-app的web和app上内置它并不合适。

所以推出了uni ext api,这些API以uni_modules的方式出现,从插件市场单独下载。但导入到工程后,仍使用uni.getBatteryInfo方式来调用。

为此,在这些uni_modules的package.json中提供了一种特殊的注册方式,允许插件向uni对象自动挂载api。(只有DCloud官方插件,以uni-开头的插件,才能使用此机制)

  • 背景2,uts将重构uni-app的内部实现

在过去,uni-app的web和小程序端,是github的独立项目,由DCloud的js团队维护。而uni-app的app端,是另2个独立项目,由DCloud的原生团队维护。 每次新加一个api,需要各个团队在不同的工程里开发,尤其是app端,需要先在原生项目里开发,然后在前端项目里封装。还需要再另一个语法提示工程中编写代码提示。

有了uts后,uni-app的实现机制将被重构,大幅的简化。

每个api,都使用uts这门统一的语言来开发,不再使用不同的技术语言。作为一个独立的uni_modules,独立的工程,有独立的版本。

仍然以uni.getBatteryInfo电量为例,开发这个api,不再需要在庞大复杂的uni-app的若干个项目里编码,也不需要再关心功能间关联和耦合。

只需要在uni-getBatteryInfo这个uni_modules下开发,目录结构如下。

这个目录清晰的列出了这个插件要做的所有事情:在不同的目录下编写uts或js代码、在d.ts里写语法提示。

├── uni_modules
│   ├── uni-getbatteryinfo
│   │   ├── changelog.md
│   │   ├── index.d.ts // 类型声明,需要同时扩展uni声明当前注册的API
│   │   ├── package.json
│   │   ├── readme.md
│   │   └── utssdk // 在不同目录实现平台能力
│   │       ├── app-android
│   │       │   └── index.uts
│   │       ├── app-ios
│   │       │   └── index.uts
│   │       ├── mp-weixin
│   │       │   └── index.js
│   │       └── web
│   │           └── index.js

复制代码

这种模式,还给开发者带来若干好处,比如开放性和灵活性。

  • 以往,uni-app内置api如果有bug,普通开发者很难看懂源码,很难参与完善。

现在,在uts的支持下,普通前端也可以review这些api的实现,发现其中的问题和提出改进方案。

  • 以往,这些uni api的bug被修复时,需要等待HBuilder发版,由于每次发版都需要发很多功能,可能bug1虽然已经修好,但bug2复测出问题,导致版本不能及时发布。

现在,ext api的uni_modules脱离HBuilder独立升级,快速解决开发者的问题。并且开发者可以自己修本地工程中ext api的bug。让问题得以更快速的解决。

  • 背景3,内置api复写

很多uni的内置api,比如uni.showWaiting,实现的比较简单,在web端,常见的waiting都有更丰富的样式、使用更多的图片资源。

uni-app的runtime不适合内置很多waiting样式和资源,而使用三方插件,又需要按三方插件的写法调用,之前工程里写好的uni.showWaiting的代码不得不重改。

有了ext api,可以实现一个uni-showwaiting的uni_modules,在web端提供更丰富的效果,并且开源,可自由裁剪和增补。

导入这个uni_modules后,之前的uni.showWaiting的api的功能就被复写。

综上,背景1、2、3的问题,都将使用uni ext api来解决。uni-app很多新增的、不常用的api将采用ext api方式。

在uts的发展路线上,uni-app自身也将使用uts实现;使用uts将可以开发完整的uni-app。

目前所有的ext api,在未来的uts版的uni-app,其内置的uni对象的api中,均会得到复用。也就是说ext api将大幅推进下一代uni-app(纯uts版)的上线速度。

欢迎广大开发者参与到uni ext api的开源共建中来。

#注意事项

  1. 由于开发api是以uni.开头的,所以无法像普通插件那样由开发者自己开发、自己发布。

参与共建的开发者需要在DCloud官方插件的开源项目中提pr,由官方审核后再发布新版uni_modules。

也只有uni-开头的插件,才能在package.json中编写注册声明,挂载方法到uni对象上。

  1. uni ext api的版本将不再跟随HBuilder和uni-app cli的版本,它将是独立的版本。

只有uni的内置api才跟随HBuilder升级。请记得内置api和ext api的区别。

  1. ext api的实现不一定都是uts,但如果使用了uts,则将受uts自身的约束。如
  • uts在iOS上真机运行必须打包自定义基座。后续官方会继续优化
  • uts在Android上涉及arr、jar、so库等三方sdk的时候,也需打包自定义基座才能真机运行。
  • wgt升级只对js、css生效,uts代码无法热更新。但这不意味着使用uts的项目就失去热更新能力,只是uts部分不能热更。js、vue、css、图片仍然可以打包成wgt热更。
  1. ext api在入口文件export的API,必须在package.json中编写注册声明

#如何开发uni ext api

#创建一个符合规则的uni_modules插件(通常是utssdk类型),如uni-getbatteryinfo

注意: 插件ID格式为:uni-API名称全小写

├── uni_modules
│   ├── uni-getbatteryinfo
│   │   ├── changelog.md
│   │   ├── index.d.ts // 类型声明,需要同时扩展uni声明当前注册的API
│   │   ├── package.json
│   │   ├── readme.md
│   │   └── utssdk // 在不同目录实现平台能力
│   │       ├── app-android
│   │       │   └── index.uts
│   │       ├── app-ios
│   │       │   └── index.uts
│   │       ├── mp-weixin
│   │       │   └── index.js
│   │       └── web
│   │           └── index.js

复制代码

#配置package.json

{
  "uni_modules": {
    "uni-ext-api": {
      "uni": ""// string | string[] | Record<string,string>
    }
  }
}

复制代码

  • 默认导出
{
  "uni_modules": {
    "uni-ext-api": {
      "uni": "getBatteryInfo"
      // 等同于
      // import getBatteryInfo from "@/uni_modules/uni-getbatteryinfo";
      // uni.getBatteryInfo = getBatteryInfo
    }
  }
}

复制代码

  • 导出多个
{
  "uni_modules": {
    "uni-ext-api": {
      "uni": ["getBatteryInfo", "isCharging"]
      // 等同于
      // import { getBatteryInfo, isCharging } from "@/uni_modules/uni-getbatteryinfo";
      // uni.getBatteryInfo = getBatteryInfo
      // uni.isCharging = isCharging
    }
  }
}

复制代码

  • 导出别名
{
  "uni_modules": {
    "uni-ext-api": {
      "uni": {
        "onUserCaptureScreen": "onCaptureScreen",
        "offUserCaptureScreen": "offCaptureScreen"
      }
      // 等同于
      // import { onCaptureScreen, offCaptureScreen } from "@/uni_modules/uni-getbatteryinfo";
      // uni.onUserCaptureScreen = onCaptureScreen
      // uni.offUserCaptureScreen = offCaptureScreen
    }
  }
}

复制代码

  • 指定支持的运行环境
{
  "uni_modules": {
    "uni-ext-api": {
      "uni": {
        "request": {
          "name": "request", // 可选别名配置
          "app": {// 表示在app平台,仅在iOS swift环境下生效
            "js": false,
            "kotlin": false,
            "swift": true
          }
        }
      }
    }
  }
}

复制代码

注意:

所有uni ext api均需要提供utssdk/interface.uts文件

所有对外暴露的方法,类型均需要在interface.uts中定义

在具体平台实现中,通过引用interface.uts中的定义的方法,类型来约束实现

声明对象字面量时,必须指定具体类型,如:const res:GetBatteryInfoSuccess = { level:10,.. }

命名规范:

  • API入参类型命名为API名称首字母大写 + 'Options',
  • 异步API success,fail回调结果类型命名为API名称首字母大写 + 'Success' 和API名称首字母大写 + 'Fail'
  • 事件API回调结果类型命名为API名称首字母大写 + 'CallbackResult'

示例(获取电量)参考

HBuilderX3.96及以下使用uni ext api后,云打包同时勾选android和iOS会导致打出来的包不能正确包含uni ext api插件,解决方案:升级至3.97+或android和iOS单独打包

#如何使用uni ext api

插件市场查找uni ext api插件,导入HBuilderX中的项目即可直接使用。

如:uni-getbatteryinfo,导入后,即可直接使用uni.getBatteryInfo

UNIAPP注意事项:小程序

各家小程序实现机制不同,可能存在的平台兼容问题

  1. 浏览器内核差异

各家小程序的浏览器内核不同,可能会造成css兼容性问题,更多细节参考:https://ask.dcloud.net.cn/article/1318

  1. 自定义组件渲染差异

微信(可以使用virtualHost配置)/QQ/百度/抖音这四家小程序,自定义组件在渲染时会比App/H5端多一级节点,在写样式时需要注意:

  • 使用flex布局时,直接给自定义组件的父元素设置为display:flex不能影响到自定义组件内部的根节点,需要设置当前自定义组件为display:flex才可以。
  • 在自定义组件内部设置根元素高度为100%,不能撑满自定义组件父元素。需要同时设置当前自定义组件高度为100%才可以。

支付宝小程序默认启用了virtualHost配置不会插入节点,一般不存在如上问题。

#vendor.js过大的处理方式

小程序工具提示vendor.js过大,已经跳过es6向es5转换。这个转换问题本身不用理会,因为vendor.js已经是es5的了。

关于体积控制,参考如下:

  • 使用运行时代码压缩
    • HBuilderX创建的项目勾选运行-->运行到小程序模拟器-->运行时是否压缩代码
    • cli创建的项目可以在package.json中添加参数--minimize,示例:"dev:mp-weixin": "cross-env NODE_ENV=development UNI_PLATFORM=mp-weixin vue-cli-service uni-build --watch --minimize"
  • 使用分包优化,关于分包优化的说明
UNIAPP注意事项:H5

H5发布到服务器注意:

  1. 配置发行后的路径(发行在网站根目录可不配置),比如发行网站路径是www.xxx.com/html5,在manifest.json文件内编辑h5节点,router下增加base属性为html5
  2. 点击菜单 发行-> H5
  3. 在当下项目下的unpackage/dist/build/h5目录找到出的资源,部署服务器(或者使用本地服务器预览),如需部署到相对路径(支持本地file协议打开)参考:https://ask.dcloud.net.cn/article/37432。

引用第三方js的方式:

  1. 通过npm引入(通过条件编译,只有是h5平台才import相应的库)
  2. 在manifest.json文件编辑h5节点的template属性,填写html模版路径,在html模版里面可以使用script的方式引入三方的js,如下示例是加了百度统计的html模板部分代码,模版全部代码可
<!-- ... -->
<body>
            <noscript>
                <strong>Please enable JavaScript to continue.</strong>
            </noscript>
            <div id="app"></div>
            <!-- built files will be auto injected -->
            <script>
                var _hmt = _hmt || [];
                (function() {
                    var hm = document.createElement("script");
                    hm.src = "https://hm.baidu.com/hm.js?xxxxxx";
                    var s = document.getElementsByTagName("script")[0];
                    s.parentNode.insertBefore(hm, s);
                })();
            </script>
</body>
<!-- ... -->
  • H5版uni-app全支持vue语法,所以可能造成部分写法在H5端生效,在小程序或App端不生效。
  • H5校验了更严格的vue语法,有些写法不规范会报警,比如: data后面写对象会报警,必须写function;不能修改props的值;组件最外层template节点下不允许包含多个节点等。
  • 编译为H5版后生成的是单页应用(SPA)。
  • 如果遇到跨域造成js无法联网,注意网络请求(request、uploadFile、downloadFile等)在浏览器存在跨域限制,解决方案有详见:https://ask.dcloud.net.cn/article/35267
  • APP和小程序的导航栏和tabbar均是原生控件,元素区域坐标是不包含原生导航栏和tabbar的;而H5里导航栏和tabbar是div模拟实现的,所以元素坐标会包含导航栏和tabbar的高度。为了优雅的解决多端高度定位问题,uni-app新增了2个css变量:--window-top和 --window-bottom,这代表了页面的内容区域距离顶部和底部的距离。举个实例,如果你想在原生tabbar上方悬浮一个菜单,之前写bottom:0。这样的写法编译到h5后,这个菜单会和tabbar重叠,位于屏幕底部。而改为使用bottom:var(--window-bottom),则不管在app下还是在h5下,这个菜单都是悬浮在tabbar上浮的。这就避免了写条件编译代码。当然仍然也可以使用H5的条件编译处理界面的不同。
  • CSS內使用vh单位的时候注意100vh包含导航栏,使用时需要减去导航栏和tabBar高度,部分浏览器还包含浏览器操作栏高度,使用时请注意。
  • 正常支持rpx,px是真实物理像素。暂不支持通过设manifest.json的 "transformPx" : true,把px当动态单位使用。
  • 使用罗盘、地理位置、加速计等相关接口需要使用https协议,本地预览(localhost)可以使用http协议。
  • PC端Chrome浏览器模拟器设备测试的时候,获取位置API需要连接谷歌服务器。
  • 组件内(页面除外)不支持onLoad、onShow等页面生命周期。
  • 为避免和内置组件冲突,自定义组件请加上前缀(但不能是u和uni)。比如可使用的自定义组件名称:my-view、m-input、we-icon,例如不可使用的自定义组件名称:u-view、uni-input,如果已有项目使用了可能造成冲突的名称,请修改名称,另外微信小程序下自定义组件名称不能以wx开头。
  • 当前日期:
  • 北京时间:
  • 时间戳:
  • 今年的第:18周
  • 我的 IP:18.118.126.145
农历
五行
冲煞
彭祖
方位
吉神
凶神
极简任务管理 help
+ 0 0 0
Task Idea Collect