IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 微信小程序(云开发基本使用、自定义组件Behavior及computed 、分包加载、基础库低版本兼容 、骨架屏使用 ) -> 正文阅读

[移动开发]微信小程序(云开发基本使用、自定义组件Behavior及computed 、分包加载、基础库低版本兼容 、骨架屏使用 )

二、云开发基本使用(了解)

1.环境初始化

开发前需要在小程序端选择好相应的云环境,一般在小程序的app.js文件中进行处理

onLaunch: function () {
 ?  if (!wx.cloud) {
 ? ?  console.error('请使用 2.2.3 或以上的基础库以使用云能力');
 ?  } else {
 ? ?  wx.cloud.init({
 ? ? ?  // env 参数说明:
 ? ? ?  // ? env 参数决定接下来小程序发起的云开发调用(wx.cloud.xxx)会默认请求到哪个云环境的资源
 ? ? ?  // ? 此处请填入环境 ID, 环境 ID 可打开云控制台查看
 ? ? ?  // ? 如不填则使用默认环境(第一个创建的环境)
 ? ? ?  env: 'dev-lu78h',
 ? ? ?  // env: {
 ? ? ?  // ? database:'dev-lu78h',
 ? ? ?  // ? storage:'pro-'
 ? ? ?  // },
 ? ? ?  traceUser: true,
 ? ?  });
 ?  }
  }

2.数据库

云开发提供了一个 JSON 数据库,顾名思义,数据库中的每条记录都是一个 JSON 格式的对象。一个数据库可以有多个集合(相当于关系型数据中的表),集合可看做一个 JSON 数组,数组中的每个对象就是一条记录,记录的格式是 JSON 对象。

1.初始化  获取操作数据的引用
    const db = wx.cloud.database()
2.添加数据
    2.1新建集合(表) 注意表的权限
     addData(){
 ? ? ?  // callback风格
 ? ? ?  // db.collection('ceshi').add({
 ? ? ?  // ? ? data:{
 ? ? ?  // ? ? ? ? name:'鲁班',
 ? ? ?  // ? ? ? ? age:18
 ? ? ?  // ? ? },
 ? ? ?  // ? ? success:res=>{console.log(res)},
 ? ? ?  // ? ? fail:err=>{console.log(err)}
 ? ? ?  // })
?
 ? ? ?  // promise版本
 ? ? ?  db.collection('ceshi').add({
 ? ? ? ? ?  data:{
 ? ? ? ? ? ? ?  name:'李白',
 ? ? ? ? ? ? ?  age:20
 ? ? ? ? ?  }
 ? ? ?  })
 ? ? ?  .then(res=>{console.log(res)})
 ?  },
 ? ?
3.查询数据
     getAll(){
 ? ? ?  // 小程序端每次只能返回20条记录  在云函数端可以每次返回100条记录
 ? ? ?  db.collection('ceshi')
 ? ? ?  .get()
 ? ? ?  .then(res=>{console.log(res)})
 ?  },
?
 ?  getId(){
 ? ? ?  db.collection('ceshi').doc('fa4fe87261a57bb300f790df346d1e19')
 ? ? ?  .get()
 ? ? ?  .then(res=>{console.log(res)})
?
 ? ? ?  // db.collection('ceshi').where({
 ? ? ?  // ?  _id:'fa4fe87261a57bb300f790df346d1e19'
 ? ? ?  // })
 ? ? ?  // .get()
 ? ? ?  // .then(res=>{console.log(res)})
 ?  },
?
 ?  getWhere(){
 ? ? ?  db.collection('ceshi').where({
 ? ? ? ? ?  name:'鲁班',
 ? ? ? ? ?  age:18
 ? ? ?  })
 ? ? ?  .get()
 ? ? ?  .then(res=>{console.log(res)})
 ?  },

3.云存储

云开发提供了一块存储空间,提供了上传文件到云端、带权限管理的云端下载能力,开发者可以在小程序端和云函数端通过 API 使用云存储功能。

