小程序和Vue+uniapp+unicloud培训课件
文章目录
- **一、什么是小程序**
- 二、Vue简介
- **2.1 Vue**的定义
- 2.2 Vue的特点
- **2.3 Vue**的使用
- 2.4 MVVM软件架构模式
- 三、uniapp
- 3.1 什么是uni-app?
- 3.2 快速上手
- 3.2.1 创建uni-app
- 3.2.2 uni-app工程目录结构
- 3.2.3 页面简介
- 新建页面
- 删除页面
- 应用首页
- 页面生命周期
- 组件生命周期
- 路由
- 路由跳转
- 页面栈
- 相互引用
- 3.2.4 运行uni-app
- 3.2.5 发布uni-app
- 打包为原生App
- 发布为Web网站
- 发布为微信小程序
- 四、 unicloud
- 五、 项目案例
- 4.4 快速上手
- 4.4.1 创建uniCloud项目
- 4.4.2 关联服务空间
- 4.4.3 创建云函数/云对象
- 五、 项目案例
一、什么是小程序
1.1 小程序简介
小程序是一种新型的应用程序,它是运行在移动设备上的应用程序,用户可以在不下载和安装应用的情况下直接使用。
1.2 小程序的特点
- 快速启动:小程序无需下载和安装,用户可以直接通过扫码或搜索进入小程序。
- 轻量级:小程序的体积相对较小,不会占用太多存储空间,可以随时随地使用。
- 原生体验:小程序采用原生技术开发,可以提供更加流畅的用户体验。
- 易于分享:小程序可以通过二维码、微信分享等方式进行传播,可以快速扩大影响力。
1.3 小程序的开发流程
小程序的开发流程主要包括以下几个步骤:
-
注册小程序账号:注册小程序账号,获取小程序开发资格。 开发小程序的第一步,需要拥有一个小程序 AppID,后续的所有开发流程会基于这个 AppID 来完成。小程序的注册非常简单,只需几个操作。
使用浏览器打开 https://mp.weixin.qq.com/ 点击立即注册
个人小程序和企业小程序的区别
一,注册时的区别:
个人版的注册需要的“资质”极少,几乎只要个人的身份信息就可以。注册流程简化许多。
企业版的注册则繁琐许多,需要提供管理者的身份信息的同时,企业的各项资质、对公账号、企业验证等等,要提供一系列的证明和验证。
个人版的注册时不需要收取300元的 认证费用的(因为个人版暂时不支持 认证)
企业版的 认证就需要收取300元
二,开发的小程序性质不同:
接口限制
个人主体的小程序肯定是无法完整地使用小程序的接口和能力的,具体哪些接口用不了呢?
- 微信支付
如需使用微信支付,就必须先开通微信支付商户账号,而开通商户号必须是具备企业资格,个人资质无法开通商户账号。
如小程序需要接入微信支付,小程序本身必须要经过微信认证才行,而个人主体注册的小程序是不支持认证的。
所以,这是一个限制:个人主体注册的小程序不能使用微信支付!
- 卡券
在微信里,卡券的分类众多,其中就包含了具有储值功能会员卡,像这种会员卡涉及到用户财产安全的接口肯定会受到严格的监管,而个人主体注册的小程序风险大,微信自然不能让你使用。
- 获取微信用户绑定的手机号码
微信在近期更新中,开放了快速填写手机号,直接获取用户微信绑定的手机号码功能。
但目前这个接口仅开放给已通过微信认证的小程序使用;尚未认证的组织类小程序和个人主体小程序,都无法使用这个功能。
4.个人版附近小程序是没办法显示
附近小程序是根据营业执照注册地址定位的。
三,企业高级接口
接口一:OAuth2.0网页授权、获取用户基本信息
这两个接口是此次开放对于微网站类应用最重要的技术保证,在OAuth2.0接口的支援下,可做到真正的微信用户状态保持、信息拉取(昵称、性别、 地区 等),可真正实现微网站用户免注册。该接口目前唯一的不爽是只 能在微信环境内使用,但是相信随着微信开放程度加强、同类竞争对手的进入,该接口应该会更加开放。不过,仅仅目前的开放程度,已经足够我们把微网站做得更 好。
接口二:客服接口
该接口是简化版的“消息下发接口”,曾今也是第三方开发公司梦寐以求的接口之一,其基本应用原理是当用户主动发送一条信息给公众平台后,公众平台可 在24小时内,无限的向该用户推送消息。此接口最重要的产品应用就是可以开发类似QQ或旺旺一样的微信客服系统。另外,也为自动回复机器人的应用,也带来 了更多的想象空间。
接口三:生成带参数二维码
该接口可以实现大家一直期盼的扫码场景:
场景一:以微信生意宝的客户“Logitech/罗技”为例,罗技公司在全国有N多家代理门店,利用该接口,罗技公司可以对不同的门店设置不同的微信二维码,这样就可以判断出粉丝是在哪家门店扫码关注的了,这也是运营人员的福音。
场景二:例如公司官网上有多个活动,都在通过二维码推广公众平台,如何统计出哪个活动带来的新粉丝最多?利用这个接口,这个问题也就不是问题咯~~
所以,此接口必将成为一个微信推广利器,不过,腾讯目前对这个接口稍作了限制,目前微信最多只支持生成1000个永久参数的二维码,但是可以无限制生成带临时参数的二维码(临时参数有效期30分钟)。
接口四:获取用户地理位置
O2O服务最具有科技感的服务形式,就是基于位置提供不同的服务、给用户提供不同的信息,该接口区别于目前微信聊天窗口中发送地理位置的功能,最大 的区别的是,该接口是以事件的形式自动上报给公众平台的,用户无法作假,也无须操作(当然,一开始需要用户授权同意)。该接口开放后可以给其他接口服务提 供前 置参数,由此可实现很多基于地理位置的组合应用,例如:实现景点微信导游,当用户走到不同的地方,发送个“导游”两个字给公众平台,系统将自动推送给用户 当前的景点信息,如果这个功能和客服系统对接,就可自动实现按照客户目前所在的区域自动分流。
接口五:获取关注者列表、用户分组接口
这两个接口可以配合获取用户基本信息接口,让微信用户可以脱离微信后台,直接在微网站后台进行客户的维护与管理,使得微网站后台更加实用高效。
接口六:语音识别
应该说这个接口是腾讯为我们提供的下酒小菜,如果合理应用,可做出更多有意思的应用和游戏。他的基本流程是这样的:用户向聊天窗口发送语音信息,微 信会把识别的文字结果也反馈给微信生意宝系统,这样就等同于发送了文字消息。比如,以后用户想要回复微网站的首页,除了可以输入文字“首页”或图标外,用 户也可以对着手机大喊一声“芝麻开门”,也能出现微网站首页。
以上是微信新开放的接口简单说明,除了这些高级接口,其实还有一些我们现在已经在使用的操作微信的客户端的脚本接口,正式开放,例如:隐藏微信中网页右 上角按钮,隐藏微信中网页底部导航栏等,另外网页获取用户网络状态的接口,对于微网站应用还是比较重要的,我们可以识别用户当前使用的是wifi还是3g 网络,以便决定信息怎么展示,帮助用户省流量、省钱。另外,对于HTML5应用,该状态的获取,可充分发掘HTML5本地应用程序的威力。
-
开发小程序:使用小程序开发工具进行开发,包括界面设计、数据管理、业务逻辑等方面。安装开发者工具
在小程序开发文档中找到小程序开发工具的下载页面,或者直接输入 https://mp.weixin.qq.com/debug/wxadoc/dev/devtools/download.html 根据自己的操作系统下载对应的安装包进行安装。需要注意的是,小程序开发工具在 Windows上仅支持 Windows 7 及以上版
-
提交审核:将开发完成的小程序提交到微信小程序平台进行审核。
-
发布上线:审核通过后,可以将小程序发布上线,供用户使用。
1.4 小程序代码构成
1.4.1 JSON 配置
JSON 是一种数据格式,并不是编程语言,在小程序中,JSON扮演的静态配置的角色。
相比于XML ,JSON格式最大的优点是易于人的阅读和编写,通常不需要特殊的工具,就能读懂和修改,是一种轻量级的数据交换格式。
JSON文件都是被包裹在一个大括号中 {},通过key-value的方式来表达数据。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FJb8ieRb-1677491373212)(C:\Users\Administrator\AppData\Local\Temp\1677412175702.png)]
JSON的Key必须包裹在一个双引号中,在实践中,编写 JSON 的时候,忘了给 Key 值加双引号或者是把双引号写成单引号是常见错误。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l63RH5IN-1677491373220)(C:\Users\Administrator\AppData\Local\Temp\1677412214164.png)]
JSON的值只能是以下几种数据格式:
- 数字,包含浮点数和整数
- 字符串,需要包裹在双引号中
- Bool值,true 或者 false
- 数组,需要包裹在方括号中 []
- 对象,需要包裹在大括号中 {}
- Null
其他任何格式都会触发报错,例如 JavaScript 中的 undefined 。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UtsiaAEK-1677491373223)(C:\Users\Administrator\AppData\Local\Temp\1677412273203.png)]
还需要注意的是 JSON 文件中无法使用注释,试图添加注释将会引发报错。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EtXIQAoO-1677491373225)(C:\Users\Administrator\AppData\Local\Temp\1677412317671.png)]
1.4.2 WXML 模板
WXML 全称是 WeiXin Markup Language,是小程序框架设计的一套标签语言,结合小程序的基础组件、事件系统,可以构建出页面的结构。
从事过网页编程的人知道,网页编程采用的是 HTML + CSS + JS 这样的组合,其中 HTML
是用来描述当前这个页面的结构,CSS
用来描述页面的样子,JS
通常是用来处理这个页面和用户的交互。
同样道理,在小程序中也有同样的角色,其中 WXML
充当的就是类似 HTML
的角色。
一个完整的 WXML语句由一段开始标签和一段结束标签组成,在标签中可以是内容,也可以是其他的 WXML 语句,这一点上同 HTML 是一致的。有所不同的是,WXML 要求标签必须是严格闭合的,没有闭合将会导致编译错误。
标签可以拥有属性,属性提供了有关的 WXML元素更多信息。属性总是定义在开始标签中,除了一些特殊的属性外,其余属性的格式都是key=“value” 的方式成对出现。需要注意的是,WXML中的属性是大小写敏感的,也就是说 class 和 Class 在WXML中是不同的属性,代码2-3是一个文本标签的示例。
数据绑定
用户界面呈现会因为当前时刻数据不同而有所不同,或者是因为用户的操作发生动态改变,这就要求程序的运行过程中,要有动态的去改变渲染界面的能力。在 Web 开发中,开发者使用 JavaScript 通过Dom 接口来完成界面的实时更新。在小程序中,使用 WXML 语言所提供的数据绑定功能,来完成此项功能。
先看一个简单的例子。
数据绑定示例
<!--pages/wxml/index.wxml-->
<text>当前时间:{{time}}</text>
保存后工具刷新,模拟器并没有显示出当前的时间,这是因为我们并没有给 time 设置任何初始值,请打开 index.js 文件,在 data 的大括号中加入:time: (new Date()).toString()
。
数据绑定示例
// pages/wxml/index.js
Page({/*** 页面的初始数据*/data: {time: (new Date()).toString()},
})
保存,模拟器刷新后正确的展示了当前时间,并且每次编译时间都会被更新。
WXML 通过 {{变量名}} 来绑定 WXML 文件和对应的 JavaScript 文件中的 data 对象属性。
后文中为了保持简单,通过以下格式来展示上述的代码逻辑,使用第一段注释来表明 WXML 对应的脚本文件中的 data 结构。
<!--
{time: (new Date()).toString()
}
-->
<text>当前时间:{{time}}</text>
属性值也可以动态的去改变,有所不同的是,属性值必须被包裹在双引号中,如下:
属性值的绑定
<!-- 正确的写法 -->
<text data-test="{{test}}"> hello world</text><!-- 错误的写法 -->
<text data-test={{test}}> hello world </text >
需要注意的是变量名是大小写敏感的,也就是说 {{name}} 和 {{Name}} 是两个不同的变量。
代码清单2-9 绑定的变量大小写敏感
<!--
{w: 'w',W: 'W'
}
--><view>{{w}}</view>
<view>{{W}}</view><!-- 输出
w
W
-->
还需要注意,没有被定义的变量的或者是被设置为 undefined 的变量不会被同步到 wxml 中,如代码2-10所示。
代码清单2-10 undefined值不会被输出到 wxml 中
<!--
{var2: undefined,var3: null,var4: "var4"
}
--><view>{{var1}}</view>
<view>{{var2}}</view>
<view>{{var3}}</view>
<view>{{var4}}</view><!--
输出:
null
var4
-->
逻辑语法
通过 {{ 变量名 }} 语法可以使得 WXML 拥有动态渲染的能力,除此外还可以在 {{ }} 内进行简单的逻辑运算。
三元运算:
<!-- 根据 a 的值是否等于 10 在页面输出不同的内容 -->
<text>{{ a === 10? "变量 a 等于10": "变量 a 不等于10"}}</text>
算数运算:
<!--
{ a: 1, b: 2, c: 3 }
--><view> {{a + b}} + {{c}} + d </view><!-- 输出 3 + 3 + d -->
类似于算数运算,还支持字符串的拼接,如代码2-11所示。
字符串的拼接
<!--
{ name: 'world' }
--><view>{{"hello " + name}}</view><!-- 输出 hello world -->
{{ }}中还可以直接放置数字、字符串或者是数组
常量
<text>{{[1,2,3]}}</text><!-- 输出 1,2,3 --><text>{{"hello world"}}</text><!-- 输出 hello world -->
条件逻辑
WXML 中,使用 wx:if=“{{condition}}” 来判断是否需要渲染该代码块:
<view wx:if="{{condition}}"> True </view>
使用 wx:elif 和 wx:else 来添加一个 else 块:
<view wx:if="{{length > 5}}"> 1 </view>
<view wx:elif="{{length > 2}}"> 2 </view>
<view wx:else> 3 </view>
因为 wx:if 是一个控制属性,需要将它添加到一个标签上。如果要一次性判断多个组件标签,可以使用一个 <block/>
标签将多个组件包装起来,并在上边使用 wx:if 控制属性。
<block wx:if="{{true}}"><view> view1 </view><view> view2 </view>
</block>
列表渲染
在组件上使用 wx:for 控制属性绑定一个数组,即可使用数组中各项的数据重复渲染该组件。默认数组的当前项的下标变量名默认为 index,数组当前项的变量名默认为 item
列表渲染示例
<!-- array 是一个数组 -->
<view wx:for="{{array}}">{{index}}: {{item.message}}
</view><!-- 对应的脚本文件
Page({data: {array: [{message: 'foo',}, {message: 'bar'}]}
})
-->
使用 wx:for-item 指定数组当前元素的变量名,使用 wx:for-index 指定数组当前下标的变量名:
<view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName">{{idx}}: {{itemName.message}}
</view>
类似 block wx:if
,也可以将 wx:for
用在 <block/>
标签上,以渲染一个包含多节点的结构块。例如:
<block wx:for="{{[1, 2, 3]}}"><view> {{index}}: </view><view> {{item}} </view>
</block>
如果列表中项目的位置会动态改变或者有新的项目添加到列表中,并且希望列表中的项目保持自己的特征和状态(如 <input/>
中的输入内容, <switch/>
的选中状态),需要使用 wx:key
来指定列表中项目的唯一的标识符。
wx:key
的值以两种形式提供:
- 字符串,代表在 for 循环的 array 中 item 的某个 property,该 property 的值需要是列表中唯一的字符串或数字,且不能动态改变。
- 保留关键字 this 代表在 for 循环中的 item 本身,这种表示需要 item 本身是一个唯一的字符串或者数字,如:
当数据改变触发渲染层重新渲染的时候,会校正带有 key 的组件,框架会确保他们被重新排序,而不是重新创建,以确保使组件保持自身的状态,并且提高列表渲染时的效率。
使用 wx:key 示例(WXML)
<switch wx:for="{{objectArray}}" wx:key="unique" > {{item.id}} </switch>
<button bindtap="switch"> Switch </button>
<button bindtap="addToFront"> Add to the front </button><switch wx:for="{{numberArray}}" wx:key="*this" > {{item}} </switch>
<button bindtap="addNumberToFront"> Add Number to the front </button>
使用 wx:key 示例(JavaScript)
Page({data: {objectArray: [{id: 5, unique: 'unique_5'},{id: 4, unique: 'unique_4'},{id: 3, unique: 'unique_3'},{id: 2, unique: 'unique_2'},{id: 1, unique: 'unique_1'},{id: 0, unique: 'unique_0'},],numberArray: [1, 2, 3, 4]},switch: function(e) {const length = this.data.objectArray.lengthfor (let i = 0; i < length; ++i) {const x = Math.floor(Math.random() * length)const y = Math.floor(Math.random() * length)const temp = this.data.objectArray[x]this.data.objectArray[x] = this.data.objectArray[y]this.data.objectArray[y] = temp}this.setData({objectArray: this.data.objectArray})},addToFront: function(e) {const length = this.data.objectArray.lengththis.data.objectArray = [{id: length, unique: 'unique_' + length}].concat(this.data.objectArray)this.setData({objectArray: this.data.objectArray})},addNumberToFront: function(e){this.data.numberArray = [ this.data.numberArray.length + 1 ].concat(this.data.numberArray)this.setData({numberArray: this.data.numberArray})}
})
模板
WXML提供模板(template),可以在模板中定义代码片段,然后在不同的地方调用。使用 name 属性,作为模板的名字。然后在 <template/>
内定义代码片段,如:
定义模板
<template name="msgItem"><view><text> {{index}}: {{msg}} </text><text> Time: {{time}} </text></view>
</template>
使用 is 属性,声明需要的使用的模板,然后将模板所需要的 data 传入。
模板使用示例
<!--
item: {index: 0,msg: 'this is a template',time: '2016-06-18'
}
--><template name="msgItem"><view><text> {{index}}: {{msg}} </text><text> Time: {{time}} </text></view>
</template><template is="msgItem" data="{{...item}}"/><!-- 输出
0: this is a template Time: 2016-06-18
-->
is可以动态决定具体需要渲染哪个模板。
动态使用模板
<template name="odd"><view> odd </view>
</template><template name="even"><view> even </view>
</template><block wx:for="{{[1, 2, 3, 4, 5]}}"><template is="{{item % 2 == 0 ? 'even' : 'odd'}}"/>
</block><!-- 输出
odd
even
odd
even
odd
-->
引用
WXML 提供两种文件引用方式import和include。
import 可以在该文件中使用目标文件定义的 template,如:
在 item.wxml 中定义了一个叫 item的 template :
<!-- item.wxml -->
<template name="item"><text>{{text}}</text>
</template>
在 index.wxml 中引用了 item.wxml,就可以使用 item模板:
<import src="item.wxml"/><template is="item" data="{{text: 'forbar'}}"/>
需要注意的是 import 有作用域的概念,即只会 import 目标文件中定义的 template,而不会 import 目标文件中 import 的 template,简言之就是 import 不具有递归的特性。
例如:C 引用 B,B 引用A,在C中可以使用B定义的 template,在B中可以使用A定义的 template ,但是C不能使用A定义的template.
模板 A
<!-- A.wxml -->
<template name="A"><text> A template </text>
</template>
模板 B
<!-- B.wxml -->
<import src="a.wxml"/><template name="B"><text> B template </text>
</template>
模板 C
<!-- C.wxml -->
<import src="b.wxml"/><template is="A"/> <!-- 这里将会触发一个警告,因为 b 中并没有定义模板 A --><template is="B"/>
include 可以将目标文件中除了 <template/> <wxs/>
外的整个代码引入,相当于是拷贝到 include 位置。
index.wxml
<!-- index.wxml -->
<include src="header.wxml"/><view> body </view><include src="footer.wxml"/>
header.wxml
<!-- header.wxml -->
<view> header </view>
footer.wxml
<!-- footer.wxml -->
<view> footer </view>
共同属性
所有wxml 标签都支持的属性称之为共同属性,如表2-1所示。
共同属性
属性名 | 类型 | 描述 | 注解 |
---|---|---|---|
id | String | 组件的唯一标识 | 整个页面唯一 |
class | String | 组件的样式类 | 在对应的 WXSS 中定义的样式类 |
style | String | 组件的内联样式 | 可以动态设置的内联样式 |
hidden | Boolean | 组件是否显示 | 所有组件默认显示 |
data-* | Any | 自定义属性 | 组件上触发的事件时,会发送给事件处理函数 |
bind*/catch* | EventHandler | 组件的事件 |
1.4.3 WXSS 样式
WXSS(WeiXin Style Sheets)是一套用于小程序的样式语言,用于描述WXML的组件样式,也就是视觉上的效果。
WXSS与Web开发中的CSS类似。为了更适合小程序开发,WXSS对CSS做了一些补充以及修改。WXSS
具有 CSS 大部分的特性,小程序在 WXSS 也做了一些扩充和修改。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CUad84qt-1677491373233)(C:\Users\Administrator\AppData\Local\Temp\1677414122175.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Yegl56EG-1677491373236)(C:\Users\Administrator\AppData\Local\Temp\1677414145584.png)]
项目公共样式:根目录中的app.wxss为项目公共样式,它会被注入到小程序的每个页面。页面样式:与app.json注册过的页面同名且位置同级的WXSS文件。 app.json注册了pages/rpx/index页面,那pages/rpx/index.wxss为页面pages/rpx/index.wxml的样式。
其它样式:其它样式可以被项目公共样式和页面样式引用。
在小程序开发中,开发者不需要像Web开发那样去优化样式文件的请求数量,只需要考虑代码的组织即可。
- 新增了尺寸单位。在写
CSS
样式时,开发者需要考虑到手机设备的屏幕会有不同的宽度和设备像素比,采用一些技巧来换算一些像素单位。WXSS
在底层支持新的尺寸单位rpx
,开发者可以免去换算的烦恼,只要交给小程序底层来换算即可,由于换算采用的浮点数运算,所以运算结果会和预期结果有一点点偏差。 - 提供了全局的样式和局部样式。和前边
app.json
,page.json
的概念相同,你可以写一个app.wxss
作为全局样式,会作用于当前小程序的所有页面,局部页面样式page.wxss
仅对当前页面生效。在CSS中,开发者可以这样引用另一个样式文件:@import url('./test_0.css')
- 此外
WXSS
仅支持部分CSS
选择器
WXSS内联样式与Web开发一致:
<!--index.wxml--><!--内联样式-->
<view style="color: red; font-size: 48rpx"></view>
小程序支持动态更新内联样式:
<!--index.wxml--><!--可动态变化的内联样式-->
<!--
{eleColor: 'red',eleFontsize: '48rpx'
}
-->
<view style="color: {{eleColor}}; font-size: {{eleFontsize}}"></view>
1.4.4 JS 逻辑交互
一个服务仅仅只有界面展示是不够的,还需要和用户做交互:响应用户的点击、获取用户的位置等等。在小程序里边,我们就通过编写 JS
脚本文件来处理用户的操作。
模块化
浏览器中,所有 JavaScript 是在运行在同一个作用域下的,定义的参数或者方法可以被后续加载的脚本访问或者改写。同浏览器不同,小程序中可以将任何一个JavaScript 文件作为一个模块,通过module.exports 或者 exports 对外暴露接口。
请看是一个简单模块示例,B.js 引用模块A,并使用A暴露的multiplyBy2方法完成一个变量乘以 2 的操作。
模块示例
// moduleA.js
module.exports = function( value ){return value * 2;
}
引用模块A
// B.js// 在B.js中引用模块A
var multiplyBy2 = require('./moduleA')
var result = multiplyBy2(4)
在需要使用这些模块的文件中,使用 require(path) 将公共代码引入
var common = require('common.js')
Page({helloMINA: function() {common.sayHello('MINA')},goodbyeMINA: function() {common.sayGoodbye('MINA')}
})
1.5 小程序宿主环境
我们称微信客户端给小程序所提供的环境为宿主环境。小程序借助宿主环境提供的能力,可以完成许多普通网页无法完成的功能。
1.5.1 渲染层和逻辑层
首先,我们来简单了解下小程序的运行环境。小程序的运行环境分成渲染层和逻辑层,其中 WXML 模板和 WXSS 样式工作在渲染层,JS 脚本工作在逻辑层。
小程序的渲染层和逻辑层分别由2个线程管理:渲染层的界面使用了WebView 进行渲染;逻辑层采用 JsCore 线程运行 JS 脚本。一个小程序存在多个界面,所以渲染层存在多个 WebView 线程,这两个线程的通信会经由微信客户端(下文中也会采用 Native 来代指微信客户端)做中转,逻辑层发送网络请求也经由 Native 转发,小程序的通信模型下图所示。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uVmAbRHX-1677491373238)(C:\Users\Administrator\AppData\Local\Temp\1677409947621.png)]
1.5.2 程序与页面
微信客户端在打开小程序之前,会把整个小程序的代码包下载到本地。
紧接着通过 app.json
的 pages
字段就可以知道你当前小程序的所有页面路径:
{"pages":["pages/index/index","pages/logs/logs"]
}
这个配置说明在 QuickStart 项目定义了两个页面,分别位于 pages/index/index
和 pages/logs/logs
。而写在 pages
字段的第一个页面就是这个小程序的首页(打开小程序看到的第一个页面)。
于是微信客户端就把首页的代码装载进来,通过小程序底层的一些机制,就可以渲染出这个首页。
小程序启动之后,在 app.js
定义的 App
实例的 onLaunch
回调会被执行:
App({onLaunch: function () {// 小程序启动之后 触发}
})
整个小程序只有一个 App 实例,是全部页面共享的。
接下来我们简单看看小程序的一个页面是怎么写的。
你可以观察到 pages/logs/logs
下其实是包括了4种文件的,微信客户端会先根据 logs.json
配置生成一个界面,顶部的颜色和文字你都可以在这个 json
文件里边定义好。紧接着客户端就会装载这个页面的 WXML
结构和 WXSS
样式。最后客户端会装载 logs.js
,你可以看到 logs.js
的大体内容就是:
Page({data: { // 参与页面渲染的数据logs: []},onLoad: function () {// 页面渲染后 执行}
})
Page
是一个页面构造器,这个构造器就生成了一个页面。在生成页面的时候,小程序框架会把 data
数据和 index.wxml
一起渲染出最终的结构,于是就得到了你看到的小程序的样子。
在渲染完界面之后,页面实例就会收到一个 onLoad
的回调,你可以在这个回调处理你的逻辑。
1.5.3 组件
小程序提供了丰富的基础组件给开发者,开发者可以像搭积木一样,组合各种组件拼合成自己的小程序。
就像 HTML
的 div
, p
等标签一样,在小程序里边,你只需要在 WXML
写上对应的组件标签名字就可以把该组件显示在界面上,例如,你需要在界面上显示地图,你只需要这样写即可:
<map></map>
使用组件的时候,还可以通过属性传递值给组件,让组件可以以不同的状态去展现,例如,我们希望地图一开始的中心的经纬度是广州,那么你需要声明地图的 longitude(中心经度) 和 latitude(中心纬度)两个属性:
<map longitude="广州经度" latitude="广州纬度"></map>
组件的内部行为也会通过事件的形式让开发者可以感知,例如用户点击了地图上的某个标记,你可以在 js
编写 markertap
函数来处理:
<map bindmarkertap="markertap" longitude="广州经度" latitude="广州纬度"></map>
当然你也可以通过 style
或者 class
来控制组件的外层样式,以便适应你的界面宽度高度等等。
1.5.4 API
为了让开发者可以很方便的调起微信提供的能力,例如获取用户信息、微信支付等等,小程序提供了很多 API 给开发者去使用。
要获取用户的地理位置时,只需要:
wx.getLocation({type: 'wgs84',success: (res) => {var latitude = res.latitude // 纬度var longitude = res.longitude // 经度}
})
调用微信扫一扫能力,只需要:
wx.scanCode({success: (res) => {console.log(res)}
})
需要注意的是:多数 API 的回调都是异步,你需要处理好代码逻辑的异步问题
二、Vue简介
2.1 Vue的定义
Vue是一种前端JavaScript框架,它是一种轻量级的MVVM框架,可以用于构建Web界面。
2.2 Vue的特点
-
易于上手:Vue具有简单易学的特点,可以快速上手。
-
灵活性高:Vue的组件化设计,可以方便地组合和重用组件。
-
性能优秀:Vue采用虚拟DOM技术,可以提高渲染效率,减少页面渲染时间。
-
支持插件化:Vue可以轻松地集成第三方插件,扩展其功能。
2.3 Vue的使用
Vue的使用主要包括以下几个方面:
- 数据绑定:Vue通过数据绑定实现视图与数据的同步更新。
- 组件化:Vue将应用程序划分为一个个组件,便于开发和维护。
- 路由管理:Vue提供了Vue Router插件,可以轻松管理应用程序的路由。
- 状态管理:Vue提供了Vuex插件,可以方便地管理应用程序的状态。
2.4 MVVM软件架构模式
MVVM是一种软件架构模式,它由三个核心部分组成:Model(模型)、View(视图)和ViewModel(视图模型)。这种模式通常用于开发用户界面,它的目的是将应用程序的逻辑和用户界面分离开来,从而提高代码的可维护性和可扩展性。
下面是MVVM架构中各个部分的详细说明:
Model
Model是应用程序中数据的存储和管理部分。它通常包括数据结构、数据库、网络通信等。在MVVM中,Model用于表示应用程序的业务逻辑和数据。
View
View是应用程序中用户界面的展示部分。它通常包括UI控件、视图元素、动画等。在MVVM中,View是与用户交互的部分,它负责将ViewModel中的数据呈现给用户,并接受用户输入的操作。
ViewModel
ViewModel是连接View和Model之间的桥梁。它主要包括数据绑定、命令绑定、事件处理等功能。在MVVM中,ViewModel用于将Model中的数据映射到View中,并且在View中的操作反映到Model中。
MVVM架构中最重要的一部分是数据绑定。数据绑定是指将View中的控件与ViewModel中的属性绑定在一起,当ViewModel中的属性值发生变化时,View中的控件会自动更新。同样地,当用户在View中进行操作时,ViewModel中的属性也会相应地进行更新。
MVVM架构的优点包括:
- 提高代码的可维护性和可扩展性:MVVM将应用程序的逻辑和用户界面分离开来,从而使得代码更易于维护和扩展。
- 提高开发效率:MVVM中的数据绑定和命令绑定可以自动完成,减少了重复代码的编写,提高了开发效率。
- 提高测试效率:由于MVVM中的View和ViewModel之间的依赖关系松散,因此可以更方便地对ViewModel进行单元测试。
总的来说,MVVM是一种强大的软件架构模式,它在现代Web开发中被广泛应用,例如Vue.js和AngularJS等框架都采用了MVVM架构。
当我们使用MVVM框架时,通常会采用以下设计模式:
数据绑定
MVVM的核心概念之一是数据绑定。数据绑定是指将视图(View)和模型(Model)之间的数据同步更新的机制。通常采用单向绑定和双向绑定。
- 单向绑定:视图只能读取模型的数据,无法更改。当模型的数据发生变化时,视图会自动更新。
- 双向绑定:视图可以读取并更改模型的数据,当视图中的数据发生变化时,模型的数据也会随之更新。
命令绑定
命令绑定是MVVM框架中的另一个重要概念。命令绑定是指将视图中的事件和ViewModel中的命令绑定在一起,从而实现对视图事件的响应。
在传统的MVC框架中,通常会将事件的处理代码写在Controller中,而在MVVM框架中,我们将这些处理代码封装在ViewModel中,通过命令绑定来实现事件处理。
ViewModel
在MVVM框架中,ViewModel负责将Model中的数据转换为View中的数据。ViewModel通常包括以下几个部分:
- 数据模型(Model):ViewModel通过数据模型(Model)来获取和管理数据。
- 数据绑定(Data Binding):ViewModel通过数据绑定(Data Binding)将数据模型(Model)中的数据同步到View中。
- 命令绑定(Command Binding):ViewModel通过命令绑定(Command Binding)将视图(View)中的事件和命令(Command)绑定在一起。
View
在MVVM框架中,View是用户界面的展示部分,通常由HTML、CSS和JavaScript等技术实现。View负责将ViewModel中的数据呈现给用户,并接受用户的输入操作。同时,View也需要将用户的操作传递给ViewModel进行处理。
总的来说,MVVM框架通过数据绑定和命令绑定实现了视图(View)和视图模型(ViewModel)之间的解耦,将应用程序的逻辑和用户界面分离开来,从而提高了代码的可维护性和可扩展性。
当我们在Vue中使用MVVM框架时,我们通常会遵循以下步骤:
- 在Vue中创建一个Vue实例,指定其所使用的HTML元素和初始数据。
- 在Vue实例中定义一个名为"methods"的对象,用于定义视图中的事件处理函数。
- 在Vue实例中定义一个名为"computed"的对象,用于定义视图中的计算属性。
- 在HTML中使用Vue指令,将视图与数据模型绑定在一起。
下面是一个使用Vue实现的简单计数器应用程序的示例:
htmlCopy code
<!DOCTYPE html>
<html>
<head>
<title>Vue MVVM Example</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
<div id="app"> <h1>{{ count }}</h1>
<button v-on:click="increment">+</button>
<button v-on:click="decrement">-</button>
</div>
<script>
var app = new Vue({
el: '#app',
data: { count: 0 },
methods: {increment: function(){ this.count += 1; }, decrement: function() { this.count -= 1; } },
computed: {}
});
</script>
</body> </html>
在这个示例中,我们使用Vue创建了一个Vue实例,将其绑定到id为"app"的HTML元素上。在Vue实例中,我们定义了一个名为"count"的数据模型,以及两个名为"increment"和"decrement"的事件处理函数。我们还通过Vue指令将视图中的两个按钮与对应的事件处理函数绑定在一起。
当用户点击"+“按钮时,Vue实例中的increment方法将被调用,它会将count加1,并通过数据绑定机制自动将更新后的值同步到视图中。当用户点击”-"按钮时,同样会调用decrement方法,将count减1。
这个示例演示了MVVM框架中数据绑定和命令绑定的实现方式,它将数据模型和视图逻辑分离开来,提高了代码的可维护性和可扩展性。
三、uniapp
3.1 什么是uni-app?
uni-app是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到iOS、Android、Web(响应式)、以及各种小程序(微信/支付宝/百度/头条/飞书/QQ/快手/钉钉/淘宝)、快应用等多个平台。
一套代码编到14个平台 :
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dvMG4iNK-1677491373241)(C:\Users\Administrator\AppData\Local\Temp\1677479569671.png)]
3.2 快速上手
开始之前,开发者需先下载安装如下工具:
- HBuilderX:官方IDE下载地址
3.2.1 创建uni-app
在点击工具栏里的文件 -> 新建 -> 项目(快捷键Ctrl+N
):
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VTyMIRCm-1677491373243)(C:\Users\Administrator\AppData\Local\Temp\1677479883538.png)]
选择uni-app
类型,输入工程名,选择模板,点击创建,即可成功创建。
uni-app自带的模板有 默认的空项目模板、Hello uni-app 官方组件和API示例,还有一个重要模板是 uni ui项目模板,日常开发推荐使用该模板,已内置大量常用组件。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6HOge0Cz-1677491373252)(C:\Users\Administrator\AppData\Local\Temp\1677479914051.png)]
3.2.2 uni-app工程目录结构
一个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原生资源目录 详见
├─hybrid App端存放本地html文件的目录,详见
├─wxcomponents 存放小程序组件的目录,详见
├─unpackage 非工程代码,一般存放运行或发行的编译结果
├─AndroidManifest.xml Android原生应用清单文件 详见
├─main.js Vue初始化入口文件
├─App.vue 应用配置,用来配置App全局样式以及监听 应用生命周期
├─manifest.json 配置应用名称、appid、logo、版本等打包信息,详见
├─pages.json 配置页面路由、导航条、选项卡等页面类信息,详见
└─uni.scss 这里是uni-app内置的常用样式变量
3.2.3 页面简介
uni-app项目中,一个页面就是一个符合Vue SFC规范
的.vue
文件或.nvue
文件。
.vue
页面和.nvue
页面,均全平台支持,差异在于当uni-app发行到App平台时,.vue
文件会使用webview进行渲染,.nvue
会使用原生进行渲染。
新建页面
uni-app
中的页面,通常会保存在工程根目录下的pages
目录下。
每次新建页面,均需在pages.json
中配置pages
列表;未在pages.json -> pages
中配置的页面,uni-app
会在编译阶段进行忽略。pages.json的完整配置参考:全局文件。
通过HBuilderX开发 uni-app
项目时,在 uni-app
项目上右键“新建页面”,HBuilderX会自动在pages.json
中完成页面注册,开发更方便。
同时,HBuilderX 还内置了常用的页面模板(如图文列表、商品列表等),选择这些模板,可以大幅提升你的开发效率。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-blFJTk8L-1677491373255)(C:\Users\Administrator\AppData\Local\Temp\1677481498150.png)]
删除页面
删除页面时,需做两件工作:
- 删除
.vue
文件或.nvue
文件 - 删除
pages.json -> pages
列表项中的配置
应用首页
uni-app
会将pages.json -> pages
配置项中的第一个页面,作为当前工程的首页(启动页)。
页面生命周期
uni-app
支持如下页面生命周期函数:
函数名 | 说明 | 平台差异说明 | 最低版本 |
---|---|---|---|
onInit | 监听页面初始化,其参数同 onLoad 参数,为上个页面传递的数据,参数类型为 Object(用于页面传参),触发时机早于 onLoad | 百度小程序 | 3.1.0+ |
onLoad | 监听页面加载,其参数为上个页面传递的数据,参数类型为 Object(用于页面传参),参考示例 | ||
onShow | 监听页面显示。页面每次出现在屏幕上都触发,包括从下级页面点返回露出当前页面 | ||
onReady | 监听页面初次渲染完成。注意如果渲染速度快,会在页面进入动画完成前触发 | ||
onHide | 监听页面隐藏 | ||
onUnload | 监听页面卸载 | ||
onResize | 监听窗口尺寸变化 | App、微信小程序、快手小程序 | |
onPullDownRefresh | 监听用户下拉动作,一般用于下拉刷新,参考示例 | ||
onReachBottom | 页面滚动到底部的事件(不是scroll-view滚到底),常用于下拉下一页数据。具体见下方注意事项 | ||
onTabItemTap | 点击 tab 时触发,参数为Object,具体见下方注意事项 | 微信小程序、QQ小程序、支付宝小程序、百度小程序、H5、App、快手小程序、京东小程序 | |
onShareAppMessage | 用户点击右上角分享 | 微信小程序、QQ小程序、支付宝小程序、字节小程序、飞书小程序、快手小程序、京东小程序 | |
onPageScroll | 监听页面滚动,参数为Object | nvue暂不支持 | |
onNavigationBarButtonTap | 监听原生标题栏按钮点击事件,参数为Object | App、H5 | |
onBackPress | 监听页面返回,返回 event = {from:backbutton、 navigateBack} ,backbutton 表示来源是左上角返回按钮或 android 返回键;navigateBack表示来源是 uni.navigateBack ;详细说明及使用:onBackPress 详解。支付宝小程序只有真机能触发,只能监听非navigateBack引起的返回,不可阻止默认行为。 | app、H5、支付宝小程序 | |
onNavigationBarSearchInputChanged | 监听原生标题栏搜索输入框输入内容变化事件 | App、H5 | 1.6.0 |
onNavigationBarSearchInputConfirmed | 监听原生标题栏搜索输入框搜索事件,用户点击软键盘上的“搜索”按钮时触发。 | App、H5 | 1.6.0 |
onNavigationBarSearchInputClicked | 监听原生标题栏搜索输入框点击事件(pages.json 中的 searchInput 配置 disabled 为 true 时才会触发) | App、H5 | 1.6.0 |
onShareTimeline | 监听用户点击右上角转发到朋友圈 | 微信小程序 | 2.8.1+ |
onAddToFavorites | 监听用户点击右上角收藏 | 微信小程序、QQ小程序 | 2.8.1+ |
onReachBottom
使用注意 可在pages.json里定义具体页面底部的触发距离onReachBottomDistance,比如设为50,那么滚动页面到距离底部50px时,就会触发onReachBottom事件。
组件生命周期
uni-app
组件支持的生命周期,与vue标准组件的生命周期相同。这里没有页面级的onLoad等生命周期:
函数名 | 说明 | 平台差异说明 | 最低版本 |
---|---|---|---|
beforeCreate | 在实例初始化之前被调用。详见 | ||
created | 在实例创建完成后被立即调用。详见 | ||
beforeMount | 在挂载开始之前被调用。详见 | ||
mounted | 挂载到实例上去之后调用。详见 注意:此处并不能确定子组件被全部挂载,如果需要子组件完全挂载之后在执行操作可以使用$nextTick Vue官方文档 | ||
beforeUpdate | 数据更新时调用,发生在虚拟 DOM 打补丁之前。详见 | 仅H5平台支持 | |
updated | 由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。详见 | 仅H5平台支持 | |
beforeDestroy | 实例销毁之前调用。在这一步,实例仍然完全可用。详见 | ||
destroyed | Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。详见 |
路由
uni-app
页面路由为框架统一管理,开发者需要在pages.json里配置每个路由页面的路径及页面样式。类似小程序在 app.json 中配置页面路由一样。所以 uni-app
的路由用法与 Vue Router
不同,如仍希望采用 Vue Router
方式管理路由,可在插件市场搜索 Vue-Router。
路由跳转
uni-app
有两种页面路由跳转方式:使用navigator组件跳转、调用API跳转。
页面栈
框架以栈的形式管理当前所有页面, 当发生路由切换的时候,页面栈的表现如下:
路由方式 | 页面栈表现 | 触发时机 |
---|---|---|
初始化 | 新页面入栈 | uni-app 打开的第一个页面 |
打开新页面 | 新页面入栈 | 调用 API uni.navigateTo 、使用组件 |
页面重定向 | 当前页面出栈,新页面入栈 | 调用 API uni.redirectTo 、使用组件 |
页面返回 | 页面不断出栈,直到目标返回页 | 调用 API uni.navigateBack 、使用组件 、用户按左上角返回按钮、安卓用户点击物理back按键 |
Tab 切换 | 页面全部出栈,只留下新的 Tab 页面 | 调用 API uni.switchTab 、使用组件 、用户切换 Tab |
重加载 | 页面全部出栈,只留下新的页面 | 调用 API uni.reLaunch 、使用组件 |
相互引用
引用组件:
传统vue项目开发,引用组件需要导入 - 注册 - 使用
三个步骤,如下:
<template><view><!-- 3.使用组件 --><uni-rate text="1"></uni-rate></view>
</template>
<script>// 1. 导入组件import uniRate from '@/components/uni-rate/uni-rate.vue';export default {components: { uniRate } // 2. 注册组件}
</script>
Vue 3.x增加了script setup
特性,将三步优化为两步,无需注册步骤,更为简洁:
<template><view><!-- 2.使用组件 --><uni-rate text="1"></uni-rate></view>
</template>
<script setup>// 1. 导入组件import uniRate from '@/components/uni-rate/uni-rate.vue';
</script>
uni-app
的easycom
机制,将组件引用进一步优化,开发者只管使用,无需考虑导入和注册,更为高效:
<template><view><!-- 1.使用组件 --><uni-rate text="1"></uni-rate></view>
</template>
<script>
</script>
在 uni-app 项目中,页面引用组件和组件引用组件的方式都是一样的(可以理解为:页面是一种特殊的组件),均支持通过 easycom
方式直接引用。
js 文件引入
js
文件或script
标签内(包括 renderjs 等)引入js
文件时,可以使用相对路径和绝对路径,形式如下
// 绝对路径,@指向项目根目录,在cli项目中@指向src目录
import add from '@/common/add.js';
// 相对路径
import add from '../../common/add.js';
注意
- js 文件不支持使用
/
开头的方式引入
NPM支持
uni-app支持使用npm安装第三方包。
此文档要求开发者们对npm有一定的了解,因此不会再去介绍npm的基本功能。如若之前未接触过npm,请翻阅NPM官方文档进行学习。
初始化npm工程
若项目之前未使用npm管理依赖(项目根目录下无package.json文件),先在项目根目录执行命令初始化npm工程:
npm init -y
cli项目默认已经有package.json了。HBuilderX创建的项目默认没有,需要通过初始化命令来创建。
安装依赖
在项目根目录执行命令安装npm包:
npm install packageName --save
使用
安装完即可使用npm包,js中引入npm包:
import package from 'packageName'
const package = require('packageName')
引入css
使用@import
语句可以导入外联样式表,@import
后跟需要导入的外联样式表的相对路径,用;
表示语句结束。
示例代码:
<style>@import "../../common/uni.css";.uni-card {box-shadow: none;}
</style>
css 引入静态资源
css
文件或style标签
内引入css
文件时(scss、less 文件同理),可以使用相对路径或绝对路径(HBuilderX 2.6.6
)
/* 绝对路径 */
@import url('/common/uni.css');
@import url('@/common/uni.css');
/* 相对路径 */
@import url('../../common/uni.css');
复制代码
注意
- 自
HBuilderX 2.6.6
起支持绝对路径引入静态资源,旧版本不支持此方式
css
文件或style标签
内引用的图片路径可以使用相对路径也可以使用绝对路径,需要注意的是,有些小程序端 css 文件不允许引用本地文件(请看注意事项)。
/* 绝对路径 */
background-image: url(/static/logo.png);
background-image: url(@/static/logo.png);
/* 相对路径 */
background-image: url(../../static/logo.png);
3.2.4 运行uni-app
浏览器运行:进入hello-uniapp项目,点击工具栏的运行 -> 运行到浏览器 -> 选择浏览器,即可体验 uni-app 的 web 版。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7LHZBReq-1677491373257)(C:\Users\Administrator\AppData\Local\Temp\1677480041248.png)]
运行App到手机或模拟器:使用电压足够的usb端口连接手机,设置中开启USB调试,手机上允许电脑设备调试手机,进入hello-uniapp项目,点击工具栏的运行 -> 运行App到手机或模拟器,即可在该设备里面体验uni-app。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pUlFurDL-1677491373259)(C:\Users\Administrator\AppData\Local\Temp\1677480055229.png)]
如需运行在苹果手机真机上,注意需使用自定义基座 .
在微信开发者工具里运行:进入hello-uniapp项目,点击工具栏的运行 -> 运行到小程序模拟器 -> 微信开发者工具,即可在微信开发者工具里面体验uni-app。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SUNwvz7p-1677491373337)(C:\Users\Administrator\AppData\Local\Temp\1677480075752.png)]
注意:如果是第一次使用,需要先配置小程序ide的相关路径,才能运行成功。如下图,需在输入框输入微信开发者工具的安装路径。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ONb88xYq-1677491373340)(C:\Users\Administrator\AppData\Local\Temp\1677480089899.png)]
3.2.5 发布uni-app
打包为原生App
在HBuilderX工具栏,点击发行,选择原生app-云端打包,如下图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-56r3umCj-1677491373342)(C:\Users\Administrator\AppData\Local\Temp\1677480192068.png)]
出现如下界面,点击打包即可
云端打包支持安心打包,保护用户隐私,不会上传代码和证书,通过差量包制作方式实现安心打包。
App打包时,注意如果涉及三方sdk,需进行申请并在manifest.json里配置,否则相关功能无法使用。
iOS App打包需要向Apple申请证书。
发布为Web网站
-
在
manifest.json
的可视化界面,进行如下配置(发行在网站根目录可不配置应用基本路径),此时发行网站路径是 www.xxx.com/h5[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zb9ssag7-1677491373344)(C:\Users\Administrator\AppData\Local\Temp\1677480428998.png)]
-
在HBuilderX工具栏,点击发行,选择网站-H5手机版,如下图,点击即可生成 H5 的相关资源文件,保存于 unpackage 目录
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GRKsksiA-1677491373347)(C:\Users\Administrator\AppData\Local\Temp\1677480576864.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bkAilRXM-1677491373349)(C:\Users\Administrator\AppData\Local\Temp\1677480599102.png)]
- 打包后,推荐使用前端网页托管服务,一键上传,自带CDN加速,无需购买虚拟机,无需安装nginx等;
发布为微信小程序
- 申请微信小程序AppID,参考:微信教程。
- 在HBuilderX中顶部菜单依次点击 “发行” => “小程序-微信”,输入小程序名称和appid点击发行即可
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-01m8R5uW-1677491373351)(C:\Users\Administrator\AppData\Local\Temp\1677480773411.png)]
如果手动发行,则点击发行按钮后,会在项目的目录 unpackage/dist/build/mp-weixin
生成微信小程序项目代码。在微信小程序开发者工具中,导入生成的微信小程序项目,测试项目代码运行正常后,点击“上传”按钮,之后按照 “提交审核” => “发布” 小程序标准流程,逐步操作即可,详细查看:微信官方教程。
如果在发行界面勾选了自动上传微信平台
,则无需再打开微信工具手动操作,将直接上传到微信服务器提交审核。
四、 unicloud
uniCloud
是 DCloud 联合阿里云、腾讯云,为开发者提供的基于 serverless 模式和 js 编程的云开发平台。
uniCloud
的 web控制台地址:https://unicloud.dcloud.net.cn
4.1uniCloud是什么和不是什么
uniCloud是DCloud在阿里云和腾讯云的serverless服务上封装而成的。
它包含IaaS层(由阿里云和腾讯云提供硬件和网络)和PaaS层(由DCloud提供开发环境)。
开发者可以自主选择uniCloud的硬件和网络资源的供应商,在阿里云版和腾讯云版之间切换。
开户和付费虽然通过DCloud渠道,但实际上开发者自动在云厂商处建立了账户和充值了余额。价格是云厂商的标准定价,DCloud只获取云服务厂商的返佣。
开发时虽使用DCloud的工具,但应用上线时,手机端是直连阿里云或腾讯云的serverless,不经由DCloud的服务器。
4.2 什么是serverless?
serverless是目前很火的概念,它是下一代云技术,是真正的“云”。
传统的云服务,让开发者免于购买实体服务器硬件,改为购买虚拟机。但开发者仍然要自己装操作系统、web服务器、数据库,自己处理热备,自己新购服务器来应对高并发,自己抗DDOS攻击…
这不是成熟的“云”!
真正的云计算,就像用水用电,没有复杂的门槛,即用即有、按需付费。
简单回顾下用电的历史。几十年前,很多单位都有专门管电的工程师,当单位的电力负荷不够时,就需要找这个管电的工程师扩容发电机。
现在这个管电工程师的岗位已经淘汰了,电已经变成随用随取、按需付费了。
传统云模式下,开发商仍然需要一个管服务器的工程师,当用户量激增或被攻击时,甚至需要半夜把工程师叫醒来扩容。这当然不合理。
serverless的云,真正的把计算、存储的能力进行了云化,开发者只需要按量租用这些计算和存储能力,再也不用关心扩容和攻击。
开发者不再有“服务器”的概念,因为没有一台具体的机器。就像现在的你再也找不到自己的发电机一样。
当用户量激增时,开发者什么都不用做,系统自动承载更高并发。开发者只需要按照对资源的消耗付费即可。
同理,如果没有用户使用,即没有资源消耗,则根本无需为云资源付费。
开发者写好云端业务代码,即js编写的云函数,通过HBuilderX部署到uniCloud上即可。
云端庞大的serverless资源池,有无数个node进程待命。当手机用户发起请求时,serverless系统会调配闲置的资源来运行开发者相应的云函数。
- serverless,让一个不懂服务器运维的开发者,可以只处理自己的业务,再不用关心热备、负载、增容、DDOS等事情。
- serverless,让一个学生,也可以享受世界最顶级的IT基础设置。
serverless在国外兴起,但国内的发展速度已经超过了国外。微信、支付宝、百度、字节跳动、快应用联盟都上线了自己的serverless云开发。
目前国内已经有超过60万开发者在使用serverless云开发,包括腾讯、阿里、DCloud的很多自有业务都在使用。
就像uni-app可跨端一样,uniCloud可跨云。基于uniCloud,无需担心使用云开发被绑定到专用的小程序平台。uni-app + uniCloud 是跨端跨云的开发方案
4.3 基本概念
4.3.1服务空间
一个服务空间对应一整套独立的云开发资源,包括数据库、存储空间、云函数等资源。服务空间之间彼此隔离。
每个服务空间都有一个全局唯一的space ID。
- 通过 HBuilderX 中管理服务空间,包括新建服务空间和关联服务空间
在 uniCloud
目录右键菜单中创建服务空间
创建服务空间后,在同样的 uniCloud
目录右键菜单中关联该服务空间。只有项目关联好服务空间后,才能上传云函数、操作服务空间下的数据库、存储等资源。
- 通过uniCloud的web控制台https://unicloud.dcloud.net.cn 管理服务空间。
web控制台可以新建、删除服务空间,管理线上的服务空间资源。
新建服务空间注意
- 第一次创建腾讯云服务空间时会为用户创建腾讯云账号并跳转到腾讯云实名界面,等待实名认证审核之后可以开通服务空间。若腾讯云实名认证提示身份证下已创建过多账户,则需要在腾讯云官网注销不用的账户。详见
- 创建服务空间可能需要几十秒的时间,可以在web控制台查看是否创建完成。
多人协作
2022年7月18日前,服务空间的多人协作是在 dev.dcloud.net.cn 的 app 协作中设置。在2022年7月18日后,改为在 unicloud.dcloud.net.cn 设置。
一个服务空间只有一个创建者,但可以设置协作成员。
项目涉及多人开发时,在uniCloud WEB控制台设置协作者(选择服务空间->成员管理),实现多人共同使用一个云服务空间。
协作者可以在HBuilderX和web控制台中操作被授权的服务空间,除了删除服务空间,其他功能均可正常操作。
授权步骤:
- 登录uniCloud WEB控制台中选择要添加协作者的服务空间
- 在服务空间详情页面左侧菜单点击
成员管理
- 输入协作者邮箱并点击
搜索
,下方会出现搜索到的结果,确认无误后点击添加成员
进行添加
- 下方
成员列表
中可以查看以及移除已添加的协作者
注意
- 服务空间协作者和App的协作者是2套体系,需要分别设置,无关联关系。App协作者在 dev.dcloud.net.cn 设置。
- 只有服务空间的创建者才可以添加成员,协作者无此权限
- 根据法律要求,协作者账号需完成实名认证才可以正常添加
应用和服务空间的关系
每个uni-app应用都有一个appid,每个服务空间都有一个spaceid。
服务空间和手机端项目是多对多绑定关系。同DCloud账号下,一个应用可以关联到多个服务空间。一个服务空间也可以被多个项目访问。
多应用共用服务空间
随着用户使用uniCloud开发的项目越来越多, 部分用户遇到了新的问题。
两个、多个项目想共用一个云服务空间,比如一个系统,有用户端项目、管理admin项目,两个项目需要公共服务空间。还有司机端、乘客端、用户端、骑手端…很多类似的问题。
如果每个项目目录下都存在多个重复的云函数文件。 每个项目都要做 同步云函数列表, 下载云函数等操作。 繁琐,而且很容易冲突。
针对上面出现的问题, 提供了一云多项目
的解决方案。
一云多端
绑定其它项目的服务空间
选中项目下的uniCloud-aliyun|tcb
目录, 右键菜单,点击 【关联云服务空间或项目… 】 ,可以关联云服务空间
、绑定其它项目的服务空间
:
以阿里云举例,
绑定其它项目的服务空间
指的是关联其他项目的当前使用的阿里云服务空间。
- 阿里云无法关联到腾讯云, 腾讯云也无法关联到阿里云, 但是项目可以关联,使用时会报错。
- 如果项目已关联其他项目, 选择云服务空间, 此时关联关系会断开。
4.3.2云数据库
uniCloud
提供了 2 个 nosql 数据库。
-
JSON文档型云数据库
uniCloud阿里云版的云数据库就是 MongoDB 的 serverless版;uniCloud腾讯云版的云数据库是兼容 MongoDB 的自研数据库。
数据库中的每条记录都是一个 JSON 格式的对象。
一个数据库可以有多个集合(相当于关系型数据中的表),集合可看做一个 JSON 数组,数组中的每个对象就是一条记录,记录的格式是 JSON 对象。
这对于js工程师而言,非常容易理解掌握。
MongoDB的传统操作方法还是比较复杂,uniCloud提供了更多简单操作数据库的方案,包括类似 SQL 的 JQL 语法、clientDB等技术。
-
redis 数据库
redis 是一种可以运行在内存中的键值对数据库,它的能力没有MongoDB强大,但由于可运行在内存中,它的性能远超常规数据库。
redis 也使用 json 方式 key/value 键值对存储数据。更多文档参考
如果开发者需要其他数据库,比如 mysql、ElasticSearch、数据湖,这些数据库没有在uniCloud的服务空间内置,云函数中通过 nodejs 的 api 可以访问这些远程数据库。
4.3.3云函数/云对象
云函数即在云端(服务器端)运行的函数。
从 HBuilderX 3.4起,新增了云函数的扩展版,云对象。
开发者无需购买、搭建服务器,只需编写代码并部署到云端即可在客户端(App/Web/小程序等)调用,同时云函数之间也可互相调用。
一个云函数的写法与一个在本地定义的 JavaScript
方法无异,代码运行在云端 Node.js
中。当云函数被客户端调用时,定义的代码会被放在 Node.js
运行环境中执行。
开发者可以如在 Node.js
环境中使用 JavaScript
一样在云函数中进行网络请求等操作,也可以使用 node_modules。
但 DCloud提供了 uniCloud对象 内置在云函数/云对象中,开发者使用更多的是 uniCloud 的 api,不了解 node 不影响开发。
HBuilderX 3.0起版本,在uniCloud/cloudfunctions
目录右键创建云函数,如下:
在HBuilderX 3.4起,上述界面更新为 新建云函数/云对象。
云对象本质是对云函数的一种封装,可以对象化的方式使用云服务。
HBuilderX 3.0之前版本,项目下没有uniCloud
目录,直接在cloudfunctions
目录上右键、新建云函数
云函数修改后,可以本地运行。只有上传到云端,方可在云端生效。
4.4 快速上手
4.4.1 创建uniCloud项目
HBuilderX中新建项目,选择uni-app项目,并勾选启用uniCloud
,在右侧选择服务供应商(腾讯云或阿里云)
项目名称随意,比如 firstunicloud
4.4.2 关联服务空间
一个开发者可以拥有多个服务空间,每个服务空间都是一个独立的serverless云环境,不同服务空间之间的云函数、数据库、存储都是隔离的。
对项目根目录uniCloud
点右键选择关联云服务空间
,绑定之前创建的服务空间,或者新建一个服务空间。
4.4.3 创建云函数/云对象
uniCloud
项目创建并绑定服务空间后,开发者可以创建云函数(云对象是云函数的一种,云函数可泛指普通云函数和云对象)。
在uniCloud/cloudfunctions
目录右键创建云函数/云对象
- 创建云函数后,生成一个目录,该目录下自动生成index.js,是该云函数的入口文件,不可改名。
- 创建云对象后,生成一个目录,该目录下自动生成index.obj.js,是该云对象的入口文件,不可改名。
如果该云函数/云对象还需要引入其他js,可在index.js入口文件中引用。
初学者,建议从云对象学起,比云函数更加简单直观。
在本教程中,我们创建一个云对象名为 helloco。
- 给云对象编写方法
打开index.obj.js,我们为它添加一个 sum 方法,逻辑就是接收传入a和b2个参数,返回求和结果。
module.exports = {sum(a, b) {// 此处省略a和b的有效性校验return a + b}
}
- 在前端调用云对象
在项目首页,pages/index/index.vue 里,添加一个按钮,点击后执行异步方法sum。
js 中 import 这个 helloco 对象,调用它的 sum 方法
<template><view class="content"><button @click="testco()">请求云对象的方法</button></view>
</template><script>export default {data() {return {}},methods: {async testco() { // 注意异步const helloco = uniCloud.importObject('helloco') // 导入云对象try {const res = await helloco.sum(1,2) //导入云对象后就可以直接调用该对象的sum方法了,注意使用异步awaitconsole.log(res) // 结果是3} catch (e) {console.log(e)}}}}
</script>
- 运行
将项目运行到浏览器或其他平台,点页面上的按钮,控制台会打印结果:3
HBuilderX自带一个云函数本地运行环境,运行项目时也默认选择 连接本地云函数。可以在底部控制台中的前端控制台右上角进行切换。
可以对helloco云对象点右键上传到uniCloud服务空间,然后在前端控制台右上角切换为 连接云端云函数,那么此时客户端连接的就是真正的现网uniCloud服务器了。
五、 项目案例
、新建云函数
云函数修改后,可以本地运行。只有上传到云端,方可在云端生效。
4.4 快速上手
4.4.1 创建uniCloud项目
HBuilderX中新建项目,选择uni-app项目,并勾选启用uniCloud
,在右侧选择服务供应商(腾讯云或阿里云)
项目名称随意,比如 firstunicloud
4.4.2 关联服务空间
一个开发者可以拥有多个服务空间,每个服务空间都是一个独立的serverless云环境,不同服务空间之间的云函数、数据库、存储都是隔离的。
对项目根目录uniCloud
点右键选择关联云服务空间
,绑定之前创建的服务空间,或者新建一个服务空间。
4.4.3 创建云函数/云对象
uniCloud
项目创建并绑定服务空间后,开发者可以创建云函数(云对象是云函数的一种,云函数可泛指普通云函数和云对象)。
在uniCloud/cloudfunctions
目录右键创建云函数/云对象
[外链图片转存中…(img-X1PYnlC3-1677491373368)]
- 创建云函数后,生成一个目录,该目录下自动生成index.js,是该云函数的入口文件,不可改名。
- 创建云对象后,生成一个目录,该目录下自动生成index.obj.js,是该云对象的入口文件,不可改名。
如果该云函数/云对象还需要引入其他js,可在index.js入口文件中引用。
初学者,建议从云对象学起,比云函数更加简单直观。
在本教程中,我们创建一个云对象名为 helloco。
- 给云对象编写方法
打开index.obj.js,我们为它添加一个 sum 方法,逻辑就是接收传入a和b2个参数,返回求和结果。
module.exports = {sum(a, b) {// 此处省略a和b的有效性校验return a + b}
}
- 在前端调用云对象
在项目首页,pages/index/index.vue 里,添加一个按钮,点击后执行异步方法sum。
js 中 import 这个 helloco 对象,调用它的 sum 方法
<template><view class="content"><button @click="testco()">请求云对象的方法</button></view>
</template><script>export default {data() {return {}},methods: {async testco() { // 注意异步const helloco = uniCloud.importObject('helloco') // 导入云对象try {const res = await helloco.sum(1,2) //导入云对象后就可以直接调用该对象的sum方法了,注意使用异步awaitconsole.log(res) // 结果是3} catch (e) {console.log(e)}}}}
</script>
- 运行
将项目运行到浏览器或其他平台,点页面上的按钮,控制台会打印结果:3
HBuilderX自带一个云函数本地运行环境,运行项目时也默认选择 连接本地云函数。可以在底部控制台中的前端控制台右上角进行切换。
可以对helloco云对象点右键上传到uniCloud服务空间,然后在前端控制台右上角切换为 连接云端云函数,那么此时客户端连接的就是真正的现网uniCloud服务器了。
五、 项目案例
https://blog.csdn.net/weixin_43025151/article/details/129019497?spm=1001.2014.3001.5501
相关文章:
小程序和Vue+uniapp+unicloud培训课件
文章目录**一、什么是小程序****1.1** **小程序简介****1.2** **小程序的特点****1.3** **小程序的开发流程**个人小程序和企业小程序的区别1.4 小程序代码构成1.4.1 JSON 配置1.4.2 WXML 模板**数据绑定**逻辑语法条件逻辑列表渲染模板引用共同属性1.4.3 WXSS 样式1.4.4 JS 逻…...
C语言--指针进阶2
目录前言函数指针函数指针数组指向函数指针数组的指针回调函数前言 本篇文章我们将继续学习指针进阶的有关内容 函数指针 我们依然用类比的方法1来理解函数指针这一全新的概念,如图1 我们用一段代码来验证一下: int Add(int x, int y) {return xy;…...
【步进电机和 Arduino】
【步进电机和 Arduino】 前言1. 什么是步进电机及其工作原理?1.1 步进电机结构1.2 绕线方式1.3 通电方式2. 如何使用Arduino和A17步进驱动器控制NEMA4988步进电机2.1 A4988 和 Arduino 连接2.2 测量AB相2.3 A4988 限流3. 步进电机和 Arduino3.1 示例代码 13.2 示例代码 24. 使…...
【面试一:|和||、和区别】
相同点: ||和&&都是逻辑运算符,而|和&是位运算符。位运算符的优先级要比逻辑运算符的优先级高。 &和&&的区别 &和&&都可以用作逻辑与的运算符,表示逻辑与(and),当运…...
【一天一门编程语言】使用汇编语言实现斐波那契数列
文章目录使用汇编语言实现斐波那契数列一、什么是斐波那契数列二、如何用汇编语言实现斐波那契数列一、汇编语言概念1.1 什么是汇编语言1.2 汇编语言的特点二、汇编语言指令2.1 简单指令2.2 复杂指令汇编语言程序结构代码实例指令集常用指令指令代码实例使用汇编语言实现斐波那…...
RabbitMQ实现死信队列
目录死信队列是什么怎样实现一个死信队列说明实现过程导入依赖添加配置编写mq配置类添加业务队列的消费者添加死信队列的消费者添加消息发送者添加消息测试类测试死信队列的应用场景总结死信队列是什么 “死信”是RabbitMQ中的一种消息机制,当你在消费消息时&#…...
【Linux】安装Tomcat教程
目录 1.上传安装包 2.解压安装包 3.启动Tomcat 4.查看启动日志 5.查看进程 6.开放端口 7.停止Tomcat 1.上传安装包 使用FinalShell自带的上传工具将Tomcat的二进制发布包上传到Linux(与前面上传JDK安装包步骤 一致)。 2.解压安装包 将上传上来的安装包解压到指定目录…...
学习笔记之Vuex(五)
Vuex(五)Vuex一、什么是Vuex二、Vuex工作原理三、搭建Vuex环境四、求和案例分析4.1 求和案例——vue实现4.2 求和案例——vuex实现(五)Vuex 一、什么是Vuex 1.概念 在Vue中实现集中式状态(数据)管理的一…...
SSM知识快速复习
SSM知识快速复习SpringIOCDIIOC容器在Spring中的实现常用注解Autowired注解的原理AOP相关术语作用动态代理实现原理事务Transactional事务属性:只读事务属性:超时事务属性:回滚策略事务属性:事务隔离级别事务属性:事务…...
【Linux】安装MySQL
目录 1.检测当前系统是否安装过MySQL相关数据库 2. 卸载现有的MySQL数据库 3.上传解压 4.顺序安装rpm包 5.启动MySQL 6.查看临时密码 7.登录MySQL 8.开放端口 1.检测当前系统是否安装过MySQL相关数据库 需要通过rpm相关指令,来查询当前系统中是否存在已安…...
【深度学习】手把手教你开发自己的深度学习模板
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录前言1数据相关1.1 数据初探1.2.数据处理1.3 数据变形2 定义网络,优化函数3. 训练前言 入坑2年后,重新梳理之前的知识,发现其实需…...
一个诡异的 Pulsar InterruptedException 异常
背景 今天收到业务团队反馈线上有个应用往 Pulsar 中发送消息失败了,经过日志查看得知是发送消息时候抛出了 java.lang.InterruptedException 异常。 和业务沟通后得知是在一个 gRPC 接口中触发的消息发送,大约持续了半个小时的异常后便恢复正常了&…...
Java岗面试题--Java并发(volatile 专题)
目录1. 面试题一:谈谈 volatile 的使用及其原理补充:内存屏障volatile 的原理2. 面试题二:volatile 为什么不能保证原子性3. 面试题三:volatile 的内存语义4. 面试题四:volatile 的实现机制5. 面试题五:vol…...
Java---打家劫舍ⅠⅡ
目录 打家劫舍Ⅰ 题目分析 代码一 代码二 打家劫舍Ⅱ 打家劫舍Ⅰ 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被…...
MySQL Lesson4
1:关于查询结果集的去重(distinct) select distinct job from emp; **distinct只能出现在所有字段的最前面。所表示的含有是所有的结果联合起来去重。 select distinct deptno,job from emp order by deptno; select count(distinct job)from…...
浅谈权限获取方法之文件上传
概述 文件上传漏洞是发生在有上传功能的应用中,如果应用程序对用户的上传文件没有控制或者存在缺陷,攻击者可以利用应用上传功能存在的缺陷,上传木马、病毒等有危害的文件到服务器上面,控制服务器。 漏洞成因及危害 文件上传漏…...
资产设备防拆标签安全防护和资产定位解决方案
随着社会经济的发展和高新技术的日新月异,对各方面的安全要求也在不断地提高,以物联网安防、入侵报警和出入口控制、应急系统等为主的安全防范系统日益成为各类文物场所智能化弱电工程不可或缺的组成部分,是重点资产管理场所内加强管理和安全…...
企业电子招标采购源码之电子招标投标全流程!
随着各级政府部门的大力推进,以及国内互联网的建设,电子招投标已经逐渐成为国内主流的招标投标方式,但是依然有很多人对电子招投标的流程不够了解,在具体操作上存在困难。虽然各个交易平台的招标投标在线操作会略有不同࿰…...
【考研408】计算机网络笔记
文章目录计算机网络体系结构计算机网络概述计算机网络的组成计算机网络的功能计算机网络的分类计算机网络的性能指标课后习题计算机网络体系结构与参考模型计算机网络协议、接口、服务的概念ISO/OSI参考模型和TCP/IP模型课后习题物理层通信基础基本概念奈奎斯特定理与香农定理编…...
[C++]继承
🥁作者: 华丞臧 📕专栏:【C】 各位读者老爷如果觉得博主写的不错,请诸位多多支持(点赞收藏关注)。如果有错误的地方,欢迎在评论区指出。 推荐一款刷题网站 👉LeetCode 文章目录一、继承…...
优化知识管理方法丨整理零碎信息,提高数据价值
信息流时代,知识成集合倍数增长,看似我们学习了很多知识,但知识零碎无系统,知识之间缺乏联系,没有深度,所以虽然你很努力,但你发现自己的能力增长特别缓慢,你需要整理知识将零散的知…...
Windows操作系统的体系结构、运行环境和运行状态
我是荔园微风,作为一名在IT界整整25年的老兵,今天我们来重新审视一下Windows这个我们熟悉的不能再熟悉的系统。说Windows操作系统的运行环境和运行状态,首先要介绍一下Windows操作系统的体系结构,然后再要说到最重要的两个概念:核…...
【工作笔记】Http响应头过长
起因 突然有测试小伙伴反馈进公司官网主页会白屏,但只是个例不是普遍现象 查监控发现没监控到异常问题 查了很久(这个很久单指对于线上问题来说)才定位是请求的异常,因为这套系统的异常用的是 ExceptionHandler,这也导…...
hive建分区表,分桶表,内部表,外部表
hive建分区表,分桶表,内部表,外部表 一、概念介绍 Hive是基于Hadoop的一个工具,用来帮助不熟悉 MapReduce的人使用SQL对存储在Hadoop中的大规模数据进行数据提取、转化、加载。Hive数据仓库工具能将结构化的数据文件映射为一张数…...
【分享】灌溉制度设计小程序VB源代码
说明 根据作物需水特性和当地气候、土壤、农业技术及灌水技术等因素制定的灌水方案。主要内容包括灌水次数、灌水时间、灌水定额和灌溉定额。灌溉制度是规划、设计灌溉工程和进行灌区运行管理的基本资料,是编制和执行灌区用水计划的重要依据。 1—计划湿润土层允…...
PR9268/300-000库存现货振动传感器 雄霸工控
PR9268/300-000库存现货振动传感器 雄霸工控PR9268/300-000库存现货振动传感器 雄霸工控SDM010PR9670/110-100PR9670/010-100PR9670/003-000PR9670/002-000PR9670/001-000PR9670/000-000PR9600/014-000PR9600/011-000PR9376/010-021PR9376/010-011PR9376/010-011PR9376/010-001…...
浅谈模型评估选择及重要性
作者:王同学 来源:投稿 编辑:学姐 模型评估作为机器学习领域一项不可分割的部分,却常常被大家忽略,其实在机器学习领域中重要的不仅仅是模型结构和参数量,对模型的评估也是至关重要的,只有选择那…...
多线程的初识和创建
✨个人主页:bit me👇 ✨当前专栏:Java EE初阶👇 ✨每日一语:知不足而奋进,望远山而前行。 目 录💤一. 认识线程(Thread)🍎1. 线程的引入🍏2. 线程…...
一句话设计模式3:工厂模式
工厂模式:new多种对象的简单方式。 文章目录 工厂模式:new多种对象的简单方式。前言一、两种工厂模式二、如何实现工厂模式1. 简单工厂2. 抽象工厂总结前言 工厂模式可以说比较常见的设计模式,仔细观察在很多源码中都有此种模式的应用;用来解决创建对象的创建问题; 一、两种工…...
【Codeforces Round #853 (Div. 2)】C. Serval and Toxel‘s Arrays【题解】
题目 Toxel likes arrays. Before traveling to the Paldea region, Serval gave him an array aaa as a gift. This array has nnn pairwise distinct elements. In order to get more arrays, Toxel performed mmm operations with the initial array. In the iii-th opera…...
WordPress书籍插件/上首页seo
硬盘是用来存储数据的,为了使用和管理方便,这些数据以文件的形式存储在硬盘上。任何操作系统都有自己的文件管理系统,不同的文件系统又有各自不同的逻辑组织方式。例如:常见的文件系统有FAT,NTFS,EXT&#…...
网站建设与管理教案怎么写/优化系统的软件
基础类可接收我们发给派生类的任何消息,因为两者拥有完全一致的接口。我们要做的全部事情就是从派生上溯造型,而且永远不需要回过头来检查对象的准确类型是什么。所有细节都已通过多态性获得了完美的控制。但经过细致的研究,我们发现扩展接口…...
有哪些网站主页做的比较好看/搜索引擎营销优缺点
库内新增对象Products 的流程说明:第一步: com.jeecms.cms.entity.assist.base下建立模型基础类,BaseCmsProducts.java com.jeecms.cms.entity.assist 下建立对象类继承继承模型,CmsProducts.java com.jeecms.cms.entity.assist.…...
wordpress订单邮件内容修改/廊坊百度关键词优化怎么做
我直接就打开了,而且还显示了旧的仓库,没有提示要登录注册什么的 MacOS SourceTree 安装与使用 - 简书...
抓取网站后台/广州网站建设费用
一面 自我介绍项目中的监控:那个监控指标常见的有哪些?微服务涉及到的技术以及需要注意的问题有哪些?注册中心你了解了哪些?consul 的可靠性你了解吗?consul 的机制你有没有具体深入过?有没有和其他的注册…...
网站建设的简洁性/百度智能建站系统
AngularJS路由报错: Unknown provider: $routeProvider根据先知们的指引,在网上爬贴,有翻到官方的解决文章。原来在AgularJS1.2.0及其之后的版本中,ngRoute已经移动到单独的文件当中,再使用则需要载入angular-route.js这一文件&am…...