微信小程序入门学习教程,从入门到精通,电影之家小程序项目知识点详解 (17)

电影之家小程序项目知识点详解


一、项目创建与基础结构

知识点1:创建微信小程序项目

语法说明

  • 使用微信开发者工具创建项目
  • app.json 是全局配置文件
  • project.config.json 是项目配置文件

案例代码:app.json

json 复制代码
{
  "pages": [
    "pages/index/index",        // 首页
    "pages/movieList/movieList", // 电影列表页
    "pages/movieDetail/movieDetail", // 电影详情页
    "pages/reviewList/reviewList", // 影评列表页
    "pages/reviewDetail/reviewDetail" // 影评详情页
  ],
  "window": {
    "backgroundTextStyle": "light",
    "navigationBarBackgroundColor": "#000",
    "navigationBarTitleText": "电影之家",
    "navigationBarTextStyle": "white"
  },
  "style": "v2",
  "sitemapLocation": "sitemap.json"
}

说明

  • pages 数组定义所有页面路径,第一项为首页
  • window 配置全局窗口表现
  • style: "v2" 表示启用新版组件样式

二、安装与使用组件库(以 Vant WeUI 为例)

知识点2:引入第三方 UI 组件库

步骤

  1. 下载 Vant WeUI 小程序版
  2. dist 文件夹复制到项目 miniprogram_npm/@vant/weapp/
  3. 在页面 JSON 中引入组件

案例代码:movieList.json

json 复制代码
{
  "usingComponents": {
    "van-search": "@vant/weapp/search/index",
    "van-loading": "@vant/weapp/loading/index",
    "van-card": "@vant/weapp/card/index"
  }
}

对应 WXML 使用示例(movieList.wxml)

xml 复制代码
<van-search
  value="{{ keyword }}"
  placeholder="请输入电影名称"
  bind:change="onSearchChange"
  bind:search="onSearch"
/>

<view wx:if="{{ loading }}" class="loading">
  <van-loading size="24px">加载中...</van-loading>
</view>

<van-card
  wx:for="{{ movieList }}"
  wx:key="id"
  title="{{ item.title }}"
  desc="{{ item.year }} · {{ item.director }}"
  thumb="{{ item.poster }}"
  bind:click="goToDetail"
  data-id="{{ item.id }}"
/>

说明

  • usingComponents 声明自定义组件
  • wx:for 循环渲染列表
  • data-id 用于传递参数到事件处理函数

三、页面开发核心知识点

知识点3:页面生命周期与数据绑定

语法说明

  • Page() 构造器定义页面逻辑
  • data 存储页面数据
  • onLoad 页面加载时触发

案例代码:index.js(首页)

javascript 复制代码
Page({
  data: {
    bannerList: [],       // 轮播图数据
    recommendMovies: [],  // 推荐电影
    loading: true         // 加载状态
  },

  // 页面加载时调用
  onLoad() {
    this.fetchBanner();
    this.fetchRecommendMovies();
  },

  // 获取轮播图
  async fetchBanner() {
    try {
      const res = await wx.request({
        url: 'https://api.example.com/banner',
        method: 'GET'
      });
      this.setData({
        bannerList: res.data
      });
    } catch (err) {
      console.error('获取轮播图失败', err);
    }
  },

  // 获取推荐电影
  async fetchRecommendMovies() {
    try {
      const res = await wx.request({
        url: 'https://api.example.com/recommend',
        method: 'GET'
      });
      this.setData({
        recommendMovies: res.data,
        loading: false
      });
    } catch (err) {
      this.setData({ loading: false });
      wx.showToast({ title: '加载失败', icon: 'none' });
    }
  },

  // 跳转到电影详情
  goToDetail(e) {
    const movieId = e.currentTarget.dataset.id;
    wx.navigateTo({
      url: `/pages/movieDetail/movieDetail?id=${movieId}`
    });
  }
});

说明

  • setData() 是唯一更新视图的方式
  • 使用 async/await 处理异步请求
  • wx.navigateTo 实现页面跳转并传参

知识点4:WXML 条件渲染与列表渲染

案例代码:index.wxml

xml 复制代码
<!-- 轮播图 -->
<swiper
  indicator-dots="true"
  autoplay="true"
  interval="3000"
  duration="500"
  class="banner-swiper"
>
  <block wx:for="{{ bannerList }}" wx:key="id">
    <swiper-item>
      <image src="{{ item.imageUrl }}" mode="aspectFill" class="banner-img" />
    </swiper-item>
  </block>
