Ionic 4剧集追踪应用:复选框状态管理与SQLite存储问题
修复剧集复选框状态异常并实现SQLite存储加载功能
我来帮你搞定这两个问题——复选框选中/取消时的数组异常,以及SQLite持久化存储已看状态的功能,咱们一步步来:
一、先修复复选框selected数组清空的问题
你的代码里有两个核心问题导致了取消选中时数组被清空:
1. 循环边界错误
checkAll函数里的循环条件用了i <= this.seasonepisodes.length,但数组索引是从0到length-1的,这个条件会让循环跑到不存在的数组下标,不仅可能报错,还会漏标/误标剧集。
2. 过滤条件不匹配
selectEpisode里用el.testID !== data.testID做过滤,但从TMDB获取的剧集对象根本没有testID属性,应该用剧集自带的id字段来匹配。当取消选中时,这个错误的条件会把所有元素都过滤掉,导致selected数组直接清空。
修复后的TS代码:
seasonepisodes: any[] = []; selected: any[] = []; // 假设你已经有获取seasondetails的逻辑,保留并优化 this.seasonepisodes = this.seasondetails?.episodes || []; checkAll() { // 修正循环边界为 < length for(let i = 0; i < this.seasonepisodes.length; i++) { const episode = this.seasonepisodes[i]; episode.checked = true; // 防止重复添加到selected数组 if (!this.selected.some(item => item.id === episode.id)) { this.selected.push(episode); } } console.log(this.seasonepisodes); } selectEpisode(data) { if (data.checked) { // 避免重复添加 if (!this.selected.some(item => item.id === data.id)) { this.selected.push(data); } } else { // 用正确的id字段过滤数组 this.selected = this.selected.filter(el => el.id !== data.id); } console.log(this.selected); // 后面会在这里加SQLite存储逻辑 }
HTML部分可以保留原样,不过建议给episodes.checked做个初始化(比如在获取到剧集数组后,给每个元素默认加checked: false),避免ngModel报警告。
二、实现SQLite存储与加载已看状态
接下来咱们把复选框状态持久化到本地SQLite数据库,确保用户重启APP后状态不会丢失。
1. 先安装依赖
在项目根目录执行:
ionic cordova plugin add cordova-sqlite-storage npm install @ionic-native/sqlite
2. 页面TS里的完整实现
首先导入SQLite并注入到组件:
import { SQLite, SQLiteObject } from '@ionic-native/sqlite/ngx'; constructor(private sqlite: SQLite) {} private db: SQLiteObject; // 假设你有当前节目ID和季数的变量(需要从页面跳转参数或接口获取) showId: number; seasonNumber: number; // 初始化数据库 async initDB() { this.db = await this.sqlite.create({ name: 'tv_tracker.db', location: 'default' }); // 创建已看剧集表,用节目ID+季数+剧集ID做唯一键,避免重复存储 await this.db.executeSql(` CREATE TABLE IF NOT EXISTS watched_episodes ( id INTEGER PRIMARY KEY AUTOINCREMENT, episode_id INTEGER, show_id INTEGER, season_number INTEGER, UNIQUE(episode_id, show_id, season_number) ) `, []); } // 页面进入时加载已看状态 async ionViewWillEnter() { await this.initDB(); // 查询当前季的已看剧集ID const res = await this.db.executeSql(` SELECT episode_id FROM watched_episodes WHERE show_id = ? AND season_number = ? `, [this.showId, this.seasonNumber]); const watchedIds = []; for (let i = 0; i < res.rows.length; i++) { watchedIds.push(res.rows.item(i).episode_id); } // 更新复选框状态和selected数组 this.seasonepisodes.forEach(episode => { episode.checked = watchedIds.includes(episode.id); if (episode.checked && !this.selected.some(item => item.id === episode.id)) { this.selected.push(episode); } }); } // 修改selectEpisode,加入存储逻辑 async selectEpisode(data) { if (data.checked) { if (!this.selected.some(item => item.id === data.id)) { this.selected.push(data); } // 插入到数据库(用INSERT OR IGNORE避免重复) await this.db.executeSql(` INSERT OR IGNORE INTO watched_episodes (episode_id, show_id, season_number) VALUES (?, ?, ?) `, [data.id, this.showId, this.seasonNumber]); } else { this.selected = this.selected.filter(el => el.id !== data.id); // 从数据库删除对应记录 await this.db.executeSql(` DELETE FROM watched_episodes WHERE episode_id = ? AND show_id = ? AND season_number = ? `, [data.id, this.showId, this.seasonNumber]); } console.log(this.selected); }
关键注意点
showId和seasonNumber需要你从页面的跳转参数或者接口返回数据中获取,用来唯一标识当前的节目和季,避免不同节目/季的剧集ID冲突。- 每次获取到
seasonepisodes后,记得给每个剧集对象初始化checked: false,避免ngModel绑定出错。
内容的提问来源于stack exchange,提问作者Gor
相关产品推荐
相关产品推荐

