Web开发学习笔记:Ionic4与SQLite数据库交互

Ionic Storage 深度解析:SQLite与IndexedDB跨平台持久化原理 在混合应用开发中,客户端数据持久化是离线能力的核心基础。SQLite作为嵌入式数据库代表,提供ACID事务与本地文件级可靠性;IndexedDB则是Web标准下的键值型存储方案,依赖浏览器实现。二者在Ionic框架中通过Storage抽象层统一接入,但实际行为受平台、WebView版本、权限模型深度影响。理解其驱动加载优先级、错误归一化机制、物理路径策略及WAL日志行为,是保障购物车、历史记录、人事档案等关键数据不丢失的前提。本文聚焦Ionic 2+中@ionic/storage的真实工作链路,结合adb调 阅读详情

以下代码使用IDE:vscode; 语言模式:TypeScript

1.使用命令创建一个service

ionic g service DBManager

创建成功后目录中会有两个文件

2.在app.module.ts中添加对DBManagerService类的引用同时在providers中添加DBManagerService类

 

3.在DBManagerService类中编写对应的代码

3.1 在constructor中使用win.openDatabase方法连接或创建数据库

this.dataBase = this.win.openDatabase('bookkeeping.db', '1.0', 'bookkeepingDB', 5 * 1024 * 1024);

其中dataBase与win均为定义的类中全局变量

public dataBase: any;
private win: any = window;

注:

第一次使用win.openDatabase时如果数据库不存在会自动创建,保存的路径个浏览器不同使用QQ浏览器的话位置应该为:C:\Users\Administrator\AppData\Local\Tencent\QQBrowser\User Data\Default\databases\http_localhost_8100,我的电脑该路径下有一个24的文件,使用Navicat Premium打开就是创建的数据库

3.2创建数据库中数据表的初始化方法

 // 创建数据库
  CreateDataBase() {
    const createSql = ' CREATE TABLE IF NOT EXISTS money_useinfo( ' +
      ' REC_CREATEOR TEXT ' +
      ',REC_CREATE_TIME TEXT ' +
      ',REC_MODIFIER TEXT' +
      ',REC_MODIFY_TIME TEXT' +
      ',SEQ_NO INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL DEFAULT 0 ' +
      ',MONEY_USE_TIME TEXT' +
      ',MONEY_UST_TYPE TEXT' +
      ',AMOUNT INTEGER' +
      ',MONEY_USE_DESC TEXT' +
      ',BACK1 TEXT' +
      ',BACK2 TEXT' +
      ',BACK3 TEXT' +
      ',BACK4 TEXT' +
      ',BACK5 TEXT' +
      ',BACK6 TEXT' +
      ',BACK7 TEXT' +
      ',BACK8 TEXT' +
      ',BACK9 TEXT' +
      ',BACK10 TEXT' +
      ')';
    this.dataBase.transaction((tx) => {
      // 建表
      tx.executeSql(createSql);
    }, (error) => {// 失败回调
      console.log('Transaction ERROR: ' + error.message);
    }, () => {// 成功回调
      console.log('数据库创建成功');
    });
    // this.sqlitePorter.importSqlToDb(this.dataBase, createSql);
    // console.log('创建表');
    // this.sqlite.create({
    //   name: 'bookkeeping.db',
    //   location: 'default'
    // }).then((db: SQLiteObject) => {
    //   const createSql = 'CREATE TABLE Artist ([Id] PRIMARY KEY, [Title]);';
    //   db.executeSql(createSql).then(res => console.log('Imported')).catch(e => console.error(e));
    //   // this.sqlitePorter.importSqlToDb(db, createSql)
    //   //   .then(() => console.log('Imported'))
    //   //   .catch(e => console.error(e));
    //   console.log('数据库创建成功');
    // });
  }

 

3.3创建查询方法(中间使用了Promise(是一個表示非同步運算的最終完成或失敗的物件))