在小程序端可以分别调用 wx.cloud.uploadFilewx.cloud.downloadFile 完成上传和下载云文件操作。

 upload(){
 ? ? ?  // 1.选择本地图片资源
 ? ? ?  wx.chooseImage({
 ? ? ? ? ?  count: 1,
 ? ? ? ? ?  sizeType: ['original', 'compressed'],
 ? ? ? ? ?  sourceType: ['album', 'camera'],
 ? ? ? ? ?  success:res=>{
 ? ? ? ? ? ? ?  // 获取本地文件的临时路径
 ? ? ? ? ? ? ?  const tempFilePaths = res.tempFilePaths[0];
 ? ? ? ? ? ? ?  // 重写图片名字(防止用户之间资源名字冲突导致资源丢失覆盖)
 ? ? ? ? ? ? ?  let suffix = tempFilePaths.split('.').pop();
 ? ? ? ? ? ? ?  let newImg = new Date().getTime()+'.'+suffix;
 ? ? ? ? ? ? ?  // 2.将资源上传至服务端(云存储  七牛云  阿里云:oss)
 ? ? ? ? ? ? ?  wx.cloud.uploadFile({
 ? ? ? ? ? ? ? ? ?  cloudPath: '20211129/'+newImg, // 上传至云端的路径
 ? ? ? ? ? ? ? ? ?  filePath: tempFilePaths, // 小程序临时文件路径
 ? ? ? ? ? ? ? ? ?  success: res => {
 ? ? ? ? ? ? ? ? ? ?  // 返回文件 ID
 ? ? ? ? ? ? ? ? ? ?  console.log(res.fileID)
 ? ? ? ? ? ? ? ? ?  },
 ? ? ? ? ? ? ? ? ?  fail: console.error
 ? ? ? ? ? ? ?  })
 ? ? ? ? ?  }
 ? ? ?  }) 
 ?  },
 ? ?
 ? ?
 ? ?
 ? ? ?  downLoad(){
 ? ? ?  // 1.首先获取云存储中的 图片资源
 ? ? ?  wx.cloud.downloadFile({
 ? ? ? ? ?  fileID: 'cloud://dev-lu78h.6465-dev-lu78h-1300506318/20211129/1638236720100.jpg', // 文件 ID
 ? ? ? ? ?  success: res => {
 ? ? ? ? ? ?  // 返回临时文件路径
 ? ? ? ? ? ?  console.log(res.tempFilePath)
 ? ? ? ? ? ? ?  //2.将图片保存到本地相册
 ? ? ? ? ? ? ?  wx.saveImageToPhotosAlbum({
 ? ? ? ? ? ? ? ? ?  filePath:res.tempFilePath
 ? ? ? ? ? ? ?  }) ? 
 ? ? ? ? ?  },
 ? ? ? ? ?  fail: console.error
 ? ? ?  })
 ?  },

4.云函数

云函数是一段运行在云端的代码,无需管理服务器,在开发工具内编写、一键上传部署即可运行后端代码。

小程序内提供了专门用于云函数调用的 API。开发者可以在云函数内使用 wx-server-sdk 提供的 getWXContext 方法获取到每次调用的上下文(appidopenid 等),无需维护复杂的鉴权机制,即可获取天然可信任的用户登录态(openid)。

1.在项目中指定云函数根目录,然后需要在project.config.json中指定云函数根目录
     "cloudfunctionRoot": "cloudfunctions/",
     
2.右键云函数根目录指定云服务环境,指定后会自动同步当前环境下的所有的云函数
?
3.新建云函数,在云函数根目录上右键选择新建node.js云函数即可,第一次会自动上传,后期如果修改此函数需要手动上传
?
4.编辑云函数内容
    注意:每次修改完本地的云函数后一定上传同步到云端
 ? ? // 云函数入口文件 ?
 ?  // 可以辅助我们在云函数中操作数据库  云存储  云函数
 ?  const cloud = require('wx-server-sdk')
?
 ?  // 云函数初始化
 ?  cloud.init({
 ? ? ?  env:"dev-lu78h"
 ?  })
