由dcloud 公司开发的 多端融合框架
1次开发 多端运行
竞品:apiCloud ,appCan ,Codova
技术架构
Hybrid混合开发端
各种小程序(微信为主)
02 配置模拟器的端口
夜神模拟器端口号:62001
海马模拟器端口号:26944
逍遥模拟器端口号:21503
MuMu模拟器端口号:7555
天天模拟器端口号:6555
雷电模拟器端口号:5555
03 运行到模拟器
注意项
hbuilder可能需要下载对应的插件
运行到安卓模拟器,有视图差别
运行可以需要一定的诗句
<view class="title">文本渲染</view>
<view>{{title}}</view>
<view v-text="title"></view>
<view>{{2+3}}</view>
<view>{{title.length}}</view>
<view>{{title.split("").reverse().join("")}}</view>
<view>{{title.length>15?'长度很长':'字少事大'}}</view>
<view v-html="str"></view>
data() {
return {
title: '你好我是uni-app',
num: 5, //定义num默认值是5
str: "社会主义好呱呱好!",
}
},
<view class="title">条件渲染</view>
<view v-if="isLog">欢迎回来主人</view>
<view v-else>请登录</view>
<view v-show="isLog">欢迎欢迎</view>
<view v-show="!isLog">新冠请走开</view>
<view v-if="score>=90">奖励</view>
<view v-else-if="score>=80">送一辆</view>
<view v-else-if="score>=70">给</view>
<view v-else-if="score>=60">给你</view>
<view v-else> 打了送医院</view>
data() {
return {
isLog: true, //是否登录
score: 55,
}
},
{{index+1}} {{item}}
<view class="title">列表渲染</view>
<view>--遍历列表</view>
<!-- item与index自定义 in固定语法 list是data中的变量 -->
<view v-for="(item,index) in list" :key="index+item">{{item}}</view>
<view>--遍历对象</view>
<view v-for="(value,key) in obj" v-bind:key="key">{{value}}</view>
<view>--遍历数字</view>
<view v-for="item in 5" :key="item+'s'">{{item}}</view>
<view>--遍历字符串</view>
<view v-for="(s,i) in title" :key="i+'d'">{{s}}</view>
<view class="title">属性渲染</view>
<button type="primary" v-bind:disabled="isLog" @click="isLog=!isLog">按钮</button>
<button type="warn" :disabled="!isLog" @click="isLog=!isLog">按钮</button>
<view class="title">表单绑定</view>
<!-- 输入 -->
<view>{{title}}-{{time}} - {{num}}</view>
<!-- 通过:value属性实现对表单单向绑定 -->
<!-- 通过v-model 对表单进行双向绑定(input启用) -->
<!-- input默认是没有样式 -->
<input placeholder="请输入..." v-model="title"></input>
<!-- 选择 -->
<picker :value="time" mode="time" start="09:01" end="21:01" @change="time=$event.detail.value" >
<view class="uni-input">{{time}}</view>
</picker>
<!-- 滑块 -->
<slider :value="num" step="5" @change="num=$event.detail.value" />
data() {
return {
time:"12:01",,
num: 5, //定义num默认值是5
}
},
<view class="title">事件</view>
<button v-on:click="num++" size="mini" type="primary">{{num}}事件绑定</button>
<button @click="num++" size="mini" type="warn">{{num}}事件绑定-简写</button>
<button @click="say" size="mini" type="primary">响应函数</button>
<button @click="say('你好小小真')" size="mini" type="warn">响应函数-传参</button>
<button type="primary" @click="doit" :data-title="title">事件对象</button>
methods: {
doit(e){
console.log(e);
uni.showModal({
title:e.target.dataset.title
})
},
say(str="你好"){
uni.showToast({
title:str
})
}
},
data() {
return {
num: 5, //定义num默认值是5
}
},
pages.json
globalStyle
全局样式data
数据methods
方法computed
计算watch
监听directive
指令filte
r过滤// #ifdef APP-PLUS
plus.navigator.setFullscreen(true);
// #endif
页面onUnload() 函数中添加
// #ifdef APP-PLUS
plus.navigator.setFullscreen(false);
// #endif
备注:若在页面unLoad() 时未调用plus.navigator.setFullscreen(false)
;,将导致退出当前页面后其他所有页面的状态栏也都被隐藏了。
// #ifdef APP-PLUS
plus.navigator.setFullscreen(true);//隐藏状态栏(应用全屏:只能隐藏状态栏,标题栏和虚拟返回键都还可以显示)
// #endif
备注:若在页面unLoad() 时未调用plus.navigator.setFullscreen(false);,将导致退出当前页面后其他所有页面的状态栏也都被隐藏了
beforeCreate
created
beforeMount
mounted
beforeUpdate
updated
beforeDestroy
destroyed
onLoad
加载
onShow
显示
onReady
准备
onHide
后台运行
onUnload
卸载
onLoad() {
console.log("onload");
},
mounted() {
console.log("mounted");
},
onReady() {
console.log("onReady");
},
onShow() {
console.log("onShow");
},
onPullDownRefresh
下拉刷新onReachBottom()
触底更新onShareAppMessage
右上角分享onPageScroll
页面滚动onShareTimeline
分享到朋友圈<template>
<view>
<view v-for="(item,index) in list" :key="index">
<view class="item">
{{item.summary}}
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
list: [], //存放笑话
page: 1, //当前页
}
},
created() {
//初始化调用获取笑话
this.getjok();
},
//下拉的时候
//下拉刷新把数据添加到前面
onPullDownRefresh() {
//获取笑话
this.getjok();
},
//触底刷新
onReachBottom() {
//触底更新把数据添加到后面
this.getjok(2)
},
// param {Number] type = [1]1代表下拉刷新,2代表触底更新
methods: {
//获取笑话
getjok(type = 1) {
var that = this;
uni.request({
url: 'http://dida100.com/mi/list.php', //仅为示例,并非真实接口地址。
data: {
page: that.page
},
method: "GET",
header: {
'custom-header': 'hello' //自定义请求头信息
},
success: (res) => {
// 02 更新数据list和page
console.log(res.data);
// concat是链接两个数组,list数据和result数组
//为什么用concat?不用有别的方法
// concat就是连接两个数组,可以同push和splice_对数组讲行操作
if(type===1){
that.list = res.data.result.concat(that.list);
uni.showToast({
title:"更新"+res.data.result.length+"条数据",
icon:"none"
})
}else{
that.list = that.list.concat(res.data.result);
}
//更新page (方便下次请求)
that.page++;
},
//成功获取或者失败都要停止下拉刷新
complete() {
//停止下拉刷新
uni.stopPullDownRefresh()
}
});
}
}
}
//目标:展示笑话信息
//方法请求笑话信息写在methods中 get3ok
//方法在哪儿调用呢?created mounted生命周期调用get3ok
//笑话分页:在data中定义存放笑话的变量List,存放当前页的page
//在getJok中更新List和page实现更新视图
//数据有哪些 data
//方法有哪些 methods
//怎么处理方法 更新数据 展示数据
</script>
<style>
.item {
padding: 30rpx;
border-bottom: 1px solid #ccc;
}
</style>
navigator
导航
open-type
打开类型
navigate
跳转redirect
重定向(当前页面不留历史记录)navigateBack
返回relauch
重启switchTab
跳转底部栏 <button type="default" @click="goOption" size="mini">go选项</button>
<button type="primary" @click="goIndex" size="mini">go index</button>
<navigator url="../options/options?count=5&title=来自life">选项</navigator>
<navigator url="../index/index" open-type="redirect">index页面(不会有返回按钮)</navigator>
methods: {
goOption(){
//跳转并传参
uni.navigateTo({
url:"/pages/options/options?count=100&title=来自js跳转"
})
},
goIndex(){
//重定向
uni.redirectTo({
url:"/pages/index/index"
})
},
url:path?name=mumu&age=18
onLoad(option){}
option的值{name:"mumu",age:18}
uni.navigateTo({url})
跳转uni.redirectTo({url})
重定向uni.navigateBack()
返回uni.switchTab()
底部栏切换uni.reLaunch()
重启"tabBar": {
"color": "#777", //文字颜色
"selectedColor": "#ff557f",//选中文字颜色
"list": [ // 2-5
{
"pagePath": "pages/index/index", //页面地址
"text": "首页",//文本
"iconPath": "/static/tabBar/index.png",//图标颜色
"selectedIconPath": "/static/tabBar/indexed.png" //选中图标颜色
},
{
"pagePath": "pages/life/life",
"text":"生命",
"iconPath": "/static/tabBar/categoryed.png",
"selectedIconPath": "/static/tabBar/category.png"
}
]
},
1、检查是否是跳转至TabBar页面,如果是TabBar页面,则需要用uniapp.switchTab进行跳转;
2、检查跳转路径是否写正确。
3、可以打印错误信息进行检查,具体如下面代码注释部分所示。
tapupdate(){
this.updatetap = !this.updatetap
//调取发布时存储的数据然后跳转页面并进行渲染...
uni.switchTab({
url:'../publish/publish',
// fail (error) {
// console.log(error)
// }
})
}
需要注意:vue的本地存储方式, 小程序在浏览器测试时也可以实现, 但是在真机运行时不能实现
uni.setStorage(object)
uni.setStorageSync(key, data)
try{
uni.setStorageSync('token', '123456')
} catch (e){
//错误
}
uni.getStorage(OBJECT)
从本地存储中异步获取对应可以对应的内容
uni.getStorageSync(key)
从本地缓存中同步获取指定key对应的内容
try {
const value = uni.getStorageSync("token");
if(value) {
console.log(value)
}
} catch(e){
//错误
}
uni.removeStorage(object)
从本地缓存中异步移除指定key
uni.removeStorageSync(key)
从本地缓存中同步移除指定key
try {
uni.removeStorageSync('storage_key')
} catch(e){
//错误
}
定义globalData:{num:100}
var app = getApp()
onShow(){ this.num = app.globalData.num }
addNum(){ app.globalData.num++; this.num = app.globalData.num }
获取当前的页面栈,是一个数组(1-5)
var page = getCurrentPages();
page[page.length-1] 获取当前页面的信息
(不要去修改)
uni.navigateBack({delta:page.length})
目的:不同的平台展示不同特性与功能
<template>
<view class="condition">
<view>条件</view>
<!-- H5手机页面中,提示用户<applet></applet> -->
<!-- #ifdef H5 -->
<view class="">H5:下载app,获取优惠卷</view>
<!-- #endif -->
<!-- #ifdef MP -->
<view class="">wx:小程序用户优惠卷5元</view>
<!-- #endif -->
<!-- #ifdef APP -->
<view class="">app 优惠卷5元 </view>
<!-- #endif -->
<view class="active">我是一行可爱的文字</view>
<button size="mini" @click="say()">你好</button>
<!-- #ifdef APP || MP-WEIXIN -->
<navigator url="/pages/condition/we">微信-App专有</navigator>
<!-- #endif -->
</view>
</template>
<script>
export default {
**js编译**
methods: {
say(){
// #ifdef APP-PLUS
uni.showModal({
title:"你好App用户"
})
// #endif
// #ifdef MP
uni.showToast({
title:"你好微信用户"
})
// #endif
// #ifdef H5
uni.showModal({
title:"你好,手机用户"
})
// #endif
}
}
}
</script>
**css条件编译**
<style>
/* #ifdef APP-PLUS */
.active{color: red;}
.condition{
padding-top: var(--status-bar-height);
/* 状态栏(电量条高度) */
}
/* #endif */
/* #ifdef H5 */
.active{color: blue;}
/* #endif */
/* #ifdef MP */
.active{color: aqua;}
/* #endif */
</style>
{
"path": "pages/condition/condition",
"style": {
"navigationBarTitleText": "首页",
"enablePullDownRefresh":false,
"h5":{
"titleNView": {
"titleText": "我是h5"
}
},
"app-plus": {
"titleNView":false //隐藏导航栏
}
}
},
// #ifdef MP-WEIXIN || APP
{
"path": "pages/condition/we",
"style": {
"navigationBarTitleText": "小程序独有页面"
}
},
// #endif
props:{ // 接收参数value value:{ type:Number, //数字类型默认值为1 default:1, } }
this .count = this.value
this.$emit("input",this.count)
uni.$on("事件名",事件值)
uni.$on("事件名",$event=>{响应操作})
uview
官网
uview的配置
创建store目录,在index.js文件中导入vuex
// 导入vuex
import Vuex from 'vuex';
//导入vue
import Vue from 'vue';
// 使用Vuex
Vue.use(Vuex);
//导出Vuex
export default new Vuex.Store({
//状态
state:{
gTitle:{
text:"你好vuex",
color:"#000",
fontSize:"24px",
background:"#f70"
},
},
//改变状态的唯一方法
mutations:{},
//异步api操作
actions:{},
//内部计算
getters:{},
//模块
modules:{},
})
在main.js中定义全局$store
//导入vuex
import store from './store/index.js'
//导入定义全局$store
Vue.prototype.$store = store;
<view>图片操作</view>
<view class="">选择与预览图片</view>
<button @click="selectPic">选择</button>
<view v-for="item in list" :key="item">
<image :src="item" mode=""></image>
</view>
<script>
export default {
data() {
return {
list: [],
}
},
onLoad() {},
methods: {
selectPic() {
var that = this;
//选择图片
uni.chooseImage({
count: 3, //默认选3张
success(res) {
//遍历结果
for (let i = 0; i < res.tempFilePaths.length; i++) {
//上传图片
uni.uploadFile({
//上传地址
url: 'http://520mg.com/ajax/file.php',
//图片信息
filePath: res.tempFilePaths[i],
// name需要和后端约定,默认都会叫file
name: 'file',
success:result => {
//转换为json
var data = JSON.parse(result.data);
//添加域名后加入list
that.list.push("http://520mg.com"+data.pic);
}
})
}
//上传到服务器
}
})
}
}
}
</script>
<template>
<view>
<view class="title">分享</view>
<!-- #ifdef MP -->
<button open-type="share">分享</button>
<!-- #endif -->
<button type="primary" size="mini" @click="shareIt">分享得积分</button>
</view>
</template>
<script>
export default {
//特别提醒在小程序中,没有这两个生命周期,页面默认没有分享功能
onShareAppMessage() {
//分享
return{
title:"送你鸽子",
path:"/page/global/global",
imageUrl:"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic1.win4000.com%2Fwallpaper%2Ff%2F57a42b9002e19.jpg&refer=http%3A%2F%2Fpic1.win4000.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1672453197&t=f36363af4b6ce3847fffb420d9a4fee5"
}
},
onShareTimeline() {
//分享到朋友圈
return{
imageUrl:"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic1.win4000.com%2Fwallpaper%2Ff%2F57a42b9002e19.jpg&refer=http%3A%2F%2Fpic1.win4000.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1672453197&t=f36363af4b6ce3847fffb420d9a4fee5"
}
},
data() {
return {
}
},
methods: {
//特别注意
//实现分享,打包上传的时候
//第一步,打开 manifest.json -> App模块权限配置,勾选 Share(分享);
//第二步,通过 https: // open.weixin. qq.com/注册获取分享id(默认用的huilder的id)
shareIt(){
uni.share({
provider: "weixin",
scene: "WXSceneSession", //微信聊天
type: 0,
href: "http://didia100.com",
title: "好书分享",
summary: "白鸽",
imageUrl: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic1.win4000.com%2Fwallpaper%2Ff%2F57a42b9002e19.jpg&refer=http%3A%2F%2Fpic1.win4000.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1672453197&t=f36363af4b6ce3847fffb420d9a4fee5",
success: function (res) {
//判断分享成功可以给积分
console.log("success:" + JSON.stringify(res));
},
fail: function (err) {
console.log("fail:" + JSON.stringify(err));
}
});
}
}
}
</script>
<style>
</style>
<template>
<view>
<view>图片操作</view>
<view class="">选择与预览图片</view>
<button @click="selectPic">选择</button>
<view v-for="item in list" :key="item" @click="preview(item)">
<image :src="item" mode=""></image>
</view>
</view>
</template>
<script>
export default {
data() {
return {
list: [],,
}
},
onLoad() {},
methods: {
preview(item){
var that = this;
//单击通过实现预览
uni.previewImage({
//预览的图片列表
urls:this.list,
current:item, //当前图片
longPressActions:{
//定义长按的按钮
itemList:['发送给朋友','保存图片','收藏'],
success:function(data){
console.log('选中了第'+(data.tapIndex+1)+'个按钮,第'+(data.index+1)+'张图片');
// 保存
if(data.tapIndex==1){
//保存到本地相册
uni.saveImageToPhotosAlbum({
filePath:that.list[data.index],
success() {
uni.showToast({
title:"保存成功"
})
}
})
}
//分享
if(data.tapIndex==0){
//分享给朋友(app打包时候分享要去微信的开发平台注册)
uni.share({
provider:'weixin',
scene:'WXSceneSession',
type:2,
imageUrl:that.list[data.index],
success:function(res){
console.log("success:"+JSON.stringify(res));
},
fail:function(err){
console.log("fail:"+JSON.stringify(err));
}
})
}
},
fail:function(err){
console.log(err.errMsg);
}
}
})
},
}
}
</script>
<style>
</style>
// 导入axios
import axios from 'axios';
const baseURL = "http://api.le.zhiyuintl.com"
//方法
function request(options) {
return new Promise((resolve, reject) => {
//获取url
var url = options.url;
//是否是http或者https开头的正则
var re = /^http?/;
// 如果不是就加baseURL
if (!re.test(url)) {
url = baseURL + url;
}
//请求头
var header = options.header || {};
//添加token
header.Authorization = "Bearer " + uni.getStorageSync("token");
//添加公用请求头
header.channel = "h5";
//如果有loading
if (options.loading) {
uni.showLoading({
...options.loading
})
}
//发起网络请求
uni.request({
url, //地址
header, //请求头
method: options.method || "GET",
data:options.data || "",
// method:"POST",
success(res) {
//如果没有权限
if (res.statusCode === 401) {
uni.showToast({
title: "没有权限"
})
reject(res);
} else {
resolve(res);
}
},
fail(err) {
reject(err)
},
complete() {
//如果有加载中,结束加载提示
if (options.loading) {
uni.hideLoading()
}
}
})
})
}
// 定义post简易方法
request.post=(url,data,config)=>{
return request({...config,url,method:"POST",data})
}
//定义get简易方法
request.get=(url,config)=>{
return request({...config,url,method:"GET"})
}
// 定义delete简易方法
request.delete=(url,data,config)=>{
return request({...config,url,method:"DELETE",data})
}
// 定义put简易方法
request.put=(url,data,config)=>{
return request({...config,url,method:"PUT",data})
}
//导入默认request
export default request;