/**
   * 数据表数据查询
   * @param tableName 类型:string 查询数据的数据表名称
   * @param sqlParam 类型:Array<any> 拼接SQLWHERE条件语句需要的参数信息
   * @param selectCol 类型:string 查询结果列(可选参数,参数如果不传值则默认为 * )
   */
  SelectData(tableName: string, sqlParam: Array<any>, selectCol?: string): Promise<any> {
    let promise = new Promise((resolve, reject) => {
      this.dataBase.transaction((tx) => {
        let selectSql = ' SELECT ';
        let sqlWhere = ' WHERE 1=1 ';
        sqlParam.forEach(item => {
          if (isNumber(item.colValue)) { // 判断值是否为数值类型
            sqlWhere += ' AND ' + item.colName + '=' + item.colValue;
          } else if (isString(item.colValue)) { // 判断值是否为字符类型
            sqlWhere += ' AND ' + item.colName + '=\'' + item.colValue + '\'';
          }
        });
        // console.log('selectCol参数值: ' + selectCol);
        if (selectCol === undefined) {
          selectCol = '*';
        }
        selectSql += selectCol + ' FROM ' + tableName + sqlWhere;
        // console.log('查询SQL: ' + selectSql);
        // 执行SQL并返回结果
        tx.executeSql(selectSql, [], (tx, result) => {// 成功回调
          // this.QueryData = TableStructureInfo.MerageFrom(result, tableName); // 将查询结果转为数组
          resolve({tx: tx, res: result });
        }, (error) => {// 失败回调
          reject({tx: tx, err: error});
          console.log('数据库操作失败: ' + error.message);
        });
      });
    });
    return promise;
  }

查询方法调用

// 调用查询方法
      this.dbManagerService.SelectData('money_useinfo', this.globalVariable.sqlParamInfo)
      .then((success) => {
        this.QueryData = success.res.rows; // 将结果中的数据赋值给QueryData对象,在前端可以直接使用ngfor访问QueryData
        console.log('当前查询返回结果:', this.QueryData);
        // return this.QueryData;
      }, (error) => {
        console.log(error);
      });

查询结果的使用:

<ion-list id='dataShow'>
    <ion-item color="primary" *ngFor="let item of QueryData"> 
    <ion-label> {{item.MONEY_USE_TIME}} </ion-label>  
    <ion-label> {{item.MONEY_UST_TYPE}} </ion-label>  
    <ion-label> {{item.AMOUNT}} </ion-label>  
    <ion-label> {{item.MONEY_USE_DESC}} </ion-label>  
  </ion-item>
  </ion-list>

注:

Promise相关连接:

https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Guide/Using_promises

https://www.cnblogs.com/brookshi/p/6422353.html

3.4创建数据新增方法

  /**
   * 数据表新增数据
   * @param tableName 类型:string 新增数据的数据表名称
   * @param sqlParam 类型:Array<any> 拼接SQL语句需要的参数信息
   */
  InsertData(tableName: string, sqlParam: Array<any>) {
    this.dataBase.transaction((tx) => {
      let insertSql = ' INSERT INTO ' + tableName;
      let sqlCols = '';
      let sqlColsValue = '';
      sqlParam.forEach(item => {
        if (sqlCols !== '') {
          sqlCols += ',' + item.colName;
        } else {
          sqlCols += item.colName;
        }
        if (sqlColsValue !== '') {
          if (isNumber(item.colValue)) { // 判断值是否为数值类型
            sqlColsValue += ',' + item.colValue;
          } else if (isString(item.colValue)) { // 判断值是否为字符类型
            sqlColsValue += ',\'' + item.colValue + '\'';
          }
        } else {
          if (isNumber(item.colValue)) { // 判断值是否为数值类型
            sqlColsValue += item.colValue;
          } else if (isString(item.colValue)) { // 判断值是否为字符类型
            sqlColsValue += '\'' + item.colValue + '\'';
          }
        }
      });

      insertSql += ' (' + sqlCols + ') ' + 'values(' + sqlColsValue + ')';
      console.log('新增SQL: ' + insertSql);
      tx.executeSql(insertSql);
    }, (error) => {// 失败回调
      console.log('数据库操作失败: ' + error.message);
    }, () => {// 成功回调
      console.log('新增成功');
    });
  }