?
?
 ?  // 云函数入口函数  函数业务逻辑主体
 ?  exports.main = async (event, context) => {
 ? ? ?  // 此处可以根据业务情况开发
 ? ? ?  // 此处云函数中的权限更高(服务端)
 ? ? ? ? ?  // 体现:操作数据库  云存储资源  免鉴权机制 
 ? ? ? ? ?  // 可以免鉴权直接返回用户的openid  小程序的appid
?
 ? ? ?  // event:调用此函数传递的参数 自动注入的用户的openid  小程序的appid
 ? ? ?  // context:描述的是云函数执行的上下文环境
?
 ? ? ?  return {event};
 ?  }
?
5.在小程序端使用云函数
 ?  getYun(){
 ? ? ?  wx.cloud.callFunction({
 ? ? ? ? ?  name:'bj30',
 ? ? ? ? ?  data:{
 ? ? ? ? ? ? ?  name:'李四',
 ? ? ? ? ? ? ?  age:20
 ? ? ? ? ?  }
 ? ? ?  })
 ? ? ?  .then(res=>{console.log(res)})
 ?  },

三、优化-自定义组件的Behavior及computed

1.Behavior组件间代码共享特性

地址:behaviors | 微信开放文档

1.1介绍

behavior是用于组件间代码共享的特性,意思就是定义一部分公共代码特性,每个 behavior 可以包含一组属性、数据、生命周期函数和方法。组件引用它时,它的属性、数据和方法会被合并到组件中,生命周期函数也会在对应时机被调用,方便管理与统一修改. 每个组件可以引用多个 behavior ,behavior 也可以引用其它 behavior

1.2创建

类似于模块创建一样,可以创建专属的behavior目录,用于存放多个behavior。

新建beha/beha.js文件
module.exports = Behavior({
 ?  // 使用beha模块
 ?  behaviors: [],
 ?  // 属性
 ?  properties: {
 ? ? ?  age:{
 ? ? ? ? ?  type:Number,
 ? ? ? ? ?  age:20
 ? ? ?  }
 ?  },
 ?  // 数据
 ?  data: {
 ? ?  name:'李四'
 ?  },
 ?  // 生命周期
 ?  attached: function(){
 ? ? ?  console.log('我是生命周期')
 ?  },
 ?  // 方法
 ?  methods: {
 ? ?  change(){
 ? ? ? ?  this.setData({
 ? ? ? ? ? ?  name:'鲁班',
 ? ? ? ? ? ?  age:100
 ? ? ? ?  })
 ? ?  }
 ?  }
  })

1.3使用

在自定义组件中,可以是require的方式引入,例如:const myBehavior = require("../../behaviors/my-behaviors.js");

注意:

如果有同名的属性 (properties) 或方法 (methods)

(1)若组件本身有这个属性或方法,则组件的属性或方法会覆盖 behavior 中的同名属性或方法

(2)若组件本身无这个属性或方法,则在组件的 behaviors 字段中定义靠后的 behavior 的属性或方法会覆盖靠前的同名属性或方法;

在son组件使用如:
    // 引入beha共享模块
 ?  let beha  = require('../../beha/beha.js');