</swiper>

<!-- 推荐电影区域 -->
<view class="section-title">为你推荐</view>
<view class="movie-grid">
  <view
    wx:for="{{ recommendMovies }}"
    wx:key="id"
    class="movie-item"
    bindtap="goToDetail"
    data-id="{{ item.id }}"
  >
    <image src="{{ item.poster }}" class="poster" mode="aspectFill" />
    <text class="title">{{ item.title }}</text>
    <text class="rating">评分:{{ item.rating }}</text>
  </view>
</view>

<!-- 加载状态 -->
<view wx:if="{{ loading }}" class="loading">加载中...</view>
<view wx:elif="{{ recommendMovies.length === 0 && !loading }}" class="empty">暂无推荐</view>

说明

  • wx:if / wx:elif / wx:else 条件渲染
  • block 用于包裹多个元素而不产生额外节点
  • bindtap 绑定点击事件

知识点5:页面间传参与接收

案例:movieDetail.js 接收参数

javascript 复制代码
Page({
  data: {
    movie: null,
    reviews: []
  },

  onLoad(options) {
    const { id } = options; // 从 URL 获取参数
    if (id) {
      this.loadMovieDetail(id);
      this.loadReviews(id);
    }
  },

  async loadMovieDetail(movieId) {
    const res = await wx.request({
      url: `https://api.example.com/movie/${movieId}`
    });
    this.setData({ movie: res.data });
  },

  async loadReviews(movieId) {
    const res = await wx.request({
      url: `https://api.example.com/reviews?movieId=${movieId}`
    });
    this.setData({ reviews: res.data });
  },

  // 跳转到影评详情
  goToReviewDetail(e) {
    const reviewId = e.currentTarget.dataset.reviewId;
    wx.navigateTo({
      url: `/pages/reviewDetail/reviewDetail?id=${reviewId}`
    });
  }
});

说明

  • onLoad(options)options 包含 URL 参数
  • 使用模板字符串拼接 API 地址

四、影评模块开发

知识点6:表单提交与用户交互

案例:发布影评(简化版)

reviewList.wxml

xml 复制代码
<view class="post-review">
  <textarea
    placeholder="写下你的影评..."
    bindinput="onInput"
    value="{{ content }}"
  />
  <button type="primary" bindtap="submitReview" disabled="{{ !content.trim() }}">发布</button>
</view>

reviewList.js

javascript 复制代码
Page({
  data: {
    content: '',
    movieId: ''
  },

  onLoad(options) {
    this.setData({ movieId: options.movieId });
  },

  onInput(e) {
    this.setData({ content: e.detail.value });
  },

  async submitReview() {
    if (!this.data.content.trim()) {
      wx.showToast({ title: '内容不能为空', icon: 'none' });
      return;
    }

    try {
      await wx.request({
        url: 'https://api.example.com/reviews',
        method: 'POST',
        data: {
          movieId: this.data.movieId,
          content: this.data.content,
          userId: wx.getStorageSync('userId') // 假设有用户登录
        }
      });
      wx.showToast({ title: '发布成功' });
      this.setData({ content: '' });
      // 重新加载影评列表
      this.triggerEvent('refresh'); // 或调用父页面方法
    } catch (err) {
      wx.showToast({ title: '发布失败', icon: 'none' });
    }
  }
});

说明

  • bindinput 实时获取输入内容
  • disabled 控制按钮状态
  • 使用 wx.getStorageSync 获取本地存储数据

五、综合性案例:完整电影详情页

综合案例:movieDetail 页面(含电影信息 + 影评列表 + 发布功能)

movieDetail.json

json 复制代码
{
  "usingComponents": {
    "van-rate": "@vant/weapp/rate/index",
    "van-button": "@vant/weapp/button/index"
  }
}

movieDetail.wxml

xml 复制代码
<view class="container" wx:if="{{ movie }}">
  <!-- 电影海报与信息 -->
  <view class="movie-header">
    <image src="{{ movie.poster }}" class="poster" />
    <view class="info">
      <text class="title">{{ movie.title }}</text>
      <text class="year">{{ movie.year }}</text>
      <view class="rating">
        <van-rate value="{{ movie.rating / 2 }}" readonly size="20" />
        <text class="score">{{ movie.rating }}</text>
      </view>
      <text class="director">导演:{{ movie.director }}</text>
      <text class="cast">主演:{{ movie.cast.join(' / ') }}</text>
    </view>
  </view>

  <!-- 剧情简介 -->
  <view class="section">
    <text class="section-title">剧情简介</text>
    <text class="summary">{{ movie.summary }}</text>
  </view>

  <!-- 影评列表 -->
  <view class="section">
    <text class="section-title">用户影评 ({{ reviews.length }})</text>
    <view wx:for="{{ reviews }}" wx:key="id" class="review-item">
      <text class="review-content">{{ item.content }}</text>
      <text class="review-time">{{ item.createTime }}</text>
    </view>
  </view>

  <!-- 跳转到完整影评列表 -->
  <van-button
    type="default"
    size="small"
    bindtap="goToReviewList"
    data-movie-id="{{ movie.id }}"
  >
    查看全部影评
  </van-button>
