從微信小程序到鴻蒙JS開發-menu&toast&dialog
https://harmonyos.51cto.com/#zz
1、menu彈出菜單
這是微信小程序沒有的一個組件,提供了一個可喚起的輕量級彈出菜單。menu的子組件為option。
- <menu id="userMenu" onselected="menuSelect">
- <option value="login">登錄</option>
- <option value="register">注冊</option>
- </menu>
在hml中寫好菜單,但這時啟動app是不會顯示出來的,且不會占用任何頁面空間。
menu需要在方法中被喚起,因此需要設置id屬性。這里通過點擊“點擊登錄/注冊“文本框喚起菜單:
- <text if="{{ !userInfo }}" onclick="showUserMenu" class="info_hint">
- 點擊登錄/注冊
- </text>
- showUserMenu() {
- this.$element("userMenu").show();
- }
使用無參的show()方法,菜單在頁面的左上角被喚起彈出。
show方法還有一個重載方法,可以設置菜單彈出的x軸和y軸偏移量。x和y需要給數值類型,單位為px。
- showUserMenu() {
- this.$element("userMenu").show({
- x: 100,
- y: 100
- });
- }
菜單項的選中事件通過onselect屬性綁定,event.value即為選中的option的value屬性。
- menuSelect(event) {
- let value = event.value;
- prompt.showToast({
- message: "點擊菜單項的值為" + value,
- duration: 3000
- })
- }
option一定要設置value屬性,否則編譯不通過。value重復倒是不會報錯,但這樣無法判斷選中了哪一個菜單項,不建議。

