


Klon Netflix untuk Meningkatkan Kemahiran Bahagian Hadapan Anda
As a developer primarily focused on backend, I've always felt that my frontend skills could use some polishing. To test this, I decided to challenge myself by building a Netflix clone using Vue.js 3 and Vite. In this article, I'll break down the project structure, key components, and share my learning experience.
Project Overview
The goal was to create a responsive web application that mimics the core features of Netflix's user interface. Here's what I initially set out to build:
- A homepage with multiple rows of movies, categorized by genre
- Smooth horizontal scrolling for movie rows
- Lazy loading of images for better performance
- A search functionality to find movies
More to be added in the future.
Tech Stack
For this project, I chose the following tools:
- Vue.js 3: For its reactivity system and component-based architecture
- Vite: As a fast build tool and development server
- Vue Router: For handling navigation
- Pinia: For state management
- Axios: For making API requests to TMDB
- @vueuse/motion: For adding smooth animations
Project Structure
Here's an overview of the project structure:
netflix-clone/ ├── src/ │ ├── components/ │ │ ├── MovieCard.vue │ │ ├── MovieList.vue │ │ ├── MovieRow.vue │ │ └── NavBar.vue │ ├── views/ │ │ ├── HomeView.vue │ │ ├── MovieDetailView.vue │ │ └── SearchView.vue │ ├── router/ │ │ └── index.js │ ├── services/ │ │ └── tmdb.js │ ├── stores/ │ │ └── movies.js │ ├── App.vue │ └── main.js ├── .env.example ├── vite.config.js └── package.json
Key Components Breakdown
MovieCard.vue
This component represents an individual movie. It displays the movie poster and, on hover, shows additional information like the title, rating, and release year.
<template> <div class="movie-card"> <img class="{ lazy" src="/static/imghw/default1.png" data-src="posterUrl" : :alt="Klon Netflix untuk Meningkatkan Kemahiran Bahagian Hadapan Anda" true :loaded imageloaded> <div v-if="isHovered" class="movie-info"> <h3 id="Klon-Netflix-untuk-Meningkatkan-Kemahiran-Bahagian-Hadapan-Anda">{{ Klon Netflix untuk Meningkatkan Kemahiran Bahagian Hadapan Anda }}</h3> <p>Rating: {{ movie.vote_average }}/10</p> <p>{{ releaseYear }}</p> </div> </div> </template> <script setup> import { ref, computed } from 'vue'; const props = defineProps(['movie']); const imageLoaded = ref(false); const isHovered = ref(false); const posterUrl = computed(() => `https://image.tmdb.org/t/p/w500${props.movie.poster_path}`); const releaseYear = computed(() => new Date(props.movie.release_date).getFullYear()); // ... hover logic </script>
Key learnings:
- Using computed properties for derived data
- Implementing hover effects with CSS transitions
- Lazy loading images for better performance
MovieRow.vue
This component creates a horizontally scrollable row of movies, typically grouped by genre.
<template> <div class="movie-row"> <h2 id="title">{{ title }}</h2> <div class="movie-list" ref="movieList"> <moviecard v-for="movie in movies" :key="movie.id" :movie="movie"></moviecard> </div> <button class="scroll-btn left"><</button> <button @click="scroll('right')" class="scroll-btn right">></button> </div> </template> <script setup> import { ref } from 'vue'; import MovieCard from './MovieCard.vue'; const props = defineProps(['title', 'movies']); const movieList = ref(null); const scroll = (direction) => { const scrollAmount = direction === 'left' ? -300 : 300; movieList.value.scrollBy({ left: scrollAmount, behavior: 'smooth' }); }; </script> ### tmdb.js (API Service) This service handles all API calls to The Movie Database (TMDB) using Axios.
import axios from 'axios'; const API_KEY = import.meta.env.VITE_TMDB_API_KEY; const BASE_URL = 'https://api.themoviedb.org/3'; const tmdbApi = axios.create({ baseURL: BASE_URL, params: { api_key: API_KEY }, }); export const getTrending = () => tmdbApi.get('/trending/all/week'); export const getMoviesByGenre = (genreId) => tmdbApi.get('/discover/movie', { params: { with_genres: genreId } }); export const searchMovies = (query) => tmdbApi.get('/search/movie', { params: { query } });
NavBar.vue
The NavBar component provides navigation for the application and includes a search input for finding movies.
<template> <nav class="navbar"> <router-link to="/" class="navbar-brand">NetflixClone</router-link> <div class="navbar-links"> <router-link to="/">Home</router-link> <div class="search-container"> <input v-model="searchQuery" placeholder="Search movies..."> </div> </div> </nav> </template> <script setup> import { ref } from 'vue'; import { useRouter } from 'vue-router'; import debounce from 'lodash/debounce'; const router = useRouter(); const searchQuery = ref(''); const debounceSearch = debounce(() => { if (searchQuery.value) { router.push({ name: 'search', query: { q: searchQuery.value } }); } }, 300); </script>
HomeView.vue
The HomeView component serves as the main page of the application, displaying multiple MovieRow components with different genres.
<template> <div class="home-view"> <movierow title="Trending" :movies="trendingMovies"></movierow> <movierow v-for="genre in genres" :key="genre.id" :title="genre.name" :movies="moviesByGenre[genre.id]"></movierow> </div> </template> <script setup> import { ref, onMounted } from 'vue'; import MovieRow from '@/components/MovieRow.vue'; import { getTrending, getGenres, getMoviesByGenre } from '@/services/tmdb'; const trendingMovies = ref([]); const genres = ref([]); const moviesByGenre = ref({}); onMounted(async () => { const [trendingResponse, genresResponse] = await Promise.all([ getTrending(), getGenres() ]); trendingMovies.value = trendingResponse.data.results; genres.value = genresResponse.data.genres.slice(0, 5); // Limit to 5 genres for this example for (const genre of genres.value) { const response = await getMoviesByGenre(genre.id); moviesByGenre.value[genre.id] = response.data.results; } }); </script>
SearchView.vue
The SearchView component displays search results based on the user's query.
<template> <div class="search-view"> <h2 id="Search-Results-for-searchQuery">Search Results for "{{ searchQuery }}"</h2> <div class="search-results"> <moviecard v-for="movie in searchResults" :key="movie.id" :movie="movie"></moviecard> </div> </div> </template> <script setup> import { ref, watch } from 'vue'; import { useRoute } from 'vue-router'; import MovieCard from '@/components/MovieCard.vue'; import { searchMovies } from '@/services/tmdb'; const route = useRoute(); const searchQuery = ref(''); const searchResults = ref([]); const performSearch = async () => { const response = await searchMovies(searchQuery.value); searchResults.value = response.data.results; }; watch(() => route.query.q, (newQuery) => { searchQuery.value = newQuery; performSearch(); }, { immediate: true }); </script>
You can find the full source code for this project on GitHub.
Atas ialah kandungan terperinci Klon Netflix untuk Meningkatkan Kemahiran Bahagian Hadapan Anda. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas



Artikel membincangkan membuat, menerbitkan, dan mengekalkan perpustakaan JavaScript, memberi tumpuan kepada perancangan, pembangunan, ujian, dokumentasi, dan strategi promosi.

Artikel ini membincangkan strategi untuk mengoptimumkan prestasi JavaScript dalam pelayar, memberi tumpuan kepada mengurangkan masa pelaksanaan dan meminimumkan kesan pada kelajuan beban halaman.

Soalan dan penyelesaian yang sering ditanya untuk percetakan tiket kertas terma depan dalam pembangunan front-end, percetakan tiket adalah keperluan umum. Walau bagaimanapun, banyak pemaju sedang melaksanakan ...

Artikel ini membincangkan debugging JavaScript yang berkesan menggunakan alat pemaju pelayar, memberi tumpuan kepada menetapkan titik putus, menggunakan konsol, dan menganalisis prestasi.

Tidak ada gaji mutlak untuk pemaju Python dan JavaScript, bergantung kepada kemahiran dan keperluan industri. 1. Python boleh dibayar lebih banyak dalam sains data dan pembelajaran mesin. 2. JavaScript mempunyai permintaan yang besar dalam perkembangan depan dan stack penuh, dan gajinya juga cukup besar. 3. Faktor mempengaruhi termasuk pengalaman, lokasi geografi, saiz syarikat dan kemahiran khusus.

Artikel ini menerangkan cara menggunakan peta sumber untuk debug JavaScript minifikasi dengan memetakannya kembali ke kod asal. Ia membincangkan membolehkan peta sumber, menetapkan titik putus, dan menggunakan alat seperti Chrome Devtools dan Webpack.

Bagaimana cara menggabungkan elemen array dengan ID yang sama ke dalam satu objek dalam JavaScript? Semasa memproses data, kita sering menghadapi keperluan untuk mempunyai id yang sama ...

Perbincangan mendalam mengenai punca-punca utama perbezaan dalam output konsol.log. Artikel ini akan menganalisis perbezaan hasil output fungsi Console.log dalam sekeping kod dan menerangkan sebab -sebab di belakangnya. � ...