</view>

<view wx:else class="loading">加载中...</view>

movieDetail.js(部分)

javascript 复制代码
Page({
  data: {
    movie: null,
    reviews: []
  },

  onLoad(options) {
    const { id } = options;
    this.loadMovieAndReviews(id);
  },

  async loadMovieAndReviews(id) {
    wx.showLoading({ title: '加载中' });
    try {
      // 并行请求
      const [movieRes, reviewRes] = await Promise.all([
        wx.request({ url: `https://api.example.com/movie/${id}` }),
        wx.request({ url: `https://api.example.com/reviews?movieId=${id}&limit=3` })
      ]);
      this.setData({
        movie: movieRes.data,
        reviews: reviewRes.data
      });
    } catch (err) {
      wx.showToast({ title: '加载失败', icon: 'none' });
    } finally {
      wx.hideLoading();
    }
  },

  goToReviewList(e) {
    const movieId = e.currentTarget.dataset.movieId;
    wx.navigateTo({
      url: `/pages/reviewList/reviewList?movieId=${movieId}`
    });
  }
});

综合知识点

  • 并行请求优化加载速度(Promise.all
  • 使用 Vant 组件库的评分组件
  • 动态绑定数据与事件
  • 页面加载状态管理

六、项目测试与发布

知识点7:小程序测试与上传

测试方法

  • 使用开发者工具的"真机调试"
  • 模拟不同网络环境(弱网、断网)
  • 使用 wx.setStorageSync 模拟登录状态

上传发布命令(通过开发者工具 GUI 操作)

  1. 点击"上传"按钮
  2. 填写版本号与项目备注
  3. 登录微信公众平台审核发布

测试示例:mock 数据(开发阶段)

javascript 复制代码
// utils/mock.js
export const mockMovie = {
  id: '1001',
  title: '肖申克的救赎',
  year: '1994',
  rating: 9.7,
  director: '弗兰克·德拉邦特',
  cast: ['蒂姆·罗宾斯', '摩根·弗里曼'],
  poster: 'https://example.com/poster1.jpg',
  summary: '银行家安迪被冤入狱,用智慧与希望重获自由...'
};

// 在页面中使用
onLoad() {
  if (__DEV__) { // 开发环境使用 mock
    this.setData({ movie: mockMovie });
  } else {
    // 真实请求
  }
}

总结

本项目覆盖了微信小程序开发的核心知识点:

模块 关键技术
项目结构 app.json 配置、页面注册
UI 组件 Vant WeUI 引入与使用
数据请求 wx.request、async/await
页面通信 URL 传参、事件传参
用户交互 表单处理、按钮状态控制
渲染逻辑 wx:for、wx:if、数据绑定
发布流程 上传、审核、发布

通过以上案例,可构建一个功能完整、交互流畅的"电影之家"小程序。

相关推荐
訾博ZiBo4 小时前
React组件复用导致的闪烁问题及通用解决方案
前端
Dever4 小时前
记一次 CORS 深水坑:开启 withCredentials 后Response headers 只剩 content-type
前端·javascript
临江仙4554 小时前
流式 Markdown 渲染在 AI 应用中的应用探秘:从原理到优雅实现
前端·vue.js
风和先行4 小时前
Android Vibrator学习记录
学习
Hilaku4 小时前
为什么我开始减少逛技术社区,而是去读非技术的书?
前端·javascript·面试
m0_728033134 小时前
JavaWeb——(web.xml)中的(url-pattern)
xml·前端
猪哥帅过吴彦祖4 小时前
第 8 篇:更广阔的世界 - 加载 3D 模型
前端·javascript·webgl
七月十二4 小时前
[Js]使用highlight.js高亮vue代码
前端
Asort4 小时前
JavaScript设计模式(十二)——代理模式 (Proxy)
前端·javascript·设计模式