新增方法调用

this.dbManagerService.InsertData('money_useinfo', this.globalVariable.sqlParamInfo);

以上查询、新增方法只适合使用ionic serve 命令 在浏览器上启动的服务

以下修改、删除方法适用于真机测试/浏览器调试

3.5创建修改方法

/**
   * 数据删除
   * @param tableName  删除数据的数据表名称
   * @param sqlPrimaryDateParam 主键数据,元素格式[{colName: colName,colValue: colValue}]
   * @param sqlUpdateDataParam  修改数据,元素格式[{colName: colName,colValue: colValue}]
   */
  UpdateData(tableName: string, sqlPrimaryDateParam: Array<any>, sqlUpdateDataParam: Array<any>): number {
    // tslint:disable-next-line: prefer-const
    let resultFlag = 0;
    // tslint:disable-next-line: prefer-const
    let updSql = ' UPDATE ' + tableName + ' SET ';
    // tslint:disable-next-line: variable-name
    let updSql_where = ' WHERE 1=1 ';
    // tslint:disable-next-line: variable-name
    let updSql_set = ' ';
    let count = 0;

    // console.log('修改数据信息:', sqlUpdateDataParam);
    // 拼接SET语句
    sqlUpdateDataParam.forEach(colInfo => {
      // console.log('当前信息:', colInfo);
      if (count === 0 && count === sqlUpdateDataParam.length - 1 ) {
        if (isString(colInfo.colValue)) {
          updSql_set = colInfo.colName + '=\'' + colInfo.colValue + '\'';
        } else if (isNumber(colInfo.colValue)) {
          updSql_set = colInfo.colName + '=' + colInfo.colValue;
        }
      } else if (count < sqlUpdateDataParam.length - 1 )  {
        if (isString(colInfo.colValue)) {
          updSql_set += colInfo.colName + '=\'' + colInfo.colValue + '\',';
        } else if (isNumber(colInfo.colValue)) {
          updSql_set += colInfo.colName + '=' + colInfo.colValue + ',';
        }
      } else if (count !== 0 && count === sqlUpdateDataParam.length - 1) {
        if (isString(colInfo.colValue)) {
          updSql_set += colInfo.colName + '=\'' + colInfo.colValue + '\'';
        } else if (isNumber(colInfo.colValue)) {
          updSql_set += colInfo.colName + '=' + colInfo.colValue;
        }
      }
      count++;
    });

    // 拼接WHERE条件语句
    sqlPrimaryDateParam.forEach(colInfo => {
      if (isString(colInfo.colValue)) {
        updSql_where += ' AND ' +  colInfo.colName + '=\'' + colInfo.colValue + '\'';
      } else if (isNumber(colInfo.colValue)) {
        updSql_where += ' AND ' +  colInfo.colName + '=' + colInfo.colValue ;
      }
    });
    updSql += updSql_set + updSql_where;
    // console.log('修改SQL:', updSql);
    if (this.win.sqlitePlugin) {
      // this.sqlitePorter.importSqlToDb(this.dataBase, insertSql);
      this.sqlite.create({
        name: 'bookkeeping.db',
        location: 'default'
      }).then((db: SQLiteObject) => {
        this.sqlitePorter.importSqlToDb(db, updSql);
        const toast = this.toastController.create({
          message: '修改成功',
          duration: 3000, // 3秒后自动消失
          position: 'middle', // 位置
          showCloseButton: true,
          closeButtonText: '关闭'
        });
        toast.then((ok) => {
          ok.present(); //  符合触发条件后立即执行显示
        });
      }, (err) => {
        console.log('修改失败:', err);
        const toast = this.toastController.create({
          message: '修改失败!',
          duration: 3000, // 3秒后自动消失
          position: 'middle', // 位置
          showCloseButton: true,
          closeButtonText: '关闭'
        });
        toast.then((ok) => {
          ok.present();
        });
        resultFlag = -1;
      });
    } else {
      this.dataBase.transaction((tx) => {
        tx.executeSql(updSql);
      }, (error) => {// 失败回调
        console.log('修改失败:', error);
        const toast = this.toastController.create({
          message: '修改失败',
          duration: 3000, // 3秒后自动消失
          position: 'middle', // 位置
          showCloseButton: true,
          closeButtonText: '关闭'
        });
        toast.then((ok) => {
          ok.present();
        });
        resultFlag = -1;
      }, () => {// 成功回调
        const toast = this.toastController.create({
          message: '修改成功',
          duration: 3000, // 3秒后自动消失
          position: 'middle', // 位置
          showCloseButton: true,
          closeButtonText: '关闭'
        });
        toast.then((ok) => {
          ok.present();
        });
      });
    }
    return resultFlag;
  }

