Cách đặt tham số truy vấn URL trong Vue với Vue-Router


114

Tôi đang cố gắng thiết lập các tham số truy vấn với Vue-router khi thay đổi các trường đầu vào, tôi không muốn điều hướng đến một số trang khác mà chỉ muốn sửa đổi các tham số truy vấn url trên cùng một trang, tôi đang làm như sau:

this.$router.replace({ query: { q1: "q1" } })

Nhưng điều này cũng làm mới trang và đặt vị trí y thành 0, tức là cuộn lên đầu trang. Đây có phải là cách chính xác để đặt các tham số truy vấn URL hay có cách nào tốt hơn để làm điều đó.


Đã chỉnh sửa:

Đây là mã bộ định tuyến của tôi:

export default new Router({
  mode: 'history',
  scrollBehavior: (to, from, savedPosition)  => {
    if (to.hash) {
      return {selector: to.hash}
    } else {
      return {x: 0, y: 0}
    }
  },
  routes: [
    ....... 
    { path: '/user/:id', component: UserView },
  ]
})

Câu trả lời:


132

Đây là ví dụ trong tài liệu:

// with query, resulting in /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})

Tham khảo: https://router.vuejs.org/en/essentials/navigation.html

Như đã đề cập trong các tài liệu đó, router.replacehoạt động nhưrouter.push

Vì vậy, bạn dường như có nó ngay trong mã mẫu của bạn được đề cập. Nhưng tôi nghĩ rằng bạn có thể cần phải bao gồm cả namehoặc paththam số, để bộ định tuyến có một số tuyến đường để điều hướng đến. Không có namehoặc path, nó trông không có ý nghĩa cho lắm.

Đây là hiểu biết hiện tại của tôi bây giờ:

  • query là tùy chọn cho bộ định tuyến - một số thông tin bổ sung cho thành phần để xây dựng chế độ xem
  • namehoặc pathlà bắt buộc - nó quyết định thành phần nào sẽ hiển thị trong của bạn <router-view>.

Đó có thể là điều còn thiếu trong mã mẫu của bạn.

CHỈNH SỬA: Chi tiết bổ sung sau khi nhận xét

Bạn đã thử sử dụng các tuyến đường được đặt tên trong trường hợp này chưa? Bạn có các tuyến đường động và việc cung cấp các thông số và truy vấn riêng biệt sẽ dễ dàng hơn:

routes: [
    { name: 'user-view', path: '/user/:id', component: UserView },
    // other routes
]

và sau đó trong các phương pháp của bạn:

this.$router.replace({ name: "user-view", params: {id:"123"}, query: {q1: "q1"} })

Về mặt kỹ thuật, không có sự khác biệt giữa các điều trên và this.$router.replace({path: "/user/123", query:{q1: "q1"}}), nhưng việc cung cấp các tham số động trên các tuyến đường được đặt tên sẽ dễ dàng hơn so với việc soạn chuỗi tuyến đường. Nhưng trong cả hai trường hợp, các tham số truy vấn nên được tính đến. Trong cả hai trường hợp, tôi không tìm thấy điều gì sai với cách xử lý các tham số truy vấn.

Sau khi bạn ở bên trong tuyến, bạn có thể tìm nạp thông số động của mình dưới dạng this.$route.params.idvà thông số truy vấn của bạn dưới dạng this.$route.query.q1.


Tôi cũng đã thử cung cấp đường dẫn, nhưng điều này không ngừng cuộn lên đầu trang, tôi đã chỉnh sửa câu hỏi với các tùy chọn bộ định tuyến, có thể có một số thay đổi cần thiết ở đó.
Saurabh

Tham số truy vấn của bạn có dự định cuộn đến đúng vị trí trong tài liệu không? Giống như câu hỏi khác của bạn về thẻ neo ?
Mani

Không, tôi chỉ muốn thêm tham số truy vấn trong URL, tôi không muốn bất kỳ cuộn nào ở đây.
Saurabh

Tôi vừa thử nghiệm các tùy chọn trong thiết lập cục bộ của mình, các tham số truy vấn hoạt động bình thường. Tôi có thể điều hướng đến tuyến đường mới và truy cập các tham số truy vấn như được hiển thị trong câu trả lời cập nhật của tôi. Vì vậy, vấn đề là - bạn không muốn nó cuộn? Hay vấn đề là toàn bộ ứng dụng được làm mới lại?
Mani

vì vậy tôi đang ở trên cùng một trang, khi tôi chọn một số đầu vào, tôi muốn thêm chúng vào URL, nhưng khi tôi làm điều đó, việc cuộn xảy ra. Cuộn là vấn đề đối với tôi. Tôi không cố gắng điều hướng đến trang khác, tôi chỉ muốn ở trên cùng một trang và thêm / sửa đổi các tham số truy vấn url một cách dễ dàng.
Saurabh

15

