ساخت یک سایت سادهی نمایش لیست فیلم با استفاده از Vue.js - قسمت دوم
نویسنده: کامیاری
تاریخ: ۱۳۹۸/۰۳/۱۸ ۱۹:۳۵
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
ng generate component [name] یا ng g c [name]
<template>
<v-app>
<v-toolbar app>
<v-toolbar-title>
<span>Vuetify</span>
<span>MATERIAL DESIGN</span>
</v-toolbar-title>
<v-spacer></v-spacer>
<v-btn
flat
href="https://github.com/vuetifyjs/vuetify/releases/latest"
target="_blank"
>
<span>Latest Release</span>
</v-btn>
</v-toolbar>
<v-content>
<HelloWorld/>
</v-content>
</v-app>
</template>
<script>
export default {
name: 'App',
components: {
},
data () {
return {
//
}
}
}
</script> <template>
<v-container v-if="loading">
<div>
<v-progress-circular
indeterminate
:size="150"
:width="8"
color="green">
</v-progress-circular>
</div>
</v-container>
<v-container v-else grid-list-xl>
<v-layout wrap>
<v-flex xs4
v-for="(item, index) in wholeResponse"
:key="index"
mb-2>
<v-card>
<v-img
:src="item.Poster"
aspect-ratio="1"
></v-img>
<v-card-title primary-title>
<div>
<h2>{{item.Title}}</h2>
<div>Year: {{item.Year}}</div>
<div>Type: {{item.Type}}</div>
<div>IMDB-id: {{item.imdbID}}</div>
</div>
</v-card-title>
<v-card-actions>
<v-btn flat
color="green"
@click="singleMovie(item.imdbID)"
>View</v-btn>
</v-card-actions>
</v-card>
</v-flex>
</v-layout>
</v-container>
</template>
<script>
import movieApi from '@/services/MovieApi'
export default {
data () {
return {
wholeResponse: [],
loading: true
}
},
mounted () {
movieApi.fetchMovieCollection('indiana')
.then(response => {
this.wholeResponse = response.Search
this.loading = false
})
.catch(error => {
console.log(error)
})
},
methods: {
singleMovie (id) {
this.$router.push('/movie/' + id)
}
}
}
</script>
<style scoped>
.v-progress-circular
margin: 1rem
</style> <template>
<v-container v-if="loading">
<div>
<v-progress-circular
indeterminate
:size="150"
:width="8"
color="green">
</v-progress-circular>
</div>
</v-container>
<v-container v-else>
<v-layout wrap>
<v-flex xs12 mr-1 ml-1>
<v-card>
<v-img
:src="singleMovie.Poster"
aspect-ratio="2"
></v-img>
<v-card-title primary-title>
<div>
<h2>{{singleMovie.Title}}-{{singleMovie.Year}}</h2>
<p>{{ singleMovie.Plot}} </p>
<h3>Actors:</h3>{{singleMovie.Actors}}
<h4>Awards:</h4> {{singleMovie.Awards}}
<p>Genre: {{singleMovie.Genre}}</p>
</div>
</v-card-title>
<v-card-actions>
<v-btn flat color="green" @click="back">back</v-btn>
</v-card-actions>
</v-card>
</v-flex>
</v-layout>
<v-layout row wrap>
<v-flex xs12>
<div>
<v-dialog
v-model="dialog"
width="500">
<v-btn
slot="activator"
color="green"
dark>
View Ratings
</v-btn>
<v-card>
<v-card-title
primary-title
>
Ratings
</v-card-title>
<v-card-text>
<table style="width:100%" border="1" >
<tr>
<th>Source</th>
<th>Ratings</th>
</tr>
<tr v-for="(rating,index) in this.ratings" :key="index">
<td align="center">{{ratings[index].Source}}</td>
<td align="center"><v-rating :half-increments="true" :value="ratings[index].Value"></v-rating></td>
</tr>
</table>
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn
color="primary"
flat
@click="dialog = false"
>
OK
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</div>
</v-flex>
</v-layout>
</v-container>
</template>
<script>
import movieApi from '@/services/MovieApi'
export default {
props: ['id'],
data () {
return {
singleMovie: '',
dialog: false,
loading: true,
ratings: ''
}
},
mounted () {
movieApi.fetchSingleMovie(this.id)
.then(response => {
this.singleMovie = response
this.ratings = this.singleMovie.Ratings
this.ratings.forEach(function (element) {
element.Value = parseFloat(element.Value.split(/\/|%/)[0])
element.Value = element.Value <= 10 ? element.Value / 2 : element.Value / 20
}
)
this.loading = false
})
.catch(error => {
console.log(error)
})
},
methods: {
back () {
this.$router.push('/')
}
}
}
</script>
<style scoped>
.v-progress-circular
margin: 1rem
</style> <template>
<v-container v-if="loading">
<div>
<v-progress-circular
indeterminate
:size="150"
:width="8"
color="green">
</v-progress-circular>
</div>
</v-container>
<v-container v-else-if="noData">
<div>
<h2>No Movie in API with {{this.name}}</h2>
</div>
</v-container>
<v-container v-else grid-list-xl>
<v-layout wrap>
<v-flex xs4
v-for="(item, index) in movieResponse"
:key="index"
mb-2>
<v-card>
<v-img
:src="item.Poster"
aspect-ratio="1"
></v-img>
<v-card-title primary-title>
<div>
<h2>{{item.Title}}</h2>
<div>Year: {{item.Year}}</div>
<div>Type: {{item.Type}}</div>
<div>IMDB-id: {{item.imdbID}}</div>
</div>
</v-card-title>
<v-card-actions>
<v-btn flat
color="green"
@click="singleMovie(item.imdbID)"
>View</v-btn>
</v-card-actions>
</v-card>
</v-flex>
</v-layout>
</v-container>
</template>
<script>
// در همه کامپوننتها جهت واکشی اطلاعات ایمپورت میشود
import movieApi from '@/services/MovieApi'
export default {
// route پارامتر مورد استفاده در
props: ['name'],
data () {
return {
// آرایه ای برای دریافت فیلمها
movieResponse: [],
// جهت نمایش لودینگ در زمان بارگذاری اطلاعات
loading: true,
// مشخص کردن آیا اطللاعاتی با سرچ انجام شده پیدا شده یا خیر
noData: false
}
},
// تعریف متدهایی که در برنامه استفاده میکنیم
methods: {
// این تابع باعث میشود که
// route
// تعریف شده با نام
// Movie
// فراخوانی شود و آدرس بار هم تغییر میکنید به آدرسی شبیه زیر
// my-site/movie/tt4715356
singleMovie (id)
this.$router.push('/movie/' + id)
},
fetchResult (value) {
movieApi.fetchMovieCollection(value)
.then(response => {
if (response.Response === 'True') {
this.movieResponse = response.Search
this.loading = false
this.noData = false
} else {
this.noData = true
this.loading = false
}
})
.catch(error => {
console.log(error)
})
}
},
// جز توابع
// life cycle
// vue.js
// میباشد و زمانی که تمپلیت رندر شد اجرا میشود
// همچنین با هر بار تغییر در
// virtual dom
// این تابع اجرا میشود
mounted () {
this.fetchResult(this.name)
},
// watchها // کار ردیابی تغییرات را انجام میدهند و به محض تغییر مقدار پراپرتی
// name
// کد مورد نظر در بلاک زیر انجام میشود
watch: {
name (value) {
this.fetchResult(value)
}
}
}
</script>
<style scoped>
.v-progress-circular
margin: 1rem
</style> import axios from 'axios'
import axios from 'axios'
export default {
fetchMovieCollection (name) {
return axios.get('&s=' + name)
.then(response => {
return response.data
})
},
fetchSingleMovie (id) {
return axios.get('&i=' + id)
.then(response => {
return response.data
})
}
} axios.defaults.baseURL = 'http://www.omdbapi.com/?apikey=b76b385c&page=1&type=movie&Content-Type=application/json'
import Vue from 'vue'
import VueRouter from 'vue-router'
// برای رجیستر کردن کامپوننتها در بخش روتر، آنها را ایمپورت میکنیم
import LatestMovie from '@/components/LatestMovie'
import Movie from '@/components/Movie'
import SearchMovie from '@/components/SearchMovie'
Vue.use(VueRouter)
export default new VueRouter({
routes: [
{
// مسیری هست که برای این کامپوننت در نظر گرفته شده(صفحه اصلی)بدون پارامتر
path: '/',
// نام روت
name: 'LatestMovie',
// نام کامپوننت مورد نظر
component: LatestMovie
},
{
// پارامتری هست که به این کامپوننت ارسال میشه id
// برای دستیابی به این کامپوننت نیاز هست با آدرسی شبیه زیر اقدام کرد
// my-site/movie/tt4715356
path: '/movie/:id',
name: 'Movie',
// در کامپوننت جاری یک پراپرتی وجود دارد
//id که میتوان با نام
// به آن دسترسی پیدا کرد
props: true,
component: Movie
},
{
path: '/search/:name',
name: 'SearchMovie',
props: true,
component: SearchMovie
}
],
// achieve URL navigation without a page reload
// When using history mode, the URL will look "normal," e.g. http://oursite.com/user/id. Beautiful!
// در آدرس # قرار نمیگیرد
mode: 'history'
}) npm install