修改方法调用

SubmitData(data: any) {
    try {
      // 修改数据信息
      const AccountDate = new Date(data.AccountDate);
      data.AccountDate = AccountDate.toLocaleDateString();
      this.globalVariable.sqlParamInfo = []; // 重置
      this.globalVariable.sqlParamInfo.push({ colName: 'MONEY_USE_TIME', colValue: data.AccountDate });
      this.globalVariable.sqlParamInfo.push({ colName: 'MONEY_UST_TYPE', colValue: data.UseType });
      this.globalVariable.sqlParamInfo.push({ colName: 'AMOUNT', colValue: data.Amount });
      this.globalVariable.sqlParamInfo.push({ colName: 'MONEY_USE_DESC', colValue: data.Remark });


      // 修改数据WHERE条件信息
      this.sqlPrimaryDateParam.push({ colName: 'SEQ_NO', colValue: this.newData.SEQ_NO });
      // console.log('当前按钮点击类型:', this.operationType);
        this.globalVariable.sqlParamInfo.push({ colName: 'REC_MODIFIER', colValue: 'PaladinXu' });
        this.globalVariable.sqlParamInfo.push({ colName: 'REC_MODIFY_TIME', colValue: new Date().toLocaleString() });
        const resultFlag = this.dbManagerService.UpdateData('money_useinfo', this.sqlPrimaryDateParam, this.globalVariable.sqlParamInfo);
    } catch (error) {
      console.log('错误信息:', error);
    }
  }

 

