2016-09-26 20 views
7

Tôi có thiết lập thành phần cha/con nơi cha mẹ đang tải dữ liệu từ máy chủ và truyền dữ liệu đó cho trẻ em qua đạo cụ. Trong đứa trẻ, tôi muốn tạo một lịch jQuery với một số dữ liệu mà nó nhận được từ cha mẹ.Đạo cụ thành phần trẻ em VueJ không cập nhật tức thì

Để chờ dữ liệu trước khi thiết lập lịch, tôi phát sự kiện trong phụ huynh mà tôi có thiết lập trình nghe sự kiện cho trẻ.

Trình nghe đang được kích hoạt ở trẻ nhưng nếu tôi this.$log('theProp'), nó không được xác định. Tuy nhiên, nếu tôi kiểm tra các thành phần với các devtools VueJs, mối quan hệ cha/con là có và đứa trẻ đã nhận được prop trong khi chờ đợi.

Giá đỡ được xác định trên trẻ em làm trụ đỡ động :the-prop="theProp". Kể từ khi đứa trẻ không nhận được prop cuối cùng, tôi giả định thiết lập của tôi là chính xác nhưng có vẻ là một số loại chậm trễ. Cha mẹ đặt các đạo cụ trong chức năng trả về của cuộc gọi ajax và một lần nữa: nó hoạt động, chỉ với một chút chậm trễ có vẻ như nó.

Tôi cũng đã thử đăng ký một người nghe watch trên ghế đỡ ở trẻ để tôi có thể thiết lập lịch sau đó và đảm bảo rằng giá đỡ ở đó. Tuy nhiên, người nghe đồng hồ sẽ kích hoạt, nhưng this.$log('theProp') vẫn chưa được xác định.

Nếu tôi chuyển dữ liệu cùng với cuộc gọi phát, chẳng hạn như this.$broadcast('dataLoaded', theData) đứa trẻ sẽ nhận được nó. Nhưng có vẻ như sai khi làm theo cách đó vì tôi cơ bản xây dựng bộ xử lý chống đỡ của riêng mình.

Tôi không đăng bất kỳ mã nào bởi vì các thành phần khá lớn và các devtools của VueJs cho tôi biết tình trạng của cha/con đang hoạt động.

Tôi có thiếu một số thông tin không? Có một chút chậm trễ giữa việc thiết lập một giá trị trong phụ huynh và đứa trẻ nhận được nó? Điều gì sẽ là cách thích hợp để chờ đợi dữ liệu cha mẹ ở trẻ?

Thông thường, khi bạn chỉ hiển thị dữ liệu vào mẫu, thời gian không quan trọng quá nhiều do dữ liệu bị ràng buộc với mẫu. Nhưng trong trường hợp này, tôi thực sự cần dữ liệu ở đó để thiết lập lịch hoặc nó sẽ sai.

Cảm ơn.

chỉnh sửa 1: đây là một jsfiddle: https://jsfiddle.net/dr3djo0u/1/ Dường như để xác nhận rằng dữ liệu không có sẵn ngay sau khi phát sóng. Tuy nhiên, người xem không hoạt động, mặc dù tôi gần như có thể thề rằng đôi khi this.$log('someData') trả về undefined khi tôi thiết lập testcase đó.

Nhưng tôi đoán vấn đề của tôi có thể ở một nơi khác, tối nay tôi sẽ có một cái nhìn, không có dự án với tôi ngay bây giờ.

chỉnh sửa 2: đã thực hiện một số thử nghiệm khác. Vấn đề của tôi là a) người nghe sự kiện dường như không nhận dữ liệu ngay lập tức và b) Tôi cũng đang cố gắng bắt đầu lịch trong cuộc gọi lại route.data nếu someData đã ở gần (ví dụ: khi đến từ cha mẹ), nhưng gọi lại tuyến đường đó được gọi là trước khi thành phần đã sẵn sàng, vì vậy nó không hoạt động ở đó.

giải pháp của tôi bây giờ là thế này:

// works when the child route is loaded directly and parent finishes loading someData 
watch: { 
    someData() { 
     this.initCalendar(); 
    } 
}, 

// works when navigating from parent (data already loaded) 
ready() { 
    if (this.someData && this.someData.length) { 
     this.initCalendar() 
    } 
} 
+1

Hi bạn có thể cung cấp một ví dụ mã đơn giản để tái tạo vấn đề? – Nora

+2

