Video.jsビデオプレーヤーである再利用可能なコンポーネントがあります。このコンポーネントは、データが初期DOMロードで渡されるときに正常に機能します。
Vuexで状態が更新された後、コンポーネントが再レンダリングされない理由を把握する必要があります。
親コンポーネントは、小道具を介してビデオのデータを渡します。また、このセットを複数のビデオで使用し、1つまたは複数のビデオで正常に動作します。
_<div v-for="video in videos" :key="video.id">
<video-player :videoName="video.videoName" :videoURL="video.videoURL" :thumbnail="video.thumbnail"></video-player>
</div>
_
Vuexストアのすべてのユーザーに対して、初期状態を汎用ビデオに設定しています。
_getFreeVideo: [
{
videoName: "the_video_name",
videoURL: "https://demo-video-url.mp4",
thumbnail: "https://s3.amazonaws.com/../demo-video-poster.jpg"
}
]
_
これはvideos
のデータに設定されます(および後でgetFreeVideoに設定)
_ data () {
return {
videos: []
}
}
_
Created()ライフサイクル内のストアで、data()のvideos
をgetFreeVideoに設定しています。
_ this.videos = this.getFreeVideo
_
..そして、ユーザーが個人的なビデオを持っているかどうかを確認し、created()ライフサイクルで状態を更新します。
_ this.$store.dispatch('getFreeVideo', 'the_video_name')
_
これにより、axiosでリクエストが行われ、ビデオデータが正常に返されます。
MapState _import { mapState } from 'vuex
_を使用して、状態の変化を監視しています。
_ computed: {
...mapState(['getFreeVideo'])
}
_
_this.videos
_が更新されない理由がわかりません。ここで、予想される動作に関する私の仮定は、状態の変更とコンポーネントの再レンダリングから更新される_videos[]
_です。
以下に示すように、状態が更新されており、計算されたプロパティ内のvideoUpdate()
にも新しいデータがあります。
..しかし、_videos[]
_は更新されないため、ビデオコンポーネントは小道具や新しい小道具などを取得できません。
いくつかのメモ:
v-if
_で子コンポーネントを非表示にしようとしています(および状態変更後に表示)setTimeout
を試してみましたが、データは通過し、videoJSプレーヤーは正しくインスタンス化されません(初期データが必要です)TypeError: Cannot read property '_withTask' of undefined
_が表示されますが、これはデモビデオが正しく読み込まれた場合でも発生するため、これは無関係と思われ、未定義として表示されるものはここにありません。TL; DR
基本的に、状態の変更後に子コンポーネントを再レンダリングすることはできません。そして、異なる構造で_videos[]
_にデータを取得できますが、それでも再レンダリングされません。
データが処理されず、再レンダリングが行われないのはなぜですか?
「反応性を理解する」または説明のないものへのリンクのみを含む回答を投稿しないでください。 ????
@ acdcjuniorに追加
_//action
getFreeVideo: (context, videoName) => {
axios({
method: 'post',
url: 'https://hidden-for-posting',
data: {
action: 'getVideo',
userId: '1777', // (hardcoded to test)
videoName: videoName
},
headers: {
'x-api-key': apiKey,
'Content-Type': 'application/json'
}
})
.then(response => {
let video = [
{
videoName: response.data.videoName,
videoURL: response.data.videoURLs.mp4,
thumbnail: response.data.thumbnails['1280']
}
]
return context.commit('updateGetFreeVideo', video)
})
.catch(error => {
if (error.response) {
console.log(error.response)
} else if (error.request) {
console.log(error.request)
} else {
console.log('Error', error.message)
}
console.log(error.config)
})
}
// mutation:
updateGetFreeVideo: (state, payload) => {
return state.getFreeVideo = payload
}
// getter:
getFreeVideo: state => {
return state.getFreeVideo
}
_
テンプレートを考慮して、投稿したコードに基づいて:
<div v-for="video in videos" :key="video.id">
以下からvideos
を選択します。
data () {
return {
videos: freeVideo
}
}
freeVideo
から初期化されますが、コードのどこにもvideos
の更新と表示されません。
解決策:
計算されたgetFreeVideo
にすでに状態がマップされています:
computed: {
...mapState(['getFreeVideo'])
}
これを使って:
<div v-for="video in getFreeVideo" :key="video.id">
Created()ライフサイクル内のストアで、data()の
videos
をgetFreeVideoに設定しています。this.videos = this.getFreeVideo
これは、this.videos
が何であれthis.getFreeVideo
を更新し続けるには不十分です。何かがthis.getFreeVideo
に設定されるたびに、this.getFreeVideo
ではなくthis.videos
のみが変更されます。
this.videos
が変更されるたびにthis.getFreeVideo
を自動的に更新する場合は、ウォッチャーを作成します。
watch: {
getFreeVideo() {
this.videos = this.getFreeVideo
}
}
v-for
でvideos
を使用し続けます:
<div v-for="video in videos" :key="video.id">
したがって、問題はすべてvideo.jsにあったことがわかりました。私はこの質問を削除したいと思いますが、助けてくれた人にポイントを失いたくありません。
ここでの解決策と入力は、ウォッチャーの使用またはこれをどのように試みたかを再考するのに役立ちました。中央ストアは正常に機能するため、今のところは中央ストアのみを使用しましたが、これは後でリファクタリングする必要があります。
今のところ、video.jsをプレーヤーとして使用するのをやめなければならず、通常のhtml5ビデオプレーヤーは問題なく動作します。
計算されたプロパティがテンプレートコードのどこかで参照されていない場合(「使用済み」など)vueは、それに対する反応性をスキップします。
まず、ストアと状態のプロパティを構造化する方法を少し混乱させます。
私は...するだろう:
1)ストア状態に「videos」プロパティがある
2)空の配列として初期化する
3)アプリケーションの起動時に、「デフォルト」ビデオをプッシュする突然変異を加えて、「ロード」デフォルトを正しく設定します
4)mapGetter
という名前でコンポーネントにvideos
を持っている
5)可能なビデオを「更新」するコンポーネントをロードするたびに、アクションをディスパッチし、適切なミューテーションを呼び出してストアの「ビデオ」プロパティを置き換えます
注:コンポーネントに異なる「デフォルト」ビデオを含めることができる場合は、おそらくストアにvideos
として初期化されたfalse
プロパティが必要になります。これにより、ストア内のvideos
プロパティのゲッターを使用する計算されたプロパティを持つことができ、それがfalse
の場合
つまり、最初の場合
// store
state: {
videos: []
}
getters: {
videos(state) { return state.videos }
}
//components
...
computed: {
videos() {
this.$store.getters.videos
}
}
For the second case
// store
state: {
videos: false
}
getters: { personal_videos(state) { return state.videos } }
//components
data() { return { default: default_videos } },
computed: {
...mapGetters([ 'personal_videos' ]),
videos() {
if (this.personal_videos) {
return this.personal_videos
} else {
return this.default
}
}
}
個人:より良い名前を付けます-_-そして最初のオプションが最も明確です