3.6创建删除方法

  /**
   * 数据删除
   * @param tableName  删除数据的数据表名称
   * @param sqlPrimaryParam 删除数据的主键
   * @param sqlDataParam  对应主键的数据
   */
  DeleteData(tableName: string, sqlPrimaryParam: Array<string>, sqlDataParam: Array<any>): number {
    let resultFlag = 0;
    let delSql = ' DELETE FROM ' + tableName;
    // tslint:disable-next-line: variable-name
    let delSql_where = ' WHERE 1=1 ';
    // tslint:disable-next-line: variable-name
    let condition_in = ' IN (';
    // tslint:disable-next-line: variable-name
    let condition_in_data = ' ';
    if (sqlPrimaryParam.length > 0) {
      sqlPrimaryParam.forEach(item => {
        // console.log('当前主键:', item);
        if (sqlDataParam.length === 1) {
          // console.log('当前主键对应值:', sqlDataParam[0][item]);
          if (isString(sqlDataParam[0][item])) {
            delSql_where += ' AND ' + item + '=\'' + sqlDataParam[0][item] + '\'';
          } else if (isNumber(sqlDataParam[0][item])) {
            delSql_where += ' AND ' + item + '=' + sqlDataParam[0][item] + '';
          } else if (isArray(sqlDataParam[0][item])) {
            let index = 0;
            if (sqlDataParam[0][item].length > 0) {
              sqlDataParam[0][item].forEach(element => {
                if (index < sqlDataParam[0][item].length - 1) {
                  if (isString(element)) {
                    condition_in_data += ' \' ' + element + '\',';
                  } else if (isNumber(element)) {
                    condition_in_data += element + ',';
                  }
                } else {
                  if (isString(element)) {
                    condition_in_data += ' \' ' + element + '\'';
                  } else if (isNumber(element)) {
                    condition_in_data += element + ')';
                  }
                }
                index++;
              });
              condition_in = ' AND ' + item + condition_in + condition_in_data;
            }
            if (condition_in_data !== '') {
              delSql += delSql_where + condition_in;
            } else {
              delSql += delSql_where;
            }
          }
        } else {
          const toast = this.toastController.create({
            message: '删除条件对应值为空或个数过多,不允许删除',
            duration: 3000, // 3秒后自动消失
            position: 'middle', // 位置
            showCloseButton: true,
            closeButtonText: '关闭'
          });
          toast.then((ok) => {
            ok.present(); //  符合触发条件后立即执行显示
          });
          resultFlag = -1;
          return resultFlag;
        }
      });
    }
    console.log('删除SQL:', delSql);
    if (this.win.sqlitePlugin) {
      // this.sqlitePorter.importSqlToDb(this.dataBase, insertSql);
      this.sqlite.create({
        name: 'bookkeeping.db',
        location: 'default'
      }).then((db: SQLiteObject) => {
        this.sqlitePorter.importSqlToDb(db, delSql);
        const toast = this.toastController.create({
          message: '删除成功',
          duration: 3000, // 3秒后自动消失
          position: 'middle', // 位置
          showCloseButton: true,
          closeButtonText: '关闭'
        });
        toast.then((ok) => {
          ok.present(); //  符合触发条件后立即执行显示
        });
      }, (err) => {
        const toast = this.toastController.create({
          message: err,
          duration: 3000, // 3秒后自动消失
          position: 'middle', // 位置
          showCloseButton: true,
          closeButtonText: '关闭'
        });
        toast.then((ok) => {
          ok.present();
        });
        resultFlag = -1;
      });
    } else {
      this.dataBase.transaction((tx) => {
        tx.executeSql(delSql);
      }, (error) => {// 失败回调
        const toast = this.toastController.create({
          message: error,
          duration: 3000, // 3秒后自动消失
          position: 'middle', // 位置
          showCloseButton: true,
          closeButtonText: '关闭'
        });
        toast.then((ok) => {
          ok.present();
        });
        resultFlag = -1;
      }, () => {// 成功回调
        const toast = this.toastController.create({
          message: '删除成功',
          duration: 3000, // 3秒后自动消失
          position: 'middle', // 位置
          showCloseButton: true,
          closeButtonText: '关闭'
        });
        toast.then((ok) => {
          ok.present();
        });
      });
    }
    return resultFlag;
  }

调用删除方法

// 提交按钮点击form触发ngSubmit
  deleteData(data: string) {
    if (this.SEQ_NO_CHECKBOX.length > 0) {
      this.globalVariable.sqlParamInfo = []; // 重置
      this.globalVariable.sqlParamInfo.push({ SEQ_NO: this.SEQ_NO_CHECKBOX });
      // console.log('主键信息:', this.globalVariable.sqlParamInfo);

      const resultFlag = this.dbManagerService.DeleteData('money_useinfo', ['SEQ_NO'], this.globalVariable.sqlParamInfo);
      if (resultFlag === 0) {
        this.cancelBtnClick();
        this.selectData(this.SELECT_CONDITIONS);
      }
    } else {
      const toast = this.toastController.create({
        message: '请选择要删除的记录!',
        duration: 3000, // 3秒后自动消失
        position: 'middle', // 位置
        showCloseButton: true,
        closeButtonText: '关闭'
      });
      toast.then((ok) => {
        ok.present(); //  符合触发条件后立即执行显示
      });
    }
  }

以上代码可能有很多冗余或者是写的麻烦了,只是与大家用于交流学习,大家可能有更好的思路或者方法可以留言交流