Nếu bạn đang 'xem' một biến và giá trị của nó bên trong' đồng hồ' là không xác định, một cái gì đó thực sự là thiết lập nó để không xác định. –

+0

Cảm ơn nhận xét của bạn. Cập nhật câu hỏi của tôi với những gì tôi đã phát hiện ra. – Chris

Trả lời

3

Theo như tôi biết, bạn không cần sự kiện để truyền dữ liệu từ mẹ sang con.

Tất cả bạn cần là, trong thành phần trẻ: props: ['theProp']

Và khi sử dụng các thành phần con trong các phụ huynh: <child :theProp="someData"></child>

Bây giờ, bất cứ nơi nào trong các phụ huynh bạn thay đổi someData, thành phần con sẽ phản ứng phù hợp .

Bạn không cần sự kiện, bạn không cần "xem", bạn không cần "sẵn sàng".


Ví dụ: sau khi một cuộc gọi AJAX, ở của cha mẹ "sẵn sàng", bạn nạp một số dữ liệu:

// at the parent component 

data: function() { 
    return { 
    someData: {} 
    } 
}, 

ready: function() { 
    var vm = this; 
    $.get(url, function(response) { 
    vm.someData = response; 
    }); 
} 

Bây giờ, bạn không cần bất cứ điều gì khác để vượt qua các dữ liệu cho đứa trẻ. Nó đã có trong đứa trẻ là theProp!

Điều bạn thực sự cần làm là, ở trẻ em, cái gì đó mà phản ứng với những thay đổi dữ liệu trên thuộc tính riêng của mình theProp.

Hoặc trong giao diện:

<div v-if="theProp.id > 0"> 
    Loaded! 
</div> 

Hoặc trong mã JavaScript:

// at the child component 

computed: { 
    // using a computed property based on theProp's value 
    awesomeDate: function() { 
    if (!this.theProp || (this.theProp.length === 0)) { 
     return false; 
    } 
    if (!this.initialized) { 
     this.initCalendar(); 
    } 
    return this.theProp.someThing; 
    } 
} 

Cập nhật 1

Bạn cũng có thể, trong các phụ huynh, làm cho con có điều kiện:

<child v-if="dataLoaded" :theProp="someData"></child> 

Chỉ đặt dataLoaded thành true khi dữ liệu có sẵn.

Cập nhật 2

Hoặc có thể vấn đề của bạn có liên quan đến một change detection caveat

Có lẽ bạn đang tạo ra một tài sản mới trong một đối tượng ...

vm.someObject.someProperty = someValue 

... khi bạn nên làm ...

vm.$set('someObject.someProperty', someValue) 

... trong số khác "hãy cẩn thận".

Cập nhật 3

Trong VueJS 2 bạn không bị giới hạn mẫu. Bạn có thể sử dụng render function và mã logic hiển thị phức tạp nhất mà bạn muốn.

Cập nhật 4 (liên quan đến OP của chỉnh sửa 2)

lẽ bạn có thể thả ready và sử dụng immediate lựa chọn, vì vậy khởi tạo của bạn đang ở một nơi duy nhất:

watch: { 
    someData: { 
    handler: function (someData) { 
     // check someData and eventually call 
     this.initCalendar(); 
    }, 
    immediate: true 
    } 
} 
+0

Tôi đang truyền dữ liệu qua các đạo cụ, câu hỏi của tôi liên quan đến việc phản ứng với việc nhận các thay đổi dữ liệu, vì tôi phải bắt đầu mọi thứ tùy thuộc vào nó. Tính chất tính toán không phải là cách để đi cho loại imho đó. – Chris

+0

Tôi đã cập nhật câu trả lời của mình bao gồm các đề xuất khác. Tuy nhiên, imho, tính toán được một phù hợp tốt đẹp cho trường hợp này. Bạn có thể tạo thuộc tính tính 'isReady' hoặc' isLoaded', dựa trên 'someData'. Trong thực tế, nếu bạn cần phản ứng với những thay đổi dữ liệu, một thuộc tính được tính ** là ** cách để đi. –

+0

khi sử dụng mẫu, có. Trong một phương thức, nếu tôi kiểm tra 'if (this.isLoaded)' và nó không được nạp vào lúc đó, tôi bỏ lỡ cơ hội để tạo lịch. Vì vậy, tôi phải xem dữ liệu cho những thay đổi như được mô tả trong bản cập nhật thứ 2 của tôi. Hoạt động tốt. – Chris

Các vấn đề liên quan