Skip to content

1.mac中vscode常用快捷键

以下是在 macOS 上常用的 Visual Studio Code (VSCode) 快捷键:

  • 文件操作:
    • 打开文件:Command + O
    • 保存文件:Command + S
    • 关闭文件:Command + W
    • 新建文件:Command + N
    • 查找文件:Command + P
    • 切换标签页:Control + Tab 或 Command + Option + 左/右箭头
    • 关闭侧边栏:Command + B
    • 切换全屏模式:Control + Command + F
  • 编辑操作:
    • 复制一行:Shift + Option + 向上/向下箭头
    • 剪切一行:Command + X
    • 粘贴:Command + V
    • 撤销:Command + Z
    • 重做:Command + Shift + Z
    • 选中整行:Command + L
    • 注释代码:Command + /
    • 缩进:Tab
    • 反向缩进:Shift + Tab
    • 格式化代码:Option + Shift + F
  • 调试操作:
    • 启动调试:F5
    • 停止调试:Shift + F5
    • 设置断点:点击行号区域或使用 F9
    • 单步执行:F10(逐语句)和 F11(逐过程)
  • 其他常用操作:
    • 打开终端:Control + `
    • 查找替换:Command + F 或 Command + H
    • 打开命令面板:Command + Shift + P

这些是常用的快捷键,还有其他更多的快捷键可根据个人需求进行设置和使用。可以通过在 VSCode 中点击 "Code" 菜单 -> "首选项" -> "键盘快捷方式" 来查看和修改现有快捷键配置。

2.tap移动端事件

"tap" 事件是移动设备上的触摸事件之一。它类似于点击事件,但是专门用于触摸屏幕设备。

html
<image data-type='pre' bindtap="switchDate" src="{{httpImage}}/rank/leftIcon.png"/>

bindtap 属性通常表示一个用于 tap 事件的事件监听器,这在移动网页应用程序中常见。

data-type 属性被设置为 'pre'。这个属性是自定义的,它的具体含义取决于开发者在代码中的实现。

通常情况下,data-* 属性是用来存储自定义数据的,可以通过 JavaScript 或其他前端技术来读取和操作这些数据。

3.原生自定义的时间切换器模板(小程序)

html
<view>
    <image data-type='pre' bindtap="switchDate" src="{{httpImage}}/rank/leftIcon.png"/>
    <view>{{year}}年{{month}}月</view>
    <image data-type='next' bindtap="switchDate" src="{{httpImage}}/rank/rightIcon.png"/>
</view>
js
Page({
    data: {
        httpImage:getApp().data.httpImage,
        rankKind:5, // 排行榜种类(3、三星活跃 5、五星高活)
        scopType:1, // 排行榜分类(1、头部 2、中部 3、尾部)
        year:2023,
        month:0,
        rankList:[],//排行列表
        updateTime:'',// 更新时间
        starText:'五',
        currentDate:null,
        minDate:null,//最小日期
        maxDate:null,//最小日期
        isShowDialog:false,
        myRankingData:{
          rank:45,
          rankChange:0,
          agentId:4012,
          agentName:"王小小",
          activeRatio:6,
          provinceName:"河北省",
          agentType:"中部经销商",
          changeType:2
        }
    },
    switchDate(e){
      const type= e.currentTarget.dataset.type
      if(type=='pre') // 向前
      {
        if(this.data.currentDate <= this.data.minDate)
        {
          return 
        }
        let firstDayPrevMonth = this.data.currentDate;
        firstDayPrevMonth.setDate(0)
        firstDayPrevMonth.setDate(1)
        let month=firstDayPrevMonth.getMonth()+1
        if(month<10)
        {
          month = '0'+month
        }
        this.setData({
          currentDate:firstDayPrevMonth,
          year:firstDayPrevMonth.getFullYear(),
          month,
        })



      }else{ // 向后

        let firstDayNextMonth =  new Date(this.data.currentDate.getFullYear(), this.data.currentDate.getMonth() + 1, 1)
        if(firstDayNextMonth >= this.data.maxDate.getTime())
        {
          return 
        }

        let month=firstDayNextMonth.getMonth()+1
        if(month<10)
        {
          month = '0'+month
        }

        this.setData({
          currentDate:firstDayNextMonth,
          year:firstDayNextMonth.getFullYear(),
          month,
        })
      }

      this.getRankList()
    },
    onLoad(options) {
        const date = new Date()
        let month = date.getMonth()+1
        let monthText = month
        if((month+1)<10)
        {
          monthText = '0'+(month)
        }
        this.setData({
          year:date.getFullYear(),
          month:monthText,
          currentDate:new Date(`${this.data.year}/${month}/01`),
          maxDate:new Date(`${this.data.year}/${month+1}/01`),
          minDate:new Date('2022/1/1')
        })
        this.getRankList()
    },
})

取data中的数据:this.data.rankKind

设置data中的数据:

js
this.setData({

  currentDate:firstDayPrevMonth,

  year:firstDayPrevMonth.getFullYear(),

})

4.小程序开发中一些不理解的地方

1.es6-promise.js库

es6-promise.js 是一个用于支持 Promise 功能的 JavaScript 库。在小程序开发中,由于小程序环境对 ES6 Promise 的支持不完整,开发者可以使用这个库来填补这一缺失。

在小程序开发中,尽管对于大多数现代浏览器来说,原生支持 ES6 Promise 是标准的,但小程序环境对 ES6 Promise 的支持可能存在一些限制或差异。

小程序不是传统意义上的浏览器环境。小程序是一种基于特定平台的应用程序框架,它在不同的平台上提供了一种轻量级的应用开发和运行环境。

不同平台的小程序,如微信小程序、支付宝小程序、百度小程序等,都有各自的内核和执行环境。这些内核并不是基于传统的浏览器内核,如WebKit、Blink 或 Gecko。

2.小程序也是浏览器环境吗,内核是什么?

具体来说,不同小程序平台的内核如下:

  1. 微信小程序:微信小程序的内核是基于自研的开放原始码项目"WeixinJSBridge",这是一个专门用于小程序的 JavaScript 框架和运行环境。
  2. 支付宝小程序:支付宝小程序使用的是自家开发的运行时框架,称为小程序开发框架,它提供了类似于浏览器的渲染引擎,用于解析和渲染小程序页面。
  3. 百度小程序:百度小程序的内核是基于自家开发的脚本引擎,称为"swan-core",它用于解析和执行小程序的代码。

尽管小程序具有一些与浏览器相似的特性,例如渲染页面、处理事件、发送网络请求等,但它们在内部实现和架构上与传统的浏览器有所不同。小程序的内核和执行环境是针对特定平台的,专门为小程序提供支持和功能。

需要注意的是,小程序在执行上具有一些与浏览器相似的特征,但在功能和实现上存在差异。开发小程序时,开发者需要根据目标平台的文档和规范来编写代码,并了解该平台特定的 API 和能力。

3.微信开发者工具有的时候报错

可能需要关闭工具重新打开,可能就好了

可能需要更新开发者工具的版本,就好了

会比较奇怪一些!

4.公司vpn的使用

公司的vpn在用的时候要把代理关闭,否则失败!

5.wx.request介绍

注意:微信小程序开发中不能使用 axios,而是使用微信自带的 wx.request模块

wx.request 是微信小程序中用于发送网络请求的 API。它可以用于向服务器发送 HTTP 请求,获取数据或与后端进行交互。以下是 wx.request 的基本用法示例:

js
wx.request({
  url: 'http://example.com/api/data', // 请求的 URL
  method: 'GET', // 请求方法,可选值包括:GET、POST、PUT、DELETE等
  data: {
    key1: 'value1',
    key2: 'value2'
  }, // 请求的数据,可选
  header: {
    'content-type': 'application/json' // 请求的数据类型
  },
  success: function (res) {
    // 请求成功的回调函数
    console.log(res.data); // 输出响应数据
  },
  fail: function (error) {
    // 请求失败的回调函数
    console.log(error);
  }
});

在上述示例中,我们使用 wx.request 发送一个 GET 请求到指定的 URL,并传递一些请求参数。成功时,会执行 success 回调函数,并在控制台输出响应数据;失败时,会执行 fail 回调函数,并输出错误信息。

你可以根据实际需求自行修改 URL、请求方法、数据、请求头和回调函数等参数。记得替换示例中的 URL 为你自己的接口地址,并根据接口要求传递正确的数据和请求头。

请注意,wx.request 是一个异步操作,因此成功或失败的回调函数将在请求完成后被调用。在回调函数中可以处理服务器响应的数据或错误信息。

同时,请确保在小程序的权限设置中允许网络请求,否则可能会导致请求失败。

6.wx.request微信小程序的请求封装逻辑

首先在 request.js文件中封装 promise 请求:

js
let Promise = require('./es6-promise.js') //promise 模块,小程序专用
import log from '../utils/log/logger' //日志有关的模块(需要封装)
import urls from './urls' //所有的请求链接
// 不login请求的promise封装
function handlePromisify(fn, showLoading = false) {
  // showLoading 显示loading 默认不显示
  if (showLoading) {
    wx.showLoading({
       title: '拼命加载中',
       mask: true
     })
  }
  requestHeader = wx.getStorageSync("requestHeader") || {}
  if (urls.pyyxHeader) {
    requestHeader = Object.assign({}, requestHeader, urls.pyyxHeader)
  }
  return function (obj = {}) { //返回一个函数,函数默认有一个空对象 obj
    //返回值为 promise 对象,promise 对象可以接收一个函数作为参数,里面做一些具体的操作
    return new Promise((resolve, reject) => {
      //给对象设置各个回调属性(其余 data,url 等属性在传进来之前就已经设置了)
      //设置请求成功时的回调(但是并没有调用它们)
      obj.success = function (res) { 
        if (showLoading) {
           setTimeout(() => {
             wx.hideLoading()
           }, 100)
        }
        //成功
        // =======直接返回可用数据res.data========
        resolve(res.data)
        log.response(obj.method, 'url:', obj.url, 'params:', obj.data, 'response:', res.data) //输出日志文件
      }
      //设置请求失败时的回调
      obj.fail = function (res) {
        //失败
        reject(res)
        log.response('Fail', obj.method, 'url:', obj.url, 'params:', obj.data, 'response:', res.data)
      }
      obj.complete = function (e) {
        if (e.errMsg.search(/fail/) != -1) {
          wx.showToast({
            title: "网络加载超时",
            icon: 'none',
            duration: 3000
          })
        }
      }
      fn(obj) //fn 就是 wx.request 模块,这里真正滴发起请求,并把obj作为参数
      //这个wx.request请求完成之后会自动走到对应的状态的回调函数,回调函数里面调用对应的 promise 状态改变函数,所以本函数handlePromisify最终返回值为 promise对象,可以进行.then等操作
    })
  }
}
// post请求封装(不 login 的时候)
function post(url, data, showLoading = true) {
  log.request('Post url:', url, 'params:', data)
  let time = parseInt(Date.now() / 1000);
  data = Object.assign({}, data, commonParams)
  data.time = time;
  data.sign = getCoinSign(time)
  var postRequest = handlePromisify(wx.request, showLoading)//调用handlePromisify,并把官方请求模块wx.request传入这个方法,生成一个返回值为 promise对象 的函数postRequest
  setCommonParams()
  return postRequest({
    url: url,
    method: 'POST',
    data: data,
    header: requestHeader,
    // header: { 'YX-PARENT-SESSID': '4ae32c0062e6cd5cc660a54482ab07354cb5906e' }

  }) //这里就是发起wx.request请求了,因为传入了参数,调用了postRequest函数,这个函数里面使用了 wx.request函数
}
module.exports = {
  get: get, //不需login 
  post: post, //不需login 
  getRequest: getRequest, //需login 
  postRequest: postRequest, //需login
  urls: urls, //这里是所有的请求 url,请求模块进行分离
}

urls.js:

js
import hosts from './hostConfig'
const { main, padHost } = hosts;
const urls = {
    devicedetail: `${main}/api/agent/devicedetail`,//设备授权详情
    applyuserauthorization: `${main}/api/agent/applyuserauthorization`,//申请设备授权
    handleuserauthorization: `${main}/api/agent/handleuserauthorization`,//家长处理授权
}
module.exports = urls

在具体页面的xxx.js文件中进行使用:这里其实就是相当于没有 api 那个文件夹,把那里面的工作在这来做了!

所以每个页面都要引入Common 请求模块,这也是缺点之一!

js
import Common from "../../../lib/request" //引入请求封装模块
getData() {
  //传入 url 和 data
  Common.post(Common.urls.pctree,
    {
    	uri: Common.urls.pctree,
    	params: JSON.stringify({})
  	}
  ).then((res) => {
    if (!res.code) {
      let provinceArr = res.data.filter((item) =>{
        return item.code != 900000
      })
      this.setData({
        multiArray: [provinceArr, provinceArr[0].items],
      })
    }
  })
},

wx.request 与 axios 的区别:

wx.request不会自动处理成功和失败情况,所以在请求的代码参数中要设置网络请求的成功回调函数 obj.success 和失败回调函数 obj.fail。这两个回调函数会在请求成功或失败时被调用,并执行相应的操作。

Axios 的语法更加简洁,它会自动处理请求的成功和失败情况,并通过 Promise 的链式调用来处理响应。不再需要显式传递 successfail 属性,而是通过 .then.catch 方法来处理响应。

上面这里封装的handlePromisify函数就做了生成 promise的操作,应该类似于 axios 的源码操作!

handlePromisify 函数的具体解释:

handlePromisify 函数,用于将一个具有回调风格的异步操作转换为返回 Promise 对象的形式。

这个函数接受两个参数:fnshowLoadingfn 是一个函数,表示需要进行异步操作的函数,这里的示例中是 wx.requestshowLoading 是一个布尔值,用于确定是否显示加载提示,默认为 false

在函数内部,首先根据 showLoading 的值决定是否显示加载提示框。然后,从本地存储中获取请求头信息,并根据 urls.pyyxHeader 对象进行合并。接下来,返回一个函数,并且该函数有一个默认的空对象参数 obj

在返回的函数中,创建了一个新的 Promise 对象,并传入了 resolvereject 作为参数。然后,通过给 obj 对象设置成功回调函数 obj.success、失败回调函数 obj.fail 和完成回调函数 obj.complete,来处理请求的各个阶段。

成功回调函数中,执行一些操作(例如隐藏加载提示框),然后调用 resolve 函数并传递请求返回的数据 res.data,表示请求成功并将数据传递给下一个 then 方法处理。同时,使用 log.response 记录请求成功的日志信息。

失败回调函数中,调用 reject 函数并传递请求返回的错误信息 res,表示请求失败,并将错误信息传递给下一个 catch 方法处理。同样,使用 log.response 记录请求失败的日志信息。

完成回调函数中,根据 e.errMsg 的值判断是否请求失败,如果失败,则显示一个网络加载超时的提示。

最后,调用 fn(obj) 来执行实际的异步操作,即发起网络请求。当 wx.request 完成时,会自动调用相应的回调函数,回调函数内部调用对应的 Promise 状态改变函数,使得最终返回的是一个 Promise 对象,可以进行 .then.catch 等操作

总之,这个 handlePromisify 函数通过封装和处理异步操作的回调函数,将其转换为返回 Promise 对象的形式,以便更便捷地进行异步操作和处理响应。

重点注意:new Promise( ) 用于构建 promise对象,它接收一个函数作为参数,函数里面可以做任何操作,只要最后调用了状态改变函数 resolve 和 reject 改变了 promise 的状态,那么最后 new Promise 的返回值就是一个可以.then和.catch的 promise 对象!否则就是一个 pending 状态的 promise!

7.小程序设置请求日志log的策略

在封装 wx.request为 promise的代码中我们可以看到,有这样一句话:

js
log.response(obj.method, 'url:', obj.url, 'params:', obj.data, 'response:', res.data) //输出日志文件

这句话的意思其实是:把我们本次请求的类型,路径地址,参数,返回值储存起来,作为日志文件

上面引入了日志管理模块

js
import log from '../utils/log/logger' //日志有关的模块(需要封装)

其中 logger 文件:

js
import manager from './manager'
import uploadLog from './upload' //上传日志
import Common from "../../lib/request.js"
// logger管理
const logger = {

	/**
	 * 初始化方法,此方法用于管理日志大小
	 * 由于微信本地文件大小限制在10M, 每次启动都需要清理3天前的日志文件
	 */
	init: function() {
		manager.cleanBefore()
	},

	/**
	 * 操作、流程类日志
	 * @param  {...any} args 
	 */
	action: function(...args) {
		manager.info(manager.type.action, args)
	},
	/**
	 * 网络请求日志
	 * @param  {...any} args 
	 */
	request: function(...args) {
		manager.info(manager.type.request, args)
	},
	/**
	 * 网络响应日志
	 * @param  {...any} args 
	 */
	response: function(...args) {
		manager.info(manager.type.response, args)
	},

	/**
	 * 读取所有日志
	 */
	read: function() {
		manager.read()
	},
  readAll: function (Common) {
    return manager.readAll(Common)
  },
	/**
	 * 删除所有的日志
	 */
	clean: function() {
		manager.clean()
	},

	/**
	 * 上传日志到服务器
	 */
  upload: function (Common) {
    console.log(Common,"loggger")
    this.readAll(Common)
		// let that = this
    // uploadLog.upload(function() {
    //   let paths = that.readAll()
    //   return paths
		// })
		// uploadLog.upload(function() {
    //   let paths = that.readAll()
    //   console.log(paths,"upload")
		// 	setTimeout(() => {
		// 		that.clean()
		// 	}, 3000)
    //   return paths
		// })
	}
 } 

export default logger

manager又是一个重要的模块,里面有存储、读取、清除日志的核心逻辑

manager.js部分代码:逻辑太过复杂

js
const fileManager = wx.getFileSystemManager(); //使用了 wx 内置的文件管理器
info: function(type, ...args) {
  console.debug(type, args[0])
  this._writeLog(type, dateUtils.dateTimeString() + ' ')
  for (let i = 0; i < args[0].length; i++) {
    const content = args[0][i]
    this._writeLog(type, this._toString(content))
    this._writeLog(type, '\t')
  }
  this._writeLog(type, type == this.type.response ? '\n\n' : '\n')
},

一般三个文件:

action(操作动作 + 处理流程,一般是 app 项目启动、设备信息、错误信息等)在一个文件

request 在一个文件

response 在一个文件

8.小程序的 appid

每个小程序的 appid 都在 project.config.json配置文件中有

image-20230608191203434