Ionic与Capacitor实战进阶:从核心技能到原生桥接深度解析 跨平台移动应用开发的核心在于如何高效、稳定地整合Web技术与原生设备能力。Ionic框架结合Capacitor运行时,为开发者提供了一套基于Web标准构建高性能混合应用的解决方案。其技术价值在于,通过统一的代码库,能够同时覆盖iOS和Android平台,显著提升开发效率并降低维护成本。在实际工程实践中,开发者需要深入理解Capacitor的原生桥接机制,掌握权限管理、后台任务、安全存储等关键技能,以应对复杂的应用场景。例如,在处理相机集成时,需精细化控制图像质量与权限请求;在实现后台数据同步时,需设计轻量且 阅读详情

相关推荐

Ionic 2 启动页轮播实战:Storage 持久化与 NavController 栈控制

启动页轮播(Intro Slider)是移动应用首次启动时的关键引导组件,其本质并非简单 UI 动画,而是基于用户状态驱动的流程控制器。它依赖可靠的本地持久化机制(如 SQLite/IndexedDB)记录‘是否已展示’状态,并需深度结合导航栈管理(如 setRoot/popToRoot)确保页面跳转原子性与历史清理彻底性。在 Ionic 2 中,@ionic/storage 提供跨平台存储抽象,规避 localStorage 在 iOS WKWebView 或 Android 定制 ROM 中的数据丢失风

weixin_34009794的博客 416

Web开发学习笔记:Ionic4使用SQLite数据库,将查询结果动态转为数组