?
 ?  Component({
 ? ? ?  // 使用beha模块
 ? ? ?  behaviors:[beha],
 ? ? ?  ...............................

1.4内置 behaviors

如使用获取所有表单控件wx://form-field-group wx://form-field-button

新建form组件使用formbeha:
    Component({
 ?      behaviors:['wx://form-field-group','wx://form-field-button'],
 ?      ................
form.wxml:
    姓名:<input type="text" name="username"  />
 ?  性别:
 ? ? ?  <radio-group name='usersex'>
 ? ? ? ? ?  <radio value="0">男</radio>
 ? ? ? ? ?  <radio value="1">女</radio>
 ? ? ?  </radio-group>
 ? ? ?  <button form-type="submit">提交</button> ?    

2.computed计算属性

1.1概述

computed是小程序自定义组件扩展 的behavior模块,通过该模块能够在小程序组件中实现计算属性 computed 和监听器 watch 。当组件中的data 或者 properties 改变时,会重新计算 computed 字段或者是触发 watch 监听器。目前针对的是在组件中的使用。

1.2安装步骤

1. 初始化环境:npm  init  -y
2. 在项目的根目录执行安装npm install --save miniprogram-computed
3. 构建npm即可 微信小程序工具--->菜单栏--->构建npm
4. 点击工具栏详情--->本地设置--->设置npm模块(勾选)
5. 在需要的组件引入const computedBehavior = require('miniprogram-computed').behavior;
?
注意:
    需要小程序基础库版本 >= 2.6.1 的环境。
    computed和watch的实现都是基于miniprogram-computed模块,所以安装一次即可。

1.3computed 基本用法

可以监听属性和数据

注意,不能直接访问this

const computedBehavior = require('miniprogram-computed').behavior;
Component({
 ?  // 使用beha模块
 ?  behaviors:[computedBehavior],
?
 ?  // 使用计算属性 不能操作this
 ?  computed:{
 ? ? ?  sum(data){
 ? ? ? ? ?  console.log('计算属性了')
 ? ? ? ? ?  return data.num1+data.num2
 ? ? ?  }
 ?  },
 ?  /**
 ? ? * 组件的属性列表
 ? ? */
 ?  properties: {
 ? ? ?  num1:{
 ? ? ? ? ?  type:Number,
 ? ? ? ? ?  value:3
 ? ? ?  }
 ?  },
?
 ?  /**
 ? ? * 组件的初始数据
 ? ? */
 ?  data: {
 ? ? ?  num2:2
 ?  },
?
 ?  /**
 ? ? * 组件的方法列表
 ? ? */
 ?  methods: {
?
 ?  }
})
?

1.4watch 基本用法

可以监听属性和数据

const computedBehavior = require('miniprogram-computed').behavior;
Component({
 ?  // 使用beha模块
 ?  behaviors:[computedBehavior],
?
 ?  // 使用监听器 observers  watch:只有修改的新值
 ?  watch:{
 ? ? ?  'num1,num2'(param1,param2){
 ? ? ? ? ?  console.log(param1,param2);
 ? ? ? ? ?  this.setData({sum:this.data.num1+this.data.num2})
 ? ? ?  }
 ?  },
?
 ?  attached(){
 ? ? ?  // 组件加载修改num1 num2
 ? ? ?  this.setData({num1:10,num2:20})
 ?  },
 ?  /**
 ? ? * 组件的属性列表
 ? ? */
 ?  properties: {
 ? ? ?  num1:{
 ? ? ? ? ?  type:Number,
 ? ? ? ? ?  value:3
 ? ? ?  }
 ?  },
?
 ?  /**
 ? ? * 组件的初始数据
 ? ? */
 ?  data: {
 ? ? ?  num2:2,
 ? ? ?  sum:0
 ?  },
?
 ?  /**
 ? ? * 组件的方法列表
 ? ? */
 ?  methods: {
?
 ?  }
})
?

1.5computed vs watch

从原理上说,watch 的性能比 computed 更好;但 computed 的用法更简洁干净。
?
此外,computed 字段状态只能依赖于 data 和其他 computed 字段,不能访问 this 。如果不可避免要访问 this ,则必须使用 watch 代替。

1.6watch vs observers

无论字段是否真的改变, observers 都会被触发,而 watch 只在字段值改变了的时候触发。

第三节

使用计算属性完成购物车封装(练习)

四、优化-分包加载

地址:分包加载 | 微信开放文档

某些情况下,开发者需要将小程序划分成不同的子包,在构建时打包成不同的分包,用户在使用时按需进行加载。每个使用分包小程序必定含有一个主包。所谓的主包,即放置默认启动页面/TabBar 页面,以及一些所有分包都需用到公共资源/JS 脚本;而分包则是根据开发者的配置进行划分。

一般可以按照功能划分:比如:会员模块 购物车模块 订单模块 商品模块

优势

1.能够提高项目首次加载速度;

2.能够解决项目包大小受限2M问题(20M);

3.能够方便团队协作开发;

注意

  • 整个小程序所有分包大小不超过 20M

  • 单个分包/主包大小不能超过 2M

1.配置分包结构

使用语法:

每个分包都可以有自己的公共的静态文件 css js images 还有自己的页面目录(page)

开发者通过在 app.json subpackages 字段声明项目分包结构:

?

直接访问主包页面:

?

访问分包A资源:

?

使用注意:

?

2.独立分包

独立分包是小程序中一种特殊类型的分包,可以独立于主包和其他分包运行。从独立分包中页面进入小程序时,不需要下载主包。当用户进入普通分包或主包内页面时,主包才会被下载。

一个小程序中可以有多个独立分包

使用语法:

开发者通过在app.jsonsubpackages字段中对应的分包配置项中定义independent字段声明对应分包为独立分包。

{
 ? ?  "root": "pageB",
 ? ?  "name": "B",
 ? ?  "pages": [
 ? ? ?  "index/index"
 ? ?  ],
 ? ?  "independent": true
 ?  }

直接访问独立分包:

?

直接访问普通分包

?

使用注意:

独立分包获取不到app实例问题,通过默认实现解决

通过默认实现解决: const app = getApp({allowDefault: true})

注意 在次位置我们虽然 能够通过默认实现获取app实例但是只能通过实例去设置实例中的一些公共的函数或者是全局变量 不能获取使用app实例中的函数和变量

// const  app = getApp();
// console.log(app)//undefined
?
// 通过默认实现解决
const app = getApp({allowDefault: true})
console.log(app)//{ }
?
// 注意 在次位置我们虽然 能够通过默认实现获取app实例但是只能通过实例去设置实例中的一些公共的函数或者是全局变量  不能获取使用app实例中的函数和变量
?
app.name='李四';

3.分包预下载

开发者可以通过配置,在进入小程序某个页面时,由框架自动预下载可能需要的分包,提升进入后续分包页面时的启动速度。对于独立分包,也可以预下载主包。

使用语法

?

五、优化-基础库低版本兼容

在小程序中因为基础库版本的不同会导致项目中组件或者api函数调用失败,从而影响项目正常运行,小程序的功能不断的增加,但是旧版本的微信客户端并不支持新功能,所以在使用这些新能力的时候需要做兼容。

1.版本号比较

获取用户的微信基础库的版本号,再次和我们开发者的版本号进行比对,如果版本号低就提示请更新微信客户端,引导用户更新微信客户端后再次使用我们的小程序产品
?
    /**
 ? ? * 定义比对基础库版本号的方法
 ? ? * params:{
 ? ? *  v1:用户的基础库版本号
 ? ? *  v2:开发者的基础库版本号
 ? ? * }
 ? ? * 
 ? ? * return{
 ? ? * ?  1:ok
 ? ? * ?  0:ok
 ? ? * ? -1:error
 ? ? * }
 ? ? * 
 ? ? * */ 
 ?  const compV=(v1,v2)=>{
 ? ?  // 1.切割成数组
 ? ?  v1 = v1.split('.');
 ? ?  v2 = v2.split('.');
?
 ? ?  // console.log(v1,v2)
?
 ? ?  // 2.循环比对
 ? ?  for(var i=0;i<v1.length;i++){
 ? ? ? ?  // 3.转换成整形
 ? ? ? ?  let num1 = parseInt(v1[i]);//用户
 ? ? ? ?  let num2 = parseInt(v2[i]);//开发者
 ? ? ? ?  if(num1 > num2){
 ? ? ? ? ?  return 1;
 ? ? ? ?  }else if(num1 < num2){
 ? ? ? ? ?  return -1;
 ? ? ? ?  }
 ? ?  }
?
 ? ?  return 0;
 ?  }
?
  // 1.比对基础库版本号
 ? ?  // 1.1获取用户的基础库版本号 
 ? ?  let v1 = wx.getSystemInfoSync().SDKVersion;//'2.20.0'
 ? ?  let v2 = '1.0.0';
 ? ?  // 1.2比对 需要将字符串切割成数组进行比对
 ? ?  let res = compV(v1,v2);
 ? ?  // 1.3处理比对结果
 ? ?  if(res == -1){
 ? ? ?  // 提示更新微信客户端
 ? ? ?  wx.showModal({
 ? ? ? ?  title:'更新提示',
 ? ? ? ?  content:'版本过低是否更新!',
 ? ? ? ?  success:res=>{
 ? ? ? ? ?  // 1.4如果用户需要更新通知到维信客户端下载页面
 ? ? ? ? ?  wx.updateWeChatApp();
 ? ? ? ?  }
 ? ? ?  })
 ? ?  }

2.API 存在判断

    // 2.if判断api是否可用 
 ?  if(!wx.getUserProfile){
 ? ?  // 直接使用老版本方法替换它 
 ? ?  // wx.getUserInfo({})
 ? ?  console.log('版本过低')
 ?  }else{
 ? ?  // wx.getUserProfile({
 ? ?  // ? desc: 'desc',
 ? ?  // })
 ? ?  console.log('版本ok')
 ?  }

3.wx.canIUse检测api

wx.canIUse可以判断组件和api是否可用及其属性是否可用
?
 ?  // 3.wx.canIUse() return:bool  检测api、组件以及其内部的属性是否可用
 ?  // 3.1检测组件是否可用
 ?  // console.log(wx.canIUse('share-element')) 
 ?  // 3.2检测组件中的属性是否可用
 ?  // console.log(wx.canIUse('text.user-select')) 
?
 ?  // 3.3检测api是否可用
 ?  // console.log(wx.canIUse('getUserProfile')) 
 ?  // 3.4检测api中的属性是否可用
 ?  // console.log(wx.canIUse('request.object.enableHttpDNS')) 
?

六、优化-骨架屏使用

地址:骨架屏 | 微信开放文档

1.工具可以为当前正在预览的页面生成骨架屏代码。工具入口位于模拟器面板右下角三点处。

?

2.骨架屏代码通过小程序模板(template)的方式引入 以 pages/parent/parent 页面为例,引入方式如下。
?
/* 引入骨架样式文件 */
@import './parent.skeleton.wxss';
?
?
<!-- 使用骨架屏 -->
<!-- 引入骨架屏模板 -->
<import src="./parent.skeleton.wxml"></import>
<!-- 使用模板 -->
<template is='skeleton' wx:if="{{buffer}}"></template>
?
<!-- <view class="info" wx:else> -->
<view class="info">
 ?  <image src="../../images/0.jpg"></image>
 ?  <text>李四</text>
</view>

?

3.与普通的模板相同,通过 wx:if 控制显示隐藏。

?

4.可在 project.config.json 增加字段 skeleton-config 进行骨架屏相关配置。
    注意配置完毕后需要重新上生生成骨架屏才能生效;

?

使用注意:

1. 骨架屏仅包括页面首屏中的可见区域,对于横向滚动的 `swiper` 等容器,超出屏幕的子元素将被忽略;
2. 骨架屏的布局复用开发者的页面布局,需要骨架屏自适应页面尺寸时,页面布局应采用 rpx 等自适应方案;
3. 部分组件如 `movable-view`、`movable-area`、`rich-text`、`editor`、`picker`、`picker-view`、`picker-view-column`、`ad`、`officail-account`和`open-data` 无法生成理想的骨架效果,可通过添加一个父容器,结合 grayBlock、empty 等配置,将其置灰。
4. 请勿修改自动生成的骨架屏的代码,当效果不理想时,建议调整相关配置,这样当页面变更时,仍可自动生成;
5. 生成的骨架屏代码中会包含预览时的页面数据,将被用来填充页面;
6. 骨架屏通常用于商品列表、新闻列表等页面,对于动画/原生组件较多的页面展示效果不佳;
7. 该能力除用于展示首屏骨架外,也可作为局部加载的 `loading` 样式,可灵活使用;

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-12-01 17:49:28  更:2021-12-01 17:49:54 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 5:46:34-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码