接下來,我將圍繞一個常見的電商小程序來構建一系列連貫的使用場景。在這個過程中,我們將把 <navigator>
組件的所有關鍵屬性和方法都串聯起來,并詳細解釋它們在每個環節所扮演的角色和作用。
核心場景:構建一個電商小程序的用戶購物流程
想象一下,我們正在開發一個名為“優品匯”的電商小程序。用戶可以瀏覽商品、查看詳情、加入購物車、下單支付、以及跳轉到合作的客服小程序。這個流程幾乎涵蓋了 <navigator>
的所有核心功能。
準備工作:項目結構與 pages.json
請在你的 uni-app
項目中,確保有如下的目錄結構,并將 pages.json
文件配置如下。這為我們所有的導航場景提供了基礎。
目錄結構 (部分):
├── pages
│ ├── index
│ │ └── index.vue
│ ├── product
│ │ ├── list.vue
│ │ └── detail.vue
│ ├── order
│ │ ├── list.vue
│ │ └── detail.vue
│ ├── payment
│ │ └── success.vue
│ └── tabBar
│ ├── cart
│ │ └── cart.vue
│ └── my
│ └── my.vue
├── static
│ └── ...
└── pages.json
pages.json
配置:
{"pages": [{"path": "pages/index/index","style": { "navigationBarTitleText": "優品匯首頁" }},{"path": "pages/product/list","style": { "navigationBarTitleText": "商品列表" }},{"path": "pages/product/detail","style": { "navigationBarTitleText": "商品詳情" }},{"path": "pages/order/list","style": { "navigationBarTitleText": "我的訂單" }},{"path": "pages/order/detail","style": { "navigationBarTitleText": "訂單詳情" }},{"path": "pages/payment/success","style": { "navigationBarTitleText": "支付成功" }},{"path": "pages/tabBar/cart/cart","style": { "navigationBarTitleText": "購物車" }},{"path": "pages/tabBar/my/my","style": { "navigationBarTitleText": "我的" }}],"globalStyle": {"navigationBarTextStyle": "black","navigationBarTitleText": "優品匯","navigationBarBackgroundColor": "#F8F8F8","backgroundColor": "#F8F8F8"},"tabBar": {"list": [{"pagePath": "pages/index/index","text": "首頁"},{"pagePath": "pages/tabBar/cart/cart","text": "購物車"},{"pagePath": "pages/tabBar/my/my","text": "我的"}]}
}
場景一:從首頁進入商品列表頁(基礎跳轉與交互定制)
用戶故事: 用戶點擊首頁“限時搶購”入口,平滑跳轉到商品列表頁,并能看到清晰的點擊反饋。
1. 首頁 pages/index/index.vue
(源頁面)
<template><view class="content"><view class="promo-section"><!-- 這是一個典型的頁面跳轉。我們在這里定制了用戶交互的每一個細節。--><navigatorurl="/pages/product/list?activityId=promo123&from=home"open-type="navigate"hover-class="promo-hover":hover-start-time="50":hover-stay-time="200"><view class="promo-card"><text class="promo-title">限時搶購</text><text class="promo-desc">點擊查看詳情</text></view></navigator></view></view>
</template><script>
export default {data() {return {};}
};
</script><style>
.content {padding: 40rpx;
}
.promo-card {background-color: #e54d42;color: white;padding: 60rpx 40rpx;border-radius: 16rpx;text-align: center;box-shadow: 0 4px 10px rgba(229, 77, 66, 0.4);
}
.promo-title {font-size: 48rpx;font-weight: bold;
}
.promo-desc {font-size: 28rpx;margin-top: 10rpx;opacity: 0.9;
}
/* 自定義點擊效果:輕微下沉和變暗 */
.promo-hover {opacity: 0.9;transform: scale(0.98);transition: all 0.2s;
}
</style>
2. 商品列表頁 pages/product/list.vue
(目標頁面)
<template><view class="container"><view v-if="activityId" class="activity-banner"><text>當前活動ID:{{ activityId }}</text><text>來源頁面:{{ fromPage }}</text></view><view class="product-list"><text>這里是商品列表...</text></view></view>
</template><script>
export default {data() {return {activityId: '',fromPage: ''};},// onLoad生命周期函數用于接收頁面參數onLoad(options) {console.log('接收到的頁面參數:', options);if (options.activityId) {this.activityId = options.activityId;}if (options.from) {this.fromPage = options.from;}}
};
</script><style>
.container {padding: 20rpx;
}
.activity-banner {background-color: #fffbe6;border: 1px solid #ffe58f;padding: 20rpx;border-radius: 8rpx;margin-bottom: 20rpx;display: flex;flex-direction: column;
}
</style>
關鍵屬性解析:
-
url: "/pages/product/list?activityId=promo123"
- 作用: 定義了導航的目標路徑。這里我們使用了相對路徑,并附帶了一個查詢參數
activityId
,這樣商品列表頁(list.vue
)就能通過onLoad
生命周期函數獲取到這個參數,從而展示特定活動下的商品。這是頁面間通信最常用、最基礎的方式。
- 作用: 定義了導航的目標路徑。這里我們使用了相對路徑,并附帶了一個查詢參數
-
open-type: "navigate"
- 作用: 這是最標準的跳轉方式,它會“保留”當前頁面(首頁),然后“推入”一個新的頁面(商品列表頁)到頁面棧中。用戶可以從商品列表頁通過左上角的返回按鈕回到首頁。這符合用戶“進入-返回”的心智模型。
-
hover-class: "promo-hover"
- 作用: 極大地提升了用戶體驗。當用戶的指尖按下這個區域時,會立即應用
.promo-hover
這個 CSS 類,提供一個即時的視覺反饋(在這里是透明度和縮放效果)。這告訴用戶:“系統已經響應了你的操作”。
- 作用: 極大地提升了用戶體驗。當用戶的指尖按下這個區域時,會立即應用
-
hover-start-time: 50
- 作用: 定義了從用戶按下到
hover-class
生效的延遲時間(50毫秒)。這個值可以防止用戶在快速劃過屏幕時不小心觸發點擊效果,讓交互更精準。
- 作用: 定義了從用戶按下到
-
hover-stay-time: 200
- 作用: 定義了用戶手指松開后,點擊效果還會“停留”的時間(200毫秒)。這給用戶一種流暢、不生硬的感覺,尤其是在性能稍差的設備上,可以確保用戶能看到完整的點擊動畫。
代碼解析與運行指南:
- 作用: 定義了用戶手指松開后,點擊效果還會“停留”的時間(200毫秒)。這給用戶一種流暢、不生硬的感覺,尤其是在性能稍差的設備上,可以確保用戶能看到完整的點擊動畫。
- 運行項目,在首頁點擊“限時搶購”卡片。
- 你會觀察到卡片有輕微下沉和變暗的動畫效果,這是
hover-class
、hover-start-time
和hover-stay-time
共同作用的結果。 - 頁面會跳轉到“商品列表”,并且頁面頂部的黃色提示框會顯示出我們從
url
中傳遞過來的參數activityId
和from
。這驗證了onLoad
函數成功接收了參數。 - 你可以點擊原生導航欄的返回按鈕,會返回到首頁,這是
open-type="navigate"
的效果。
場景二:從商品列表跳轉到 TabBar 購物車頁
用戶故事: 在商品列表頁,用戶點擊懸浮的購物車圖標,直接切換到底部導航的購物車頁面。
1. 商品列表頁 pages/product/list.vue
(在場景一的基礎上增加)
<template><view class="container"><!-- ... (場景一中的代碼) ... --><view class="product-list"><text>這里是商品列表...</text><!-- 在這里添加一個跳轉到商品詳情的鏈接,為場景五做準備 --><navigatorurl="/pages/product/detail?id=P001"open-type="navigate"class="product-item-link"animation-type="fade-in":animation-duration="400"><button type="default">查看商品P001詳情(App有漸變動畫)</button></navigator></view><!-- 購物車懸浮按鈕 --><navigatorurl="/pages/tabBar/cart/cart"open-type="switchTab"hover-class="none"><view class="fab-cart-btn"><text>🛒</text></view></navigator></view>
</template><script>
// ... (與場景一相同) ...
export default {data() {return {activityId: '',fromPage: ''};},onLoad(options) {console.log('接收到的頁面參數:', options);if (options.activityId) {this.activityId = options.activityId;}if (options.from) {this.fromPage = options.from;}}
};
</script><style>
/* ... (場景一的樣式) ... */
.container {padding: 20rpx;
}
.activity-banner {background-color: #fffbe6;border: 1px solid #ffe58f;padding: 20rpx;border-radius: 8rpx;margin-bottom: 20rpx;display: flex;flex-direction: column;
}
.product-item-link {margin-top: 40rpx;
}
.fab-cart-btn {position: fixed;bottom: 100rpx;right: 40rpx;width: 100rpx;height: 100rpx;background-color: #007aff;border-radius: 50%;display: flex;justify-content: center;align-items: center;font-size: 50rpx;color: white;box-shadow: 0 4px 12px rgba(0, 122, 255, 0.4);
}
</style>
2. 購物車頁 pages/tabBar/cart/cart.vue
(目標頁面)
<template><view><view class="title">購物車</view><text>這里是您的購物車頁面。</text></view>
</template>
代碼解析與運行指南:
- 從首頁進入商品列表頁。
- 點擊右下角的藍色圓形購物車按鈕。
- 應用會立即切換到“購物車”Tab,并且底部的 TabBar 會高亮“購物車”項。
- 核心觀察點: 此時,你無法通過返回手勢或返回按鈕回到“商品列表頁”。這是因為
open-type="switchTab"
清空了所有非 TabBar 的頁面棧,確保了導航的扁平化。 hover-class="none"
確保了點擊這個圖標按鈕時,它本身不會有任何多余的視覺變化。
場景三:下單成功后,使用 redirect
和 reLaunch
用戶故事: 用戶支付成功后,可以選擇“查看訂單”(不希望再返回支付頁)或“返回首頁”(開始一次全新的會話)。
1. 支付成功頁 pages/payment/success.vue
<template><view class="container"><view class="icon-success">?</view><text class="status-text">支付成功!</text><view class="button-area"><!-- 使用 reLaunch 返回首頁。這會清空所有頁面棧,只留下首頁。--><navigator url="/pages/index/index" open-type="reLaunch"><button class="plain-btn">返回首頁</button></navigator><!-- 使用 redirect 跳轉到訂單頁。這會關閉當前頁面,用訂單列表頁替換它。--><navigator url="/pages/order/list" open-type="redirect"><button type="primary">查看訂單</button></navigator></view></view>
</template><script>
export default {data() {return {};}
};
</script><style>
.container {display: flex;flex-direction: column;align-items: center;padding-top: 150rpx;
}
.icon-success {font-size: 120rpx;color: #09bb07;border: 5px solid #09bb07;border-radius: 50%;width: 180rpx;height: 180rpx;display: flex;justify-content: center;align-items: center;
}
.status-text {font-size: 40rpx;margin-top: 40rpx;margin-bottom: 80rpx;
}
.button-area {display: flex;width: 100%;justify-content: space-around;
}
.plain-btn {background-color: white;border: 1px solid #ccc;
}
</style>
2. 訂單列表頁 pages/order/list.vue
(目標頁面)
<template><view><text>這是您的訂單列表。</text></view>
</template>
代碼解析與運行指南:
- 為了模擬,你可以先手動跳轉到支付成功頁(例如,在首頁加一個臨時的
<navigator url="/pages/payment/success">
)。 - 測試
redirect
: 點擊“查看訂單”按鈕。頁面會跳轉到訂單列表。此時,點擊導航欄返回按鈕,你會發現你回到了進入支付成功頁之前的那個頁面(比如首頁),而不是支付成功頁。這證明了redirect
成功地替換了頁面棧中的當前頁。 - 測試
reLaunch
: 重新進入支付成功頁。這次點擊“返回首頁”按鈕。頁面會跳轉到首頁。此時,頁面棧被完全清空,你無法返回到任何之前的頁面,就像剛打開小程序一樣。
場景四:navigateBack
, target
與 hover-stop-propagation
用戶故事: 在訂單詳情頁,用戶可以返回多級頁面、跳轉到客服小程序,并與頁面內復雜組件進行無干擾的交互。
1. 訂單詳情頁 pages/order/detail.vue
為了模擬此場景,你需要手動按順序打開頁面:首頁 -> 我的(Tab) -> [添加一個按鈕跳轉到訂單列表] -> [訂單列表頁添加按鈕跳轉到訂單詳情]
。這樣才能構造出足夠深的頁面棧。
<template><view class="container"><text class="title">訂單詳情</text><!-- 場景4.1: 返回多級頁面 --><view class="card"><text>假設我們的頁面路徑是: 我的 -> 訂單列表 -> 訂單詳情。</text><text>點擊下方按鈕將直接返回“我的”頁面。</text><navigator open-type="navigateBack" :delta="2"><button type="default">返回“我的” (返回2級)</button></navigator></view><!-- 場景4.2: 跳轉到外部小程序 --><view class="card"><text>點擊下方按鈕,將打開合作的客服小程序。</text><!-- 注意: app-id需要真實存在且在manifest.json中配置 --><navigatortarget="miniProgram"open-type="navigate"app-id="wxf8e0cf27a58a75e2" path="pages/index/index"><button type="primary">聯系客服(跳轉到“小程序示例”)</button></navigator></view><!-- 場景4.3: 阻止事件冒泡 --><view class="card"><text>下方卡片整體可點擊,但內部按鈕的點擊效果不會影響卡片。</text><navigator url="/pages/product/detail?id=P002" class="product-card" hover-class="card-hover"><view class="product-info"><text>可點擊的商品卡片</text><text>點擊空白處或文字,整個卡片會有點擊效果。</text></view><!-- @click.native 確保在navigator內button的點擊事件能觸發 --><button class="fav-button" :hover-stop-propagation="true" @click.native="onFavorite">收藏</button></navigator></view></view>
</template><script>
export default {methods: {onFavorite() {uni.showToast({title: '收藏成功!',icon: 'none'});// 這里會執行收藏邏輯,但不會觸發父級navigator的hover效果}}
}
</script><style>
.container { padding: 20rpx; }
.card { margin-bottom: 30rpx; padding: 20rpx; border: 1px solid #eee; border-radius: 8rpx; }
.title { font-size: 36rpx; font-weight: bold; margin-bottom: 20rpx; }
button { margin-top: 20rpx; }.product-card {display: flex;justify-content: space-between;align-items: center;padding: 20rpx;background-color: #f9f9f9;border-radius: 8rpx;
}
.card-hover {background-color: #e0e0e0;
}
.fav-button {margin: 0; /* 重置按鈕的默認margin */background-color: #ffc107;color: white;
}
</style>
代碼解析與運行指南:
navigateBack
&delta
: 確保你有至少3層頁面棧(如我的
->訂單列表
->訂單詳情
)。在訂單詳情頁點擊“返回‘我的’”按鈕,你會看到應用跳過了訂單列表,直接回到了“我的”頁面。target="miniProgram"
: 點擊“聯系客服”按鈕。如果你的環境支持(如微信開發者工具或真機)且app-id
有效(這里用的是微信官方的“小程序示例”appid),它會拉起另一個小程序。hover-stop-propagation
:- 先點擊“可點擊的商品卡片”的文字或空白區域,整個卡片背景會變灰(
card-hover
效果)。 - 然后,只點擊黃色的“收藏”按鈕。你會看到按鈕有自己的點擊效果,并且彈出了“收藏成功!”的提示,但整個卡片的背景不會變灰。這證明了
hover-stop-propagation
成功阻止了點擊態的冒泡。
- 先點擊“可點擊的商品卡片”的文字或空白區域,整個卡片背景會變灰(
場景五:為 App 端定制頁面過渡動畫
用戶故事: 在 App 端,從商品列表點擊某個商品時,希望商品詳情頁以“漸顯”的方式出現,而不是平臺默認的側滑。
1. 商品列表頁 pages/product/list.vue
(在場景二的代碼中已包含)
我們復用場景二中的代碼,重點關注那個跳轉到詳情頁的 <navigator>
。
<!-- 在 pages/product/list.vue 中 -->
<navigatorurl="/pages/product/detail?id=P001"open-type="navigate"class="product-item-link"<!-- 以下兩個屬性是本場景核心 -->animation-type="fade-in":animation-duration="400"
><button type="default">查看商品P001詳情(App有漸變動畫)</button>
</navigator>
2. 商品詳情頁 pages/product/detail.vue
(目標頁面)
<template><view><text>商品詳情頁</text><text v-if="productId">商品ID: {{ productId }}</text></view>
</template><script>export default {data() {return {productId: ''}},onLoad(options) {this.productId = options.id}}
</script>
代碼解析與運行指南:
- 重要: 此效果僅在 App 端可見。請使用 HBuilderX 將項目運行到手機或模擬器上。在小程序開發者工具或 H5 端,這兩個屬性會被忽略。
- 在 App 中,從首頁進入商品列表頁。
- 點擊“查看商品P001詳情”按鈕。
- 你會觀察到,商品詳情頁不是從右側滑入的,而是以一個持續 400 毫秒的漸顯動畫出現。返回時,它會以“漸隱”動畫消失。
- 這證明了
animation-type
和animation-duration
成功地定制了 App 端的原生轉場動畫,提升了應用的獨特性和品質感。