2、Toast提示框
鴻蒙js開發模式至今無法通過console.log()等方法打印日志(mac系統如此),但在寫程序時不免要進行調試,提示框就是一種很好的方法。
在js文件中引入prompt模塊:
- import prompt from '@system.prompt';
調用prompt.showToast()彈出提示框:
- prompt.showToast({
- message: "提示信息",
- duration: 3000
- });
這個方法只能傳遞message和duration兩個參數,彈出位置是在頁面接近最下方中間位置,而且字有點小。
源碼注釋中說明,duration取值是1500到10000,如果不在范圍中會自動更改為邊界值。
再看看微信小程序的Toast,使用wx.showToast彈出。
- wx.showToast({
- title: '提示信息',
- duration: 3000
- })
彈出位置在頁面正中,且可以切換預置,或自定義圖標。
- wx.showToast({
- title: '常回家看看',
- duration: 3000,
- icon: 'none',
- image: "/icon/index1.png"
- })
就是這個圖標位置怪怪的,但個人感覺這種提示彈窗更加明顯,可擴展性也更強。
3、prompt模塊的對話框dialog
需要用戶確認操作的功能十分常用,比如是否刪除,是否下單等。在微信小程序中采用的是wx.showModal(),彈窗內容、按鈕內容和顏色都可以自定義,事件在success函數中進行捕獲:
- wx.showModal({
- title: "提示",
- content: "確認刪除嗎?",
- confirmColor: "#e20a0b",
- confirmText: "對,刪了它",
- cancelColor: "#777777",
- cancelText: "再考慮一下",
- success: res => {
- if(res.confirm) {
- console.log("刪除成功!");
- } else if(res.cancel) {
- console.log("取消刪除操作。")
- }
- }
- })
在鴻蒙中,prompt模塊的showDialog()方法提供了彈出對話框:
- prompt.showDialog({
- title: "操作提示",
- message: "確認刪除嗎?",
- buttons: [
- {
- text: "我要刪除",
- color: "#e20a0b"
- },
- {
- text: "取消操作",
- color: "#777777"
- }
- ],
- success: res => {
- prompt.showToast({
- message: "點擊了第" + res.index + "個按鈕"
- })
- }
- })
對話框也是在底部彈出的,且按鈕可以自行定義。點擊按鈕后,success方法會獲取按鈕的索引值,根據索引進行業務邏輯的編寫。
想要設置三個按鈕也是可以的,這個功能微信小程序的showModal()是沒有的。
- prompt.showDialog({
- title: "操作提示",
- message: "確認刪除嗎?",
- buttons: [
- {
- text: "我要刪除",
- color: "#e20a0b"
- },
- {
- text: "取消操作",
- color: "#777777"
- },
- {
- text: "附加按鈕",
- color: "#333333"
- }
- ],
- success: res => {
- prompt.showToast({
- message: "點擊了第" + res.index + "個按鈕"
- })
- }
- })
4、dialog對話框組件
prompt.showDialog()只能彈出具有提示文字和按鈕的對話框,如果需要更豐富的模態對話框功能,鴻蒙還提供了dialog組件,這個組件在微信小程序中也是沒有的。和menu一樣,寫在hml中的dialog并不會顯示,也不會占用頁面空間,需要通過id在方法中被喚起。
- <dialog id="loginDialog">
- <div class="loginDialog">
- <div class="formItem">
- <image src="{{ phone ? (imgUrl + 'phone.png') : (imgUrl + 'phone1.png') }}"></image>
- <input id="phoneInput" type="number" placeholder="請輸入手機號" onchange="inputPhone"></input>
- </div>
- <div class="formItem">
- <image src="{{ pwd ? (imgUrl + 'password.png') : (imgUrl + 'password1.png') }}"></image>
- <input id="pwdInput" type="password" placeholder="請輸入密碼" onchange="inputPwd"></input>
- </div>
- <button class="inputBtn" onclick="login">登錄</button>
- </div>
- </dialog>
這里需注意,官方文檔中說的“支持單個子組件”的意思是,dialog中只能有一個直接子組件,即需要用一個div將內容套起來。
同樣地,根據id找到元素,使用show()方法喚起對話框。對話框的show()方法無重載,會在頁面底部彈出。dialog的大小取決于子組件div的大小,div給樣式即可。
- menuSelect(event) {
- let value = event.value;
- if ("login" == value) {
- this.phone = "";
- this.pwd = "";
- this.$element("loginDialog").show();
- } else if ("register" == value) {
- this.phone = "";
- this.pwd = "";
- this.$element("registerDialog").show();
- }
- },
可用close()方法關閉它。
- this.$element("registerDialog").close();
附上本頁面的代碼,后臺功能自己搭建了Spring Boot服務器進行交互。下篇將講解表單組件:
- <!-- 我的 -->
- <div class="myPage">
- <div class="userInfo">
- <image src="{{ userInfo && userInfo.avatar != '0' ? userInfo.avatar : (imgUrl + 'user.png')}}"></image>
- <div class="info_desc">
- <text if="{{ !userInfo }}" onclick="showUserMenu" class="info_hint">
- 點擊登錄/注冊
- </text>
- <text if="{{ userInfo }}" class="info_name">
- {{ userInfo.nickname ? userInfo.nickname : userInfo.username }}
- </text>
- <text if="{{ userInfo }}" class="info_detail">
- {{ userInfo.age }} {{ userInfo.gender == 1 ? '男' : (userInfo.gender == 2 ? '女' : '性別保密') }}
- </text>
- </div>
- </div>
- <menu id="userMenu" onselected="menuSelect">
- <option value="login">登錄</option>
- <option value="register">注冊</option>
- </menu>
- <dialog id="loginDialog">
- <div class="loginDialog">
- <div class="formItem">
- <image src="{{ phone ? (imgUrl + 'phone.png') : (imgUrl + 'phone1.png') }}"></image>
- <input id="phoneInput" type="number" placeholder="請輸入手機號" onchange="inputPhone"></input>
- </div>
- <div class="formItem">
- <image src="{{ pwd ? (imgUrl + 'password.png') : (imgUrl + 'password1.png') }}"></image>
- <input id="pwdInput" type="password" placeholder="請輸入密碼" onchange="inputPwd"></input>
- </div>
- <button class="inputBtn" onclick="login">登錄</button>
- </div>
- </dialog>
- </div>
- <!-- 我的end -->
css:
- /*我的*/
- .userInfo {
- width: 92%;
- height: 240px;
- margin: 20px 0 20px 0;
- border-radius: 30px;
- box-shadow: 5px 5px 15px #bbbbbb;
- background-color: #eeeeee;
- display: flex;
- align-items: center;
- }
- .userInfo>image {
- margin: 0 40px 0 40px;
- width: 160px;
- height: 160px;
- border-radius: 90px;
- object-fit: contain;
- }
- .info_desc {
- height: 200px;
- margin-right: 20px;
- flex: 1;
- display: flex;
- flex-direction: column;
- justify-content: center;
- }
- .info_hint {
- font-size: 48px;
- font-weight: bold;
- color: #333333;
- }
- .info_name {
- font-size: 40px;
- font-weight: 600;
- height: 100px;
- color: #333333;
- }
- .info_detail {
- font-size: 34px;
- color: #666666;
- }
- .loginDialog {
- width: 80%;
- height: 400px;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- }
- .formItem {
- width: 100%;
- height: 100px;
- display: flex;
- align-items: center;
- justify-content: space-between;
- margin-bottom: 20px;
- }
- .formItem>image {
- width: 70px;
- height: 70px;
- margin: 0 10px 0 10px;
- }
- input {
- flex: 1;
- }
- .inputBtn {
- width: 200px;
- height: 70px;
- }
js:(省略data部分)
- // 彈出菜單
- showUserMenu() {
- this.$element("userMenu").show();
- },
- // 菜單選中
- menuSelect(event) {
- let value = event.value;
- if ("login" == value) {
- this.phone = "";
- this.pwd = "";
- this.$element("loginDialog").show();
- } else if ("register" == value) {
- this.phone = "";
- this.pwd = "";
- // this.$element("registerDialog").show();
- }
- },
- // 手機號輸入框
- inputPhone(e) {
- this.phone = e.value;
- },
- // 密碼輸入框
- inputPwd(e) {
- this.pwd = e.value;
- },
- // 登錄
- login() {
- fetch.fetch({
- url: this.url + "/litemall/user/login?phone=" + this.phone + "&pwd=" + this.pwd,
- responseType: "json",
- success: res => {
- let data = JSON.parse(res.data);
- if (0 != data.code) {
- prompt.showToast({
- message: data.msg,
- duration: 3000
- })
- } else {
- this.userInfo = data.data;
- this.$element("loginDialog").close();
- }
- }
- })
- }
登錄成功效果:
https://harmonyos.51cto.com/#zz