以下代码使用vsCode+TypeScript编写 1.定义数据查询方法 /** * 数据表数据查询 * @param tableName 类型:string 查询数据的数据表名称 * @param sqlParam 类型:Array<any> 拼接SQLWHERE条件语句需要的参数信息 * @param selectCol 类型:string 查询结果...

JustWantToFly的博客 644

SQLite数据库的添加(Create),查询(Retrieve),更新(Updata),删除(Delete)

一、步骤 添加数据: 1.获取SQLiteDatabase对象,SQLiteDatabase提供insert()方法进行添加,这个方法接收三个参数。 2.创建ContentValues对象;向ContentValues中添加数据。 3.向SQLiteDatabase传入三个参数:表名,null,ContentValues对象。 更新数据: 1.获取SQLiteDatabas

打工仔的博客 1638

Ionic3学习笔记(六)存储之使用 SQLite

本文为原创文章,转载请标明出处 目录 安装 CURD操作 1. 安装 命令行输入 ionic cordova plugin add cordova-sqlite-storage npm install --save @ionic-native/sqlite 在 ./src/app/app.module.ts 中添加 import {SQLite} from "@ionic-nativ...

201

Ionic实战四:中集成Sqlite数据存储记录

文章目录1.插件集成2.项目中引入3.页面引入4.数据库初始化5.增删改查方法6.方法引用7.模拟器中数据展示 1.插件集成 ionic cordova plugin add cordova-sqlite-storage npm install --save @ionic-native/sqlite 2.项目中引入 在app.module.ts中加入 import { SQLite, SQLiteObject } from ‘@ionic-native/sqlite’; 在providers中加入 SQLi

博主逸尘 655

使用SQLite实例深入理解PouchDB

PouchDB是一个开源的JavaScript数据库,它是专门为现代Web应用程序设计的,尤其是那些需要在离线时运行的应用程序。PouchDB在浏览器中运行,并且可以与远程服务器同步,这使得它非常适合移动应用。它的设计允许在设备上本地存储数据,并且能够在有互联网连接时将数据同步到远程数据库,如CouchDB。集成PouchDB到移动应用中,需要考虑的方面包括如何选择合适的插件、如何配置环境、以及如何优化性能以提供良好的用户体验。

weixin_33670640的博客 907

在ionic上使用sqlite

在看一篇文章,《Use SQLite Instead of Local Storage In Ionic Framework》,觉得挺好,因为之后开发可能需要用到,所以顺便翻译一下,记录下来以后使用。 首先创建我们的ionic项目: ionic start IonicProject blank cd IonicProject ionic platform add and

u012379815的博客 7375

ionic使用sqlite存储数据

ionic1使用sqlite存储数据,保存、删除、修改、查询等操作

ionic4项目中常用模块(http、translate、echart)

ionic4项目中常用模块(http、translate、echart) 默认cordova插件不需要多说,一般在创建ionic4项目的时候就会安装好,一般在config.xml中的底部会看到,如下: <plugin name="cordova-plugin-whitelist" spec="1.3.3" /> <plugin name="cordova-plugin-statu...

分享技术,传播知识! 1397

保姆级教程:用Arduino+MPU6050自制寻北仪(附MEMS陀螺精度测试报告)

本文提供了一份详细的Arduino与MPU6050自制寻北仪的保姆级教程,包括硬件选型、卡尔曼滤波算法优化、地磁场补偿及真北计算等关键技术。通过实测数据展示了MEMS陀螺仪在民用领域的高精度性能,帮助读者低成本实现1°以内的寻北精度。

weixin_42522964的博客 363

anaconda安装-超详细版

文章目录一、anaconda安装1.1 anaconda安装地址1.2 安装详细步骤检验安装是否成功更改conda源(后续安装第三方库可以加快速度) 一、anaconda安装 Anaconda 是一个用于科学计算的 Python 发行版,支持 Linux, Mac, Windows, 包含了众多流行的科学计算、数据分析的 Python 包。装anaconda,就不需要单独装python了。 anaconda优点: 1、anaconda里面集成了很多关于python科学计算的第三方库,主要是安装方便,而p

in546的博客 25万+

Ionic5+Angular9+Cordova混合开发

记录下自己的学习路线,仅供参考 环境搭建 有很多大佬介绍了如何安装环境,可以看这里 ionic5+angular8混合移动开发(一)——环境搭建 基于ionic4、cordova搭建android开发环境 ionic+angular+cordova 安卓环境搭建 理解 ionic 、 angular 和cordova之间的关系 理解Ionic、Angular、Cordova及插件之间的关系 Ang...

Downsiren的博客 1351

通义千问语言模型Qwen2.5架构详解

此外,将基于API的模型 Qwen-Plus 与领先的专有和开源模型进行了对比,包括 GPT4-o、Claude-3.5-Sonnet、Llama-3.1-405B和DeepSeek-V2.5。Qwen2.5-Math-72B-Instruct的整体性能超越了Qwen2-Math-72B-Instruct和GPT4-o,甚至是非常小的专业模型如 Qwen2.5-Math-1.5B-Instruct也能在与大型语言模型的竞争中取得高度竞争力的表现。近来也出现了明显的转向小型语言模型(SLMs)的趋势。

搏博的专栏 1万+

ionic---数据本地存储sqlite

ionic混合app本地数据持久化,sqlite的实现

leason的博客 1349

利用腾讯云轻量服务器快速搭建网站CDN

腾讯云的轻量最近在主机和站长中间可谓是占尽来风头,优秀的线路,低廉的价格使得越来越多的人开始使用腾讯云的轻量级服务器来部署应用。由于腾讯云轻量服务器的海外服务器电信走的是CN2GIA线路带宽30m挺适合做CDN的,我就记录一下如何利用腾讯云香港的轻量服务器搭建一个CDN。 购买服务器 首先选购服务器,最近腾讯云在做活动,力度很大国内备案用户可以选用国内的服务器最低128元/年,未备案的可以选用香港或者新加坡的服务器。 购买链接 服务器系统选Debian、Ubuntu、centos都可以 一键脚

demo_top的博客 2562

【开源数据集】电动车佩戴头盔检测数据集(TWHD)

佩戴头盔检测数据集VOC格式图像与标注数量各5448张

hzg19930513的博客 5163

Web开发笔记:Ionic实现表格展示数据

1.accountgrid.page.html <ion-content style="overflow: scroll;" (ionScroll)="ionScroll()" scroll-events='true' id='Content'> <!-- 查询条件 --> <div id="CONTENT_TOP" style="width: 100%; border: tomato 1px solid;"> <form (

JustWantToFly的博客 1057

Python 实战:全面解析“微信搜一搜”内容爬取,从入门到企业级架构

本文将带你从零搭建爬虫项目,采用 Requests、Scrapy、Selenium、Proxy 池、中间人监控(如 Fiddler/mitmproxy)、分布式调度、数据库持久化、断点续抓等方案,实现可持续、抗封能力强的内容抓取系统。理解“微信搜一搜”页面结构与 Javascript 渲染逻辑;使用 Scrapy 框架搭建分布式爬虫;使用 Selenium 模拟浏览器抓取;构建代理池提升爬取成功率;对抗验证码、IP 封禁与 cookie 过期问题;

2201_76125261的博客 1392

ionic 开发小问题集锦

1. ionic默认的很多配置在android和ios系统都是不一样的,因此开发的时候一定要注意,对ionic的配置进行更改,在app.js中利用$ionicConfigProvider 修改 ①tabs的位置,android默认在顶端,ios默认在底端 ②tabs的类型,android默认是striped(条纹状),ios 默认是standard    想将android中的默认样式都修改

Laura Hong的博客 760

指纹浏览器 WebGPU:新一代图形指纹的检测趋势与提前防御

指纹浏览器与风控系统对抗已升级至硬件层面。传统基于WebGL的API拦截和像素噪声技术,在WebGPU时代因架构变革而失效。WebGPU通过Compute Shader直接测量GPU物理算力,暴露了软件模拟的致命缺陷。防御需转向真实GPU硬件直通和虚拟化技术,如vGPU分割算力并伪装特征,以应对风控系统对硬件拓扑和浮点精度的检测。唯有基于物理算力的拟态,才能抵御新一代图形指纹的降维打击。

数据知道的博客 214

高空抛物监控系统:基于YOLOv8的轨迹追踪与可视化系统

本文详细介绍了一种基于YOLOv8深度学习模型的高空抛物监控系统,该系统能够实时检测并追踪高层建筑抛掷物的运动轨迹。文章包含完整的系统设计思路、算法实现细节、数据集构建方法以及基于PyQt5的可视化界面开发过程。我们提供了完整的Python实现代码,并讨论了系统的性能优化策略和实际部署考量。此外,我们还推荐了几个公开可用的高空抛物数据集,并详细分析了系统的应用前景和技术挑战。

YOLO 446

Ionic3学习笔记(七)Storage

本文为原创文章,转载请标明出处 目录 简介 安装 配置 使用 1. 简介 Storage可以很容易的存储键值对和JSON对象。Storage在底层使用多种存储引擎,根据运行平台选择最佳的存储方式。 当运行在Native模式时,Storage将优先使用SQLite。 当运行在Web中或作为PWA应用时,Storage将根据你确定的优先级使用IndexedDB、WebSQL或locals...

181

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Ionic Starter Template 项目推荐

Ionic Starter Template 项目推荐 1. 项目基础介绍和主要编程语言 Ionic Starter Template 是一个基于 Ionic Framework 的开源项目模板,主要用于快速构建混合移动应用。该项目使用 JavaScript 作为主要的编程语言,结合 HTML 和 CSS 进行前端开发。Ionic Framework 是一个流行的开源框架,允许开发者使用 Web ...

gitblog_00348的博客 723

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Ionic2的数据存储

当在一个原生app词法环境下,一般优先使用SQLite,因为它是使用最广泛的稳定的文档型数据库之一,它也避免了一些诸如localstorage和IndexedDB的一些困境,比如系统在磁盘空间不够的时候会清除数据。如果你是在web中或者web app中运行的话,一般倾向于使用IndexedDB,WebSQL,以及localstorage.假如你使用的是SQLite,首先你得安装 cordova-sq

张伟array[0]的博客 5360

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

ionic 中使用pouchdb + sqlite安装

ionic 中使用pouchdb + sqlite安装

m464466721的博客 293
上一篇: Web开发学习笔记:Ionic4使用SQLite数据库,将查询结果动态转为数组
下一篇: Web开发学习笔记:Ionic4中根据滚动条滚动的距离设置返回顶部按钮显示与隐藏
JustWantToFly
博客等级 码龄10年 42粉丝 81原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值