บันทึก
คำตอบที่แนะนำให้ใช้รูปแบบต่างๆของ$window.history.back()
ทุกคนพลาดส่วนสำคัญของคำถาม: วิธีกู้คืนสถานะของแอปพลิเคชันไปยังตำแหน่งสถานะที่ถูกต้องเมื่อประวัติกระโดด (ย้อนกลับ / ไปข้างหน้า / รีเฟรช) ด้วยสิ่งนั้นในใจ; โปรดอ่านต่อ
ใช่เป็นไปได้ที่จะให้เบราว์เซอร์ย้อนกลับ / ไปข้างหน้า (ประวัติ) และรีเฟรชในขณะที่เรียกใช้เครื่องui-router
สถานะบริสุทธิ์แต่ต้องใช้เวลาสักหน่อย
คุณต้องมีส่วนประกอบหลายอย่าง:
URL ที่ไม่ซ้ำ เบราว์เซอร์จะเปิดใช้งานปุ่มย้อนกลับ / ไปข้างหน้าเมื่อคุณเปลี่ยน URL เท่านั้นดังนั้นคุณต้องสร้าง URL ที่ไม่ซ้ำกันต่อรัฐที่เยี่ยมชม URL เหล่านี้ไม่จำเป็นต้องมีข้อมูลสถานะใด ๆ
บริการเซสชัน URL ที่สร้างขึ้นแต่ละรายการมีความสัมพันธ์กับสถานะหนึ่ง ๆ ดังนั้นคุณต้องมีวิธีในการจัดเก็บคู่สถานะ URL ของคุณเพื่อให้คุณสามารถดึงข้อมูลสถานะได้หลังจากที่แอปเชิงมุมของคุณถูกรีสตาร์ทโดยการคลิกย้อนกลับ / ไปข้างหน้าหรือรีเฟรช
ประวัติความเป็นมาของรัฐ พจนานุกรมง่ายๆของสถานะ ui-router ที่คีย์ด้วย URL ที่ไม่ซ้ำกัน หากคุณสามารถพึ่งพา HTML5 ได้คุณก็สามารถใช้HTML5 History APIได้ แต่ถ้าเช่นฉันคุณไม่สามารถใช้งานได้ด้วยตัวเองในโค้ดไม่กี่บรรทัด (ดูด้านล่าง)
บริการระบุตำแหน่ง สุดท้ายคุณต้องสามารถจัดการทั้งการเปลี่ยนแปลงสถานะของเราเตอร์ ui-router ซึ่งถูกเรียกใช้ภายในโดยรหัสของคุณและการเปลี่ยนแปลง url ของเบราว์เซอร์ตามปกติมักเกิดจากการที่ผู้ใช้คลิกปุ่มเบราว์เซอร์หรือพิมพ์สิ่งต่างๆลงในแถบเบราว์เซอร์ ทั้งหมดนี้อาจเป็นเรื่องยุ่งยากเล็กน้อยเพราะมันง่ายที่จะสับสนเกี่ยวกับสิ่งที่กระตุ้นให้เกิดอะไรขึ้น
นี่คือการดำเนินการตามข้อกำหนดเหล่านี้ของฉัน ฉันได้รวมทุกอย่างไว้เป็นสามบริการ:
บริการเซสชัน
class SessionService
setStorage:(key, value) ->
json = if value is undefined then null else JSON.stringify value
sessionStorage.setItem key, json
getStorage:(key)->
JSON.parse sessionStorage.getItem key
clear: ->
@setStorage(key, null) for key of sessionStorage
stateHistory:(value=null) ->
@accessor 'stateHistory', value
accessor:(name, value)->
return @getStorage name unless value?
@setStorage name, value
angular
.module 'app.Services'
.service 'sessionService', SessionService
นี่คือกระดาษห่อหุ้มสำหรับsessionStorage
วัตถุจาวาสคริปต์ ฉันได้ตัดมันลงเพื่อความชัดเจนที่นี่ สำหรับคำอธิบายทั้งหมดโปรดดู: ฉันจะจัดการกับการรีเฟรชหน้าด้วยแอปพลิเคชัน AngularJS Single Page ได้อย่างไร
บริการประวัติศาสตร์ของรัฐ
class StateHistoryService
@$inject:['sessionService']
constructor:(@sessionService) ->
set:(key, state)->
history = @sessionService.stateHistory() ? {}
history[key] = state
@sessionService.stateHistory history
get:(key)->
@sessionService.stateHistory()?[key]
angular
.module 'app.Services'
.service 'stateHistoryService', StateHistoryService
StateHistoryService
ดูหลังจากการจัดเก็บและการดึงของรัฐประวัติศาสตร์คีย์โดยการสร้าง URL ที่ไม่ซ้ำกัน มันเป็นเพียงเครื่องห่อหุ้มที่สะดวกสำหรับวัตถุสไตล์พจนานุกรม
บริการตำแหน่งของรัฐ
class StateLocationService
preventCall:[]
@$inject:['$location','$state', 'stateHistoryService']
constructor:(@location, @state, @stateHistoryService) ->
locationChange: ->
return if @preventCall.pop('locationChange')?
entry = @stateHistoryService.get @location.url()
return unless entry?
@preventCall.push 'stateChange'
@state.go entry.name, entry.params, {location:false}
stateChange: ->
return if @preventCall.pop('stateChange')?
entry = {name: @state.current.name, params: @state.params}
url = "/#{@state.params.subscriptionUrl}/#{Math.guid().substr(0,8)}"
@stateHistoryService.set url, entry
@preventCall.push 'locationChange'
@location.url url
angular
.module 'app.Services'
.service 'stateLocationService', StateLocationService
StateLocationService
จับสองเหตุการณ์:
locationChange . สิ่งนี้เรียกว่าเมื่อตำแหน่งของเบราว์เซอร์มีการเปลี่ยนแปลงโดยทั่วไปเมื่อกดปุ่มย้อนกลับ / ไปข้างหน้า / รีเฟรชหรือเมื่อแอปเริ่มทำงานครั้งแรกหรือเมื่อผู้ใช้พิมพ์ URL หากรัฐสำหรับ location.url ปัจจุบันที่มีอยู่ในStateHistoryService
นั้นจะใช้ในการเรียกคืนสถานะผ่าน $state.go
UI-เราเตอร์
stateChange สิ่งนี้เรียกว่าเมื่อคุณย้ายสถานะภายใน ชื่อและพารามิเตอร์ของสถานะปัจจุบันจะถูกเก็บไว้ในStateHistoryService
คีย์โดย url ที่สร้างขึ้น URL ที่สร้างขึ้นนี้อาจเป็นอะไรก็ได้ที่คุณต้องการโดยอาจระบุหรือไม่ระบุสถานะด้วยวิธีที่มนุษย์อ่านได้ ในกรณีของฉันฉันใช้พารามิเตอร์สถานะบวกกับลำดับของตัวเลขที่สร้างขึ้นแบบสุ่มซึ่งได้มาจาก guid (ดูส่วนท้ายสำหรับข้อมูลโค้ดตัวสร้างคำแนะนำ) URL @location.url url
ที่สร้างขึ้นจะปรากฏในแถบเบราว์เซอร์และขับเคลื่อนเพิ่มไปยังกองประวัติศาสตร์ภายในเบราว์เซอร์ที่ใช้ เพิ่ม url ไปยังกองประวัติของเบราว์เซอร์ที่เปิดใช้งานปุ่มไปข้างหน้า / ย้อนกลับ
ปัญหาใหญ่ของเทคนิคนี้คือการเรียก@location.url url
ใช้stateChange
เมธอดจะทำให้เกิด$locationChangeSuccess
เหตุการณ์และเรียกใช้locationChange
เมธอด การเรียก@state.go
จากอย่างเท่าเทียมกันlocationChange
จะทริกเกอร์$stateChangeSuccess
เหตุการณ์และstateChange
วิธีการ สิ่งนี้ทำให้เกิดความสับสนและทำให้ประวัติเบราว์เซอร์ยุ่งเหยิงไม่สิ้นสุด
วิธีแก้ปัญหานั้นง่ายมาก คุณสามารถเห็นpreventCall
อาร์เรย์ที่ใช้เป็นสแต็ก ( pop
และpush
) ทุกครั้งที่มีการเรียกวิธีการใดวิธีการหนึ่งจะป้องกันไม่ให้วิธีการอื่นเรียกว่าครั้งเดียวเท่านั้น เทคนิคนี้ไม่รบกวนการทริกเกอร์เหตุการณ์ $ ที่ถูกต้องและทำให้ทุกอย่างตรง
ตอนนี้สิ่งที่เราต้องทำคือเรียกใช้HistoryService
วิธีการในช่วงเวลาที่เหมาะสมในวงจรชีวิตการเปลี่ยนสถานะ สิ่งนี้ทำได้ในวิธี AngularJS Apps .run
ดังนี้:
แอปเชิงมุมเรียกใช้
angular
.module 'app', ['ui.router']
.run ($rootScope, stateLocationService) ->
$rootScope.$on '$stateChangeSuccess', (event, toState, toParams) ->
stateLocationService.stateChange()
$rootScope.$on '$locationChangeSuccess', ->
stateLocationService.locationChange()
สร้าง Guid
Math.guid = ->
s4 = -> Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1)
"#{s4()}#{s4()}-#{s4()}-#{s4()}-#{s4()}-#{s4()}#{s4()}#{s4()}"
เมื่อใช้งานทั้งหมดนี้ปุ่มเดินหน้า / ถอยหลังและปุ่มรีเฟรชก็ทำงานได้ตามที่คาดไว้