Không cần tải lại trang hoặc làm mới dom, history.pushStatecó thể thực hiện công việc.
Thêm phương thức này vào thành phần của bạn hoặc ở nơi khác để thực hiện điều đó:

addParamsToLocation(params) {
  history.pushState(
    {},
    null,
    this.$route.path +
      '?' +
      Object.keys(params)
        .map(key => {
          return (
            encodeURIComponent(key) + '=' + encodeURIComponent(params[key])
          )
        })
        .join('&')
  )
}

Vì vậy, ở bất kỳ đâu trong thành phần của bạn, hãy gọi addParamsToLocation({foo: 'bar'})để đẩy vị trí hiện tại với các tham số truy vấn trong ngăn xếp window.history.

Để thêm các tham số truy vấn vào vị trí hiện tại mà không cần đẩy mục nhập lịch sử mới , hãy sử dụng history.replaceStatethay thế.

Đã thử nghiệm với Vue 2.6.10 và Nuxt 2.8.1.

Hãy cẩn thận với phương pháp này!
Vue Router không biết rằng url đã thay đổi, vì vậy nó không phản ánh url sau pushState.



4
this.$router.push({ query: Object.assign(this.$route.query, { new: 'param' }) })

1
Tôi thích câu trả lời này nhất. Thật không may, nguyên nhân nàyError: Avoided redundant navigation to current location
Max Coplan

Khắc phục:this.$router.push({ query: Object.assign({...this.$route.query}, { new: 'param' }) })
Max Coplan

2
Nhưng bây giờ tôi nghĩ về nó bạn chỉ có thể làmthis.$router.push({ query: {...this.$route.query,new: 'param'},) })
Max Coplan

3

Nếu bạn đang cố gắng giữ một số tham số, trong khi thay đổi các tham số khác, hãy nhớ sao chép trạng thái của truy vấn bộ định tuyến vue và không sử dụng lại nó.

Điều này hoạt động, vì bạn đang tạo một bản sao không tham chiếu:

  const query = Object.assign({}, this.$route.query);
  query.page = page;
  query.limit = rowsPerPage;
  await this.$router.push({ query });

trong khi bên dưới sẽ dẫn đến Vue Router nghĩ rằng bạn đang sử dụng lại cùng một truy vấn và dẫn đến NavigationDuplicatedlỗi:

  const query = this.$route.query;
  query.page = page;
  query.limit = rowsPerPage;
  await this.$router.push({ query });

Tất nhiên, bạn có thể phân tách đối tượng truy vấn, chẳng hạn như sau, nhưng bạn sẽ cần phải biết tất cả các tham số truy vấn cho trang của mình, nếu không, bạn có nguy cơ mất chúng trong điều hướng kết quả.

  const { page, limit, ...otherParams } = this.$route.query;
  await this.$router.push(Object.assign({
    page: page,
    limit: rowsPerPage
  }, otherParams));
);

Lưu ý, trong khi ví dụ trên là cho push(), điều này cũng hoạt động với replace().

Đã kiểm tra với vue-router 3.1.6.


3

Để thêm nhiều tham số truy vấn, đây là điều phù hợp với tôi (từ đây https://forum.vuejs.org/t/vue-router-programmatically-append-to-querystring/3655/5 ).

một câu trả lời ở trên là gần đúng… mặc dù với Object.assign nó sẽ thay đổi điều này. $ route.query không phải là điều bạn muốn làm… hãy đảm bảo đối số đầu tiên là {} khi thực hiện Object.assign

this.$router.push({ query: Object.assign({}, this.$route.query, { newKey: 'newValue' }) });

2

Để thiết lập / xóa nhiều tham số truy vấn cùng một lúc, tôi đã kết thúc với các phương pháp bên dưới như một phần của tổng hợp toàn cục của mình ( thistrỏ đến thành phần vue):

    setQuery(query){
        let obj = Object.assign({}, this.$route.query);

        Object.keys(query).forEach(key => {
            let value = query[key];
            if(value){
                obj[key] = value
            } else {
                delete obj[key]
            }
        })
        this.$router.replace({
            ...this.$router.currentRoute,
            query: obj
        })
    },

    removeQuery(queryNameArray){
        let obj = {}
        queryNameArray.forEach(key => {
            obj[key] = null
        })
        this.setQuery(obj)
    },

1

Tôi thường sử dụng đối tượng lịch sử cho việc này. Nó cũng không tải lại trang.

Thí dụ:

history.pushState({}, '', 
                `/pagepath/path?query=${this.myQueryParam}`);

0

Đây là giải pháp đơn giản của tôi để cập nhật các tham số truy vấn trong URL mà không cần làm mới trang. Đảm bảo rằng nó hoạt động cho trường hợp sử dụng của bạn.

const query = { ...this.$route.query, someParam: 'some-value' };
this.$router.replace({ query });
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.