小程序笔记

目录

1.navigator

2.flex布局

3.伪元素选择器

4.wx:for嵌套

5. wx:key遍历数组

6.margin和padding的使用(内外边距)

7. justify-content

8.bindtap 和 catchtap 的区别

9.步进器

10.white-space

11.word-break

12.line-height

13.生命周期函数

14.mobx-miniprogram

15.mobx-miniprogram 三个核心概念

16.request请求相关知识点

17.constructor构造函数

18.promise方法

19. handler方法

20.description方法

21.then和catch使用

22.请求拦截器和响应拦截器

23.async await

24.store对象的四个属性

25.fields

26.computed与watch异同

27.mobx中的computed和reactions

28.token含义及用法

29.param

30.actions

31.miniprogram-computed安装步骤

32.wx.request网络请求

33. observable 函数

34.LBS逆地址解析

35.async-validator

1. 概述

2. 基础用法

3. 自定义异步验证

4. 其他特性

5. 总结

36.SwipeCell自动收起

1. 触发机制

2. 编程实现

3. 注意事项

4. 示例代码(小程序框架)

37.微信小程序节流阀

1. 函数节流的概念

2. 函数节流的应用场景

3. 实现函数节流的方法

4. 在微信小程序中使用节流函数

5. 注意事项


1.navigator

navigator是一个全局对象,它提供了与浏览器相关的信息和操作接口。在前端开发中,我们通常会使用 navigator 对象来获取用户浏览器的相关信息。
navigator 对象的常见属性和方法包括:
navigator.userAgent: 返回当前浏览器的用户代理字符串。
navigator.appName: 返回当前浏览器的名称。
navigator.appVersion: 返回当前浏览器的版本号。
navigator.language: 返回当前浏览器的语言设置。
navigator.platform: 返回当前浏览器所在设备的操作系统平台。
navigator.geolocation: 提供了一组 API,用于获取当前设备的地理位置信息。
navigator.mediaDevices: 提供了一组 API,用于访问当前设备的音频、视频、屏幕等媒体设备。
navigator.serviceWorker: 提供了一组 API,用于在浏览器中注册和管理 Service Worker,实现离线缓存和推送通知等功能

2.flex布局

            flex-direction属性

             flex-direction属性用于设置主轴方向,通过设置主轴方向可以规定项目的排列方向。 

             row:默认值,主轴为从左到右的水平方向。

              row-reverse:主轴为从右到左的水平方向。

              column:主轴为从上到下的垂直方向。

              column-reverse:主轴为从下到上的垂直方向。 

            justify-content属性

               justify-content属性用于设置项目在主轴方向上的对齐方式。能够分配项目之间及其周围                 多余的空间。 

               flex-start:默认值,表示项目对齐到主轴起点,项目间不留空隙。

               flex-end:项目对齐到主轴终点,项目间不留空隙。

               center:项目在主轴上居中排列,项目间不留空隙。

        

               space-between:两端对齐,两端的项目分别靠向容器的两端,其他项目之间的间隔相等                   space-around:每个项目之间的距离相等   

           

             align-items属性align-items属性用于设置项目在交叉轴上的对齐方式。

             center:项目在交叉轴的中间位置对齐。

             flex-start:项目顶部与交叉轴起点对齐,flex-end:项目底部与交叉轴终点对齐。

             baseline:项目的第一行文字的基线对齐。

3.伪元素选择器

 所谓“伪元素” 就是在dom结构本来是不存在的 但是通过css创建出来的元素

        ::before   ::after

        用于向指定元素的前面或者后面加入特定的内容

4.wx:for嵌套

wx:for 是用来做列表渲染,在组件上使用wx:for绑定一个数组,数组的下标变量名默认为index,数组当前项的变量名默认为item.

5. wx:key遍历数组

wx:key 提升性能。 

wx:key 属性值有两种添加属性。 

1. 字符串,需要是遍历的数组中 item 的某个属性,要求该属性是列表中唯一的字符串或者数字,不能进行动态改变。 

2. 保留关键字 *this ,*this代表的是 item 本身,item 本身是唯一的字符串或者数字

6.margin和padding的使用(内外边距)

外边距(margin):

外边距定义了元素与其周围元素之间的空白区域。
外边距可以设置为正值、负值或百分比。
外边距可以用来控制元素之间的间距、对齐元素、扩展元素的可点击区域等。
外边距不会影响元素的背景颜色或边框。


内边距(padding):

内边距定义了元素的内容与其边框之间的空白区域。
内边距可以设置为正值、负值或百分比。
内边距可以用来控制元素内容与边框之间的间距、增加元素的可点击区域等。
内边距会影响元素的背景颜色。
在CSS中,可以使用以下属性来控制外边距和内边距:

外边距属性:

margin-top:顶部外边距
margin-right:右侧外边距
margin-bottom:底部外边距
margin-left:左侧外边距


内边距属性:

padding-top:顶部内边距
padding-right:右侧内边距
padding-bottom:底部内边距
padding-left:左侧内边距


这些属性可以接受不同的值,例如像素(px)、百分比(%)、em等

7. justify-content

justify-content 属性:设置主轴的对齐方式,弹性子元素在主轴方向上的对齐方式,

justify-content: flex-start; 默认值,主轴顶端对齐

justify-content: flex-end; 主轴的末端对齐

justify-content: center; 居中对齐,子元素位于弹性容器的中心

justify-content: space-between; 两端对齐,子元素和子元素之间有空白空间,项目之间的间隔都相等。

justify-content: space-around; 子元素之前、之间、之后都留有空白空间,且空间自行分配,项目之间的间隔比项目与边框的间隔大一倍。

space-evenly:弹性项目平均分布在该行上,相邻项目的间隔,项目与容器之间空间相等

8.bindtap 和 catchtap 的区别

事件冒泡:bindtap会将事件传递给父节点进行处理,而catchtap会阻止事件继续冒泡到父节点。换句话说,当一个元素上的bindtap事件被触发时,如果该元素的父节点也有相同类型的bindtap事件,父节点的事件处理函数也会被执行;而catchtap则只会触发当前元素的事件处理函数。

绑定顺序:多个元素同时绑定了bindtap和catchtap事件时,它们的触发顺序是不同的。bindtap的触发顺序是由子元素向父元素冒泡的顺序(即从内到外);而catchtap的触发顺序是由父元素向子元素捕获的顺序(即从外到内)。

阻止默认行为:对于某些具有默认行为的元素(如<form>、<input type="submit">等),bindtap可以通过返回false来阻止默认行为的触发;而catchtap无法阻止这些默认行为。

用途:在一般情况下,推荐使用bindtap来进行事件绑定,因为它可以与父元素的事件一起工作,并且在处理冒泡事件时更加灵活。只有在确实需要阻止事件冒泡或不想触发父元素的事件处理函数时,才使用catchtap。

9.步进器

微信小程序步进器(stepper)是一个自定义组件,其代码相对简单,适合新手学习使用。步进器常用于购物车等需要增减数量的场景,也用于一些旅游项目中增减房间数和人数等。从开发的角度来看,步进器需要适应多种场景和控制一些状态,如最小值、最大值、每次增加或减少的值、是否禁用以及组件的索引值等。

10.white-space

white-space属性值

normal:忽略多余的空白,只保留一个空白(默认);
pre:保留空白(行为方式类似于html中的pre标签);
nowrap:只保留一个空白,文本不会换行,会在在同一行上继续,直到遇到br标签为止。
pre-wrap:保留空白符序列,正常地进行换行;
pre-line:合并空白符序列,保留换行符;
inherit:从父元素继承white-space属性的值。

11.word-break

word-break 属性规定自动换行的处理方法。

提示:通过使用 word-break 属性,可以让浏览器实现在任意位置的换行。

12.line-height

  1. 定义与用途:line-height属性定义了元素中文本行之间的最小距离,即基线间的距离。这不仅影响了文本的垂直间距,还可能与字号一起影响文本之间的空白距离。

  2. 语法与取值:line-height的语法包括多种取值方式,如normal(默认值,通常为1到1.2倍的字体尺寸)、实数(缩放因子)、长度值(如像素值)、百分比(基于元素的字体尺寸)以及inherit(继承父元素的行高)。

  3. 适用范围:line-height适用于所有元素,但在微信小程序中,通常直接应用于text组件或其父级容器,以调整文本内容的行高。

  4. 设置方式:在WXSS(微信小程序样式表)中,可以通过类选择器或ID选择器等方式为元素设置line-height属性。

13.生命周期函数

  onload:页面加载时的生命周期函数

  onShow:页面显示生命周期函数,没打开页面就会调用一次

  onReady:页面初次渲染完成生命周期函数,页面初次渲染完成时触发

  onHide:页面隐藏生命周期函数 如页面切入到后台或通过底部tab栏到其他页面

  onUnload:页面卸载生命周期函数

14.mobx-miniprogram


mobx-miniprogram 是针对微信小程序开发的一个简单、高效、轻量级状态管理库,它基于Mobx状态管理框架实现。

使用 mobx-miniprogram 定义管理的状态是响应式的,当状态一旦它改变,所有关联组件都会自动更新相对应的数据

通过该扩展工具库,开发者可以很方便地在小程序中全局共享的状态,并自动更新视图组件,从而提升小程序的开发效率

15.mobx-miniprogram 三个核心概念

observable:用于创建一个被监测的对象,对象的属性就是应用的状态(state),这些状态会被转换成响应式数据。

action:用于修改状态(state)的方法,需要使用 action 函数显式的声明创建。

computed:根据已有状态(state)生成的新值。计算属性是一个方法,在方法前面必须加上 get 修饰符

16.request请求相关知识点

1. request对象和response对象的原理
    1. request和response对象是由服务器创建的。我们来使用它们
    2. request对象是来获取请求消息,response对象是来设置响应消息

2. request对象继承体系结构:    
    ServletRequest        --    接口
    HttpServletRequest    -- 接口
    org.apache.catalina.connector.RequestFacade 类(tomcat)

3. request功能:
    1. 获取请求消息数据
        1. 获取请求行数据
             GET /day14/demo1?name=zhangsan HTTP/1.1
            方法:
                1. 获取请求方式 :GET
                     String getMethod()  
                2. 获取虚拟目录:/day14
                    String getContextPath()
                3. 获取Servlet路径: /demo1
                     String getServletPath()
                4. 获取get方式请求参数:name=zhangsan
                    String getQueryString()
                5. 获取请求URI:/day14/demo1
                     String getRequestURI():        /day14/demo1
                     StringBuffer getRequestURL()  :http://localhost/day14/demo1

                     URL:统一资源定位符 : http://localhost/day14/demo1    中华人民共和国
                     URI:统一资源标识符 : /day14/demo1                    共和国
                
                6. 获取协议及版本:HTTP/1.1
                     String getProtocol()

                7. 获取客户机的IP地址:
                     String getRemoteAddr()
                
        2. 获取请求头数据
             方法:
                String getHeader(String name):通过请求头的名称获取请求头的值
                 Enumeration<String> getHeaderNames():获取所有的请求头名称
            
        3. 获取请求体数据:
            请求体:只有POST请求方式,才有请求体,在请求体中封装了POST请求的请求参数
            步骤:
                1. 获取流对象
                     BufferedReader getReader():获取字符输入流,只能操作字符数据
                     ServletInputStream getInputStream():获取字节输入流,可以操作所有类型数据
                        在文件上传知识点后讲解

                2. 再从流对象中拿数据

17.constructor构造函数

constructor伴随着函数产生的,当创建一个函数时,会默认为函数创建一个prototype对象(原型对象)。在prototype对象里,也会默认添加两个属性,__proto__和constructor。

__proto__是形成原型链的重要原因,如果想要了解原型链,请进入JavaScript--原型链。constructor属性是指向构造函数本身的。

比如: function A() { }

A.prototype.constructor === A

接下来,我将通过一个实例对象,来写成一系列相关的constructor,这里你需要去进入JavaScript--原型链中去了解原型链。

let a = new A()

(注:通过构造函数new一个实例对象,new的过程中,发生了:新创建一个空对象{},将this指向这个对象,执行构造函数内容,返回这个对象)

18.promise方法

1. Promise.all 的用法
这个方法接受一个Promise对象的数组作为参数

只有当数组中的所有Promise对象都成功完成时,它才会返回一个新的成功的Promise对象,其结果是一个由每个Promise对象的返回值组成的数组。

如果有任何一个Promise对象失败,all()方法将立即返回一个失败的Promise对象。

多个 Promise 任务同时执行。 如果全部成功执行,则以数组的方式返回所有 Promise 任务的执行结果。 如果有一个Promise 任务 rejected,则只返回 rejected 任务的结果。

let Promise1 = new Promise(function(resolve, reject){})
let Promise2 = new Promise(function(resolve, reject){})
let Promise3 = new Promise(function(resolve, reject){})

let p = Promise.all([Promise1, Promise2, Promise3])

p.then(funciton(){
  // 三个都成功,则成功    
}, function(){
  // 只要有失败,则失败
})
let p1 = new Promise((resolve, reject) => {
  resolve('成功了');
})

let p2 = new Promise((resolve, reject) => {
  resolve('success');
})

let p3 = Promse.reject('失败');

Promise.all([p1, p2]).then((result) => {
  console.log(result)               //['成功了', 'success']
}).catch((error) => {
  console.log(error)
})

Promise.all([p1,p3,p2]).then((result) => {
  console.log(result)
}).catch((error) => {
  console.log(error)      // 失败了,打出 '失败'
})

需要特别注意的是,Promise.all获得的成功结果的数组里面的数据顺序和Promise.all接收到的数组顺序是一致的,即p1的结果在前,即便p1的结果获取的比p2要晚。这带来了一个绝大的好处:在前端开发请求数据的过程中,偶尔会遇到发送多个请求并根据请求顺序获取和使用数据的场景,使用Promise.all毫无疑问可以解决这个问题。

2. Promise.race 的用法
顾名思义,Promse.race 就是赛跑的意思,意思就是说,
Promise.race([p1, p2, p3])里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态。

这个方法也接受一个Promise对象的数组作为参数。

与all()不同的是,race()方法会在数组中的任何一个Promise对象最先完成(无论是成功还是失败)时,就返回一个新的Promise对象,其结果就是那个最先完成的Promise对象的结果。

这里强调下,其它的promise实例仍然会继续运行,只不过其状态和结果不会归于最终的结果。

let p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('success')
  },1000)
})

let p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject('failed')
  }, 500)
})

Promise.race([p1, p2]).then((result) => {
  console.log(result)
}).catch((error) => {
  console.log(error)  // 打开的是 'failed'
})
//请求某个图片资源
function requestImg(){
    var p = new Promise((resolve, reject) => {
        var img = new Image();
        img.onload = function(){
            resolve(img);
        }
        img.src = '图片的路径';
    });
    return p;
}

//延时函数,用于给请求计时
function timeout(){
    var p = new Promise((resolve, reject) => {
        setTimeout(() => {
            reject('图片请求超时');
        }, 5000);
    });
    return p;
}

Promise.race([requestImg(), timeout()]).then((data) =>{
    console.log(data);
}).catch((err) => {
    console.log(err);
});

requestImg函数会异步请求一张图片,我把地址写为"图片的路径",所以肯定是无法成功请求到的。timeout函数是一个延时5秒的异步操作。我们把这两个返回Promise对象的函数放进race,于是他俩就会赛跑,如果5秒之内图片请求成功了,那么遍进入then方法,执行正常的流程。如果5秒钟图片还未成功返回,那么timeout就跑赢了,则进入catch,报出“图片请求超时”的信息。

3. Promise.allSettled 的用法
接收一个 Promise 对象数组作为参数

和 Promise.all() 相似,它等待所有 Promise 都达到稳定(Settled)状态(即无论是 fulfilled 还是 rejected )后才会确定。
返回一个新的 Promise 对象,这个新的 Promise 在数组中的所有 Promise 都已经确定状态后才会确定

返回的 Promise 会解析为一个包含每个 Promise 结果的数组,每个结果都是一个包含 status 属性和 value 或 reason 属性的对象。
一旦所有Promise都确定了,返回的 Promise 会变成 fulfilled ,并且结果是一个数组,包含了每个输入 Promise 的结果描述对象,这些对象具有status( fulfilled 或 rejected )和对应的 value 或 reason 属性。

不会因为数组中的某个 Promise 被拒绝而立即返回,它会等待所有的 Promise 完成

Promise.all() 更关注所有 Promise 是否都成功完成,它适用于需要所有任务成功完成才能继续下一步场景。
而 Promise.allSettled() 则允许你观察一组异步操作的所有结果,无论成功与否,这对于获取并处理所有任务的最终状态非常有用。

const promise1 = Promise.resolve(3);
const promise2 = 42;   // promise2 是一个非 Promise 值,它会被隐式地转换为一个已解析的 Promise。
const promise3 = new Promise((resolve, reject) => {
  setTimeout(reject, 100, 'foo');
});
const promise4 = new Promise((resolve, reject) => {
  setTimeout(resolve, 50, 'bar');
});

const promises = [promise1, promise2, promise3, promise4];

Promise.allSettled(promises).
  then((results) => results.forEach((result) => console.log(result.status)));

// 输出:
// "fulfilled"
// "fulfilled"
// "rejected"
// "fulfilled"

4. Promise.resolve 的用法

var p1 = Promise.resolve(1);
var p2 = Promise.resolve(p1);
var p3 = new Promise(function(resolve, reject){
  resolve(1);
});
var p4 = new Promise(function(resolve, reject){
  resolve(p1);
});

console.log(p1 === p2); 
console.log(p1 === p3);
console.log(p1 === p4);
console.log(p3 === p4);

p4.then(function(value){
  console.log('p4=' + value);
});

p2.then(function(value){
  console.log('p2=' + value);
})

p1.then(function(value){
  console.log('p1=' + value);
})

Promise.resolve(...) 可以接收一个 值 或者是一个 Promise对象 作为参数。

当参数是普通值时,它返回一个resolved状态的Promise对象,对象的值就是这个参数;
当参数是一个Promise对象时,它直接返回这个Promise参数。因此,p1 === p2。

但通过new的方式创建的Promise对象都是一个新的对象,因此后面的三个比较结果都是false。

另外,为什么p4的then最先调用,但在控制台上是最后输出结果的呢?
因为p4的resolve中接收的参数是一个Promise对象p1,resolve会对p1”拆箱“,获取p1的状态和值,但这个过程是异步的

.

无论是 then 还是 catch ,只要不报错,都返回的是 resolved 状态的 promise。
报错则返回的是 rejected 状态的 promise

Promise.resolve().then(() => {
    console.log(1); // 不报错,返回的是resolved状态的promise,触发then回调
}).catch(() => {
    console.log(2); // 不触发
}).then(() => {
    console.log(3); // 触发
})

// 1
// 3
Promise.resolve().then(() => {
    console.log(1);
    throw new Error('error'); // 报错,返回的是rejected状态的promise,触发catch回调
}).catch(() => {
    console.log(2); // 不报错,返回的是resolved状态的promise,触发then回调
}).then(() => {
    console.log(3); // 触发
})

// 1
// 2
// 3

5. Promise.reject 的用法

用于创建一个已拒绝的 Promise。

接收一个原因(reason)作为参数,并返回一个已拒绝为该原因的 Promise 对象

const promise = Promise.reject('error');

promise.catch((reason) => {
  console.log(reason); // 输出 "error"
});

Promise.reject('error') 创建了一个已拒绝的 Promise,原因是字符串 error。

然后,我们使用 catch() 方法来处理这个已拒绝的 Promise。

catch() 方法接收一个回调函数作为参数,这个回调函数在 Promise 被拒绝时被调用,并接收 Promise 的原因作为参数。在这个例子中,回调函数输出了 Promise 的原因,即字符串 error。

19. handler方法

方式一,使用Handler.sendMessage()

在该使用方式中,因创建Handler的方式不同,又可分两种:创建Handler子类、使用匿名Handler内部类,但本质都是相同的,都是继承Handler类创建子类

一,创建Handler子类
1、自定义Handler子类,并重写handleMessage()方法
    class mHandler extends Handler {
       //重写handleMessage()方法
         @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            //执行的UI操作 
        }
    }
2、主线程中创建mHandler的实例
    private mHandler mhandler = new mHandler();
3、在子线程中创建需要发送的消息对象
    Message msg = Message.obtain();
    msg.what = 1;
4、在子线程中通过Hander发送消息到消息队列
    mhandler .sendMessage(msg);
5、启动子线程
 
二、使用匿名Handler子类
1、在主线程中通过匿名内部类创建Handler类对象
    Handler mhandler =  new Handler(){
        //重写handleMessage()方法
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            //执行的UI操作 
        }
    };
2、在子线程中创建需要发送的消息对象
    Message msg = Message.obtain();
    msg.what = 1;
3、在子线程中通过Hander发送消息到消息队列
    mhandler .sendMessage(msg);
4、启动子线程

方式二、使用Handler.post()方法

1、在主线程中创建Handler实例
    private Handler mhandler = new Handler();
2、在子线程中使用Handler.post()
     mhandler.post(new Runnable() {
                                @Override
                            public void run() {
                                 //执行的UI操作 
                            }
                        });
3、启动子线程

20.description方法

属性 (Attributes)
title: 列表标题,可选。
border: 是否显示边框,默认为 true。
column: 列的定义,一个对象数组,每个对象包含 label(标签名)、span(列跨度)等属性。
插槽 (Slots)
default: 用于插入列表项的内容。
事件 (Events)
Element Plus 的 Descriptions 组件通常不直接触发事件,但你可以在其子组件(如 DescriptionItem)上监听事件。

方法 (Methods)
Descriptions 组件通常不直接提供方法,但你可以通过 Vue 的响应式数据来动态控制其内容。

21.then和catch使用

1、then()方法是异步执行。

意思是:就是当.then()前的方法执行完后再执行then()内部的程序,这样就避免了,数据没获取到等的问题。通常用在ajax请求后面

2、catch()方法防止因为错误而造成系统崩溃

在程序逻辑中, 需要在易出现问题的逻辑代码片段上, 加持catch方法, 这样做可以捕获错误, 但是不会影响整个程序运转;

3、示例

        1、then()里写两个参数,第一个是成功时的回调方法,默认给这个方法传递了成功的数据,
另一个是失败的方法,以及失败的数据

<script>
export default {
  name: 'demo',
  data() {
    return {}
  },
  methods: {
    testDemo(data) {
      // ajax请求
      testAjax(url, params).then(data => {
        // 处理成功
        console.log(data)
      }, data => {
        // 处理失败
        console.log(data)
      })
    }
  }
}
</script>

        2、一般情况下,为了不报错,会在then()后面调用.catch(),相当于类似try{}catch(e){} ,可以理解为省略了try()

<script>
export default {
  name: 'demo',
  data() {
    return {}
  },
  methods: {
    testDemo(data) {
      // ajax请求
      testAjax(url, params).then(data => {
        // 处理成功
        console.log(data)
      }).catch(err => {
        // 报错
        console.log(err)
      })
    }
  }
}
</script>

    3、主要区别:如果在then的第一个函数里抛出了异常,后面的catch能捕获到,而then的第二个函数捕获不到。因此,建议总是使用catch方法,而不使用then方法的第二个参数。

22.请求拦截器和响应拦截器

请求拦截器的作用:

修改请求配置:您可以在请求拦截器中修改请求的URL、headers、请求体等配置信息。例如,您可以为每个请求添加身份验证令牌、设置默认的Content-Type等。
请求错误处理:您可以在请求拦截器中检查请求是否满足某些条件,如果不满足,则可以中止请求、重定向或执行其他逻辑。这样可以统一处理请求异常情况。
加载指示器:您可以在请求拦截器中添加加载指示器,以通知用户请求正在进行中,例如显示一个加载动画或进度条。
请求重试:如果遇到请求失败的情况,例如网络错误,您可以在请求拦截器中实现请求重试的逻辑

// 请求拦截器
 instance.interceptors.request.use( config=> {
 	 // config 前端  访问后端的时候  参数

	  config.headers['Authorization']="yyl"
     return config;
   }, error=> {
     // 超出 2xx 范围的状态码都会触发该函数。
     // 对响应错误做点什么
     return Promise.reject(error);
   });

响应拦截器的作用:

全局错误处理:您可以在响应拦截器中捕获所有的响应,并根据不同的响应状态码进行全局错误处理。例如,您可以统一处理401未授权错误、404未找到错误等。
响应数据处理:您可以在响应拦截器中修改响应数据,例如解析、格式化或转换响应数据,以便在应用程序的其他部分使用。
加载指示器:您可以在响应拦截器中隐藏加载指示器,以通知用户请求已完成。例如,隐藏加载动画或进度条,并显示响应的内容。

// 添加响应拦截器
instance.interceptors.response.use( response=> {
   //状态码500
   if(response.data.code==500){
   		// 跳转到login组件里面
   		myrouter.push({path:"/login"});
   		return;
   }
    // return response.data.t;
    // 在Home中  this.tableData = response.data.t;去掉.data.t使用上面的那个
    return response;
   
},  error=> {
    // 超出 2xx 范围的状态码都会触发该函数。
    // 对响应错误做点什么
    return Promise.reject(error);
});

23.async await

async 是异步的意思,await则可以理解为 async wait。所以可以理解async就是用来声明一个异步方法,而 await是用来等待异步方法执行
async作为一个关键字放在函数前面,表示该函数是一个异步函数,异步函数意味着该函数的执行不会阻塞后面代码的执行;而 await 用于等待一个异步方法执行完成;
await 等待一个 Promise 对象,如果 Promise的状态变成了 resolve 或者 rejcet,那么 async函数会恢复执行。并会阻塞该函数内后面的代码。
使用 async/await 可以实现用同步代码的风格来编写异步代码,这是因为 async/await 的基础技术使用了生成器和 Promise,生成器是协程的实现,利用生成器能实现生成器函数的暂停和恢复。
为了优化 .then 链而开发出来的。

1. async关键字

async关键字用于声明一个异步函数,这个函数返回一个Promise对象。在函数内部可以使用await关键字来等待异步操作完成

async function getData() {
  const response = await fetch('https://api.example.com/data');
  const data = await response.json();
  return data;
}

在上面的代码中,我们声明了一个异步函数`getData()`,使用await关键字等待了fetch方法返回的Promise对象,然后使用await关键字等待了response.json()方法返回的Promise对象,最后返回了获取到的数据。

2. await关键字

await关键字用于等待一个异步操作完成,它只能在异步函数中使用。当执行到await关键字时,程序会暂停执行,直到异步操作完成并返回结果。

async function getData() {
  const response = await fetch('https://api.example.com/data');
  const data = await response.json();
  console.log(data);
}

在上面的代码中,当执行到第一行的await关键字时,程序会暂停执行,直到fetch方法返回的Promise对象被解决,并返回一个response对象。然后再执行第二行的await关键字,等待response.json()方法返回的Promise对象被解决,并返回一个包含解决值的data对象。最后打印出获取到的数据。

需要注意的是,在使用await关键字时,其后面必须是一个返回Promise对象的异步操作,否则就会抛出错误。同时,在使用await关键字时,建议将其放在try-catch语句中进行错误处理,以便捕获可能发生的错误。
 

24.store对象的四个属性

1.State

Vuex的作用类似全局对象,Vuex 使用单一状态树,用一个对象State包含了整个应用层级的所有状态,你可以理解为这些状态就是一堆全局变量和数据。
比如在下面的Store对象里面就给state属性里面添加了一个count变量

 //创建一个 store
 const store = new Vuex.Store({
    //state存储应用层的状态
    state:{
        count:5  //总数:5
    }
 });

2.Mutations

Vuex给我们提供修改仓库 store中的状态的唯一办法就是通过提交mutation

我们在 mutations中定义了一个叫increment的函数,函数体就是我们要进行更改的地方

会接受 state作为第一个参数,第二个是自定义传参

 const store = new Vuex.Store({
    //state存储应用层的状态
    state:{
        count:5  //总数:5
    },
    mutations:{
        increment(state,value){
            state.count += value;
        }
    }
 });
 const store = new Vuex.Store({
    //state存储应用层的状态
    state:{
        count:5  //总数:5
    },
    mutations:{
        increment(state,value){
            state.count += value;
        }
    }
 });

当我们在其他组件里面想要调用store对象里的mutations里的函数的时候,如下面的代码所示
我们在提交commit时候,第一个参数传的increment,就是对应在 mutations中的increment。
一般通过方法或钩子触发,例如:

 methods: {
   getVal(event) {
     //获取当前的按键的值
     let value = event.target.dataset.value;
     //通过commit提交一个名为increment的mutation
     this.$store.commit("increment", value);
   }
 }

如果要在其他组件中获取store里的count变量的值,采用{{count}}方式:

export default {
  computed: {
      count(){
          return this.$store.state.count;
      }
  }
};  

3.Getters:
可以认为,getters 是store的计算属性,类似于computed,对state里的数据进行一些过滤,改造等等

假设我们要在state.count的基础上派生出一个新的状态newCount出来,就适合使用我们的 getters
getters 接受 state 作为其第一个参数,举例如下:

 const store = new Vuex.Store({
   //state存储应用层的状态
   state:{
      count:5  //总数:5
   },
   getters:{
      newCount:state => state.count * 3
   }
 });

这样的话,我们在其他组件中可以使用到这个新的变量了,如下所示
,先在其他组件中使用下面的代码导出newCount变量,然后通过{{newCount}}使用即可

export default {
  computed: {
      newCount(){
          return this.$store.getters.newCount;
      }
  }
};  

4.action:

用来解决异步流程来改变state数据。
而matution是直接进行同步操作的,如果你在mutations里进行异步操作,你会发现没用,并不会起任何效果
只有通过action=>mutations=>states,这个流程进行操作,具体步骤如下:

export default new Vuex.Store({
  //存放数据
  state: {
    obj: {}, 
  },
  //4.通过commit mutations中的方法来处理
  mutations: {
    getParam (state,Object) {
	   //5.修改state中的数据
       state.obj= Object
    }
  },
  //2.接受dispatch传递过来的方法和参数
  actions: {//我们直接把下面的context当成是上面的mutations属性即可
    getParamSync (context,Object) {
	    //处理异步操作
        setTimeout(()=>{
	        //3.通过commit提交一个名为getParam的mutation
//action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation
            context.commit('getParam',Object)
        },3000)
    }
  }
})
 methods: {
   getVal() {
	  let name= 'xia';
	  let age= '26';
	  let sex= 'man';
	  //1.通过dispatch将方法getParamSync和多个参数{name,age,sex}传递给actions
	  this.$store.dispatch('getParamSync',{name,age,sex})
   }
 }

25.fields

概念: 在Java类中,字段(Fields)是用于存储对象的状态的变量。它们描述了对象的特征或属性。字段可以是基本数据类型(如整数、字符、布尔值等)或其他类的对象。通过定义字段,类可以持有和操作对象的数据

Java中的字段可以按照以下两个方面进行分类:

实例字段(Instance Fields):每个对象都有自己的实例字段副本,用于存储对象特定的状态和属性。

静态字段(Static Fields):静态字段属于类本身,被该类的所有实例共享,用于存储类级别的共享数据。

功能: 字段在类中具有重要的功能。它们允许类存储和表示对象的状态。通过字段,我们可以记录对象的特定信息,例如名称、年龄、大小等。字段还可以作为对象之间传递数据的一种方式,使得对象可以在不同方法中共享数据。

特点:

变量:字段是一种变量,用于存储数据。它们可以在类的任何方法中使用,并在对象的整个生命周期中保持存在。

访问控制:字段可以具有不同的访问修饰符(如public、private、protected、default等),以控制对字段的访问权限。这有助于维护数据的封装性和安全性。

对象状态:字段用于描述和记录对象的状态。通过修改字段的值,我们可以改变对象的状态,从而影响对象的行为和属性。

类级别:静态字段属于类本身,可以在不创建对象的情况下访问。它们被类的所有实例所共享。

public class Person {
    // 实例字段
    private String name;
    private int age;
 
    // 静态字段
    public static String country = "未知";
 
    // 构造方法
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
 
    // 实例方法
    public void sayHello() {
        System.out.println("你好,我叫" + name + ",今年" + age + "岁。");
    }
 
    // 静态方法
    public static void changeCountry(String newCountry) {
        country = newCountry;
    }
 
    public static void main(String[] args) {
        // 创建Person对象并访问字段和方法
        Person person1 = new Person("张三", 25);
        person1.sayHello();  // 输出: 你好,我叫张三,今年25岁。
 
        Person person2 = new Person("李四", 30);
        person2.sayHello();  // 输出: 你好,我叫李四,今年30岁。
 
        System.out.println("当前国家:" + Person.country);  // 输出: 当前国家:未知
 
        Person.changeCountry("中国");
        System.out.println("更新后的国家:" + Person.country);  // 输出: 更新后的国家:中国
    }
}

26.computed与watch异同

computed与watch的异同


不同点
触发条件不同
  computed计算属性会依赖于使用它的data属性,只要是依赖的data属性值有变动,则自定义重新调用计算属性执行一次。

  watch则是在监控的data属性值发生变动时,其会自动调用watch回调函数。

执行速度不同
  computed计算属性的值是直接从缓存中获取,而不是重新编译执行一次,因而其性能要高一些,尤其是在data属性中的值无变化,而重复调用computed回调函数时更是如此,所以说在Vue中,应该尽可能的多使用computed替代watch。

  watch中的值需要data属性重新编译执行,因而其性能方面会有所损失。

使用方式不同
  computed计算属性的回调函数方法可以直接在页面中通过插值表达式——{{}}来获取。此时我们不需要再data数据域中再定义一个与方法名相同的属性。

  watch中的方法名必须是data数据域中所存在的,否则无法使用。

相同点
  都可以实现通过监控data数据域中属性值的变化来触发相应的回调函数,进而实现我们特殊的逻辑业务处理功能。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue-router</title>
</head>
<body>
<div id="app">
    <input type="text" v-model="lastName" placeholder="姓">
    <input type="text" v-model="firstName" placeholder="名">
    <h2>拼接:{{fullName}}</h2>
</div>
</body>
<script src="../../../js/vue/vue/2.0/vue.js"></script>
<script src="../../../js/vue/vue-router/2.3.1/vue-router.js"></script>
<script type="application/javascript">
    new Vue({
        el:'#app'
        ,data:{
            firstName:''
            ,lastName:''
        }
        ,computed:{
            fullName:function () {
                return this.lastName + '·' + this.firstName;
            }
        }
    });
</script>
</html>

27.mobx中的computed和reactions

MobX是一个简单、可扩展的状态管理库,它通过透明的函数响应式编程(TFRP)实现了响应式应用程序。MobX背后的核心思想是任何源自应用状态的东西都应该自动地得到任何以来于此状态的数据。这使得应用状态更易于管理和维护。

MobX主要围绕着以下几个基本概念展开:

  • Observables:可观察的数据,任何需要被观察的数据都应该通过MobX的observable函数进行声明。
  • Computed Values:由一个或多个observable值计算得到的值,能够自动地在相关observable数据变化时更新。
  • Reactions:对observable数据变化做出响应的机制,可以是副作用或者基于响应的输出。
  • Actions:更改状态的行为,确保状态的改变是可追溯的。

在MobX中,核心概念主要有三个:可观察的数据(Observables)、计算值(Computed Values)、Reactions。这三者形成了MobX的基本运行机制,通过对数据的观察和响应实现了状态的自动管理和更新。

Computed属性的概念

在MobX中,Computed属性是指根据现有的状态数据衍生出的新数据。Computed属性的值可以根据当前的状态数据自动计算得出,并且在状态数据变化时自动更新。

Computed属性的应用场景

Computed属性常用于根据一些状态数据计算出衍生的数据,例如根据购物车中的商品列表计算出总价,或者根据用户的筛选条件对商品列表进行过滤等。

Computed属性的定义方式

在MobX中,可以使用@computed装饰器或computed函数来定义Computed属性。例如,在JavaScript中可以这样定义一个Computed属性:

import { observable, computed } from 'mobx';
class ShoppingCart { 
 @observable items = []; 

 @computed get total() { 
   return this.items.reduce((total, item) =&gt; total + item.price, 0);

  }}

Reactions可以根据观察的数据自动运行,并在数据发生变化时进行相应的处理。Reactions具有以下特点:

  • 自动运行:不需要手动调用,当观察的数据发生变化时会自动执行。
  • 精确追踪:只有当观察的数据被访问时,Reactions才会自动跟踪这些数据,并在数据变化时执行相关逻辑,以确保不会浪费性能。
  • 可控制的副作用:Reactions可以创建各种副作用,但在设计良好的应用程序中,副作用应该是可控制和可预测的。

autorun函数

在MobX中,autorun是创建Reactions的一种方式。它会自动运行传入的函数,并追踪函数中所访问的可观察数据,当这些可观察数据发生变化时,autorun会重新运行传入的函数。例如,在以下示例中,autorun会自动追踪和输出count的值。

import mobx
from mobx import autorun
count = mobx.observable(0)
def print_count():   
 print("Count is:", count.get())
reaction = autorun(print_count)
count.set(5) # 这里会触发 autorun 输出 'Count is: 5'

28.token含义及用法

含义:作为计算机术语时,是“令牌”的意思。Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。

token其实说的更通俗点可以叫暗号,在一些数据传输之前,要先进行暗号的核对,不同的暗号被授权不同的数据操作。说白了token是一个身份卡,有权限的作用。例如在USB1.1协议中定义了4类数据包:token包、data包、handshake包和special包。主机和USB设备之间连续数据的交换可以分为三个阶段,第一个阶段由主机发送token包,不同的token包内容不一样(暗号不一样)可以告诉设备做不同的工作,第二个阶段发送data包,第三个阶段由设备返回一个handshake包。

使用:

使用token机制的身份验证方法,在服务器端不需要存储用户的登录记录。

大概的流程:

1️⃣客户端使用用户名和密码请求登录。

2️⃣服务端收到请求,验证用户名和密码。

3️⃣验证成功后,服务端会生成一个token,然后把这个token发送给客户端。

4️⃣客户端收到token后把它存储起来,可以放在cookie或者Local Storage(本地存储)里。

5️⃣客户端每次向服务端发送请求的时候都需要带上服务端发给的token。

6️⃣服务端收到请求,然后去验证客户端请求里面带着token,如果验证成功,就向客户端返回请求的数据。

29.param

 首先明确这个注解是为SQL语句中参数赋值而服务的。

      @Param的作用就是给参数命名,比如在mapper里面某方法A(int id),当添加注解后A(@Param("userId") int id),也就是说外部想要取出传入的id值,只需要取它的参数名userId就可以了。将参数值传如SQL语句中,通过#{userId}进行取值给SQL的参数赋值

mapper中的方法:

public User selectUser(@Param("userName") String name,@Param("password") String pwd);

  映射到xml中的<select>标签

<select id="selectUser" resultMap="User">  
   select * from user  where user_name = #{userName} and user_password=#{password}  
</select>

    其中where user_name = #{userName} and user_password = #{password}中的userName和password都是从注解@Param()里面取出来的,取出来的值就是方法中形式参数 String name 和 String pwd的值

30.actions

actions其实也很简单,我们都知道在想要修改state中的数据,必须要通过mutations,但是mutations是同步的,只能执行同步代码,这显然不能满足所有需求,而actions就是异步的提交mutations,它的作用也是用来修改state的,但是不是直接修改,因为修改state中数据的方法有且只有通过mutations。

mutations和actions都是用来修改state的,只是前者是同步修改,后者是异步修改。

在JavaScript程序中最直接、最常见的异步操作就是Ajax。

我们先npm install axios --save安装一下axios。

Ajax的作用是请求后端的数据,那么我们首先要创建一个后端服务,我这里使用nodejs

const http = require('http');

http.createServer((req, res) => {
    res.setHeader('Access-Control-Allow-Origin', '*')
    res.end(JSON.stringify([
        'data1',
        'data2',
        'data3'
    ]))
}).listen('9999',() => {
    console.log('server running!!!');
})

store/index.js中,我们要先 import axios from 'axios'引入一下axios

然后在actions属性下写入以下内容:

  actions: {
    getData (ctx) {
      axios.get('http://localhost:9999').then((res) => {
        console.log(res);
      })
    }
  }

我们先不修改state的值,只是简单输出一下获取到的后端数据。

actions的内容编写好之后,我们如何调用它呢?

我们再新建一个Part2组件

<template>
    <div>
    
    </div>
</template>

<script>
    export default {
        name: 'MyPart2',
        mounted() {
            this.$store.dispatch('getData');
        }
    }
</script>

调用actions的方式之一就是this.$store.dispatch('方法名')

经过实际测试,我们可以正常获取到后端的值。

那么接下来的要做的就是通过actions提交mutations来修改state中的数据。

方式也很简单,我们在写actions中的方法时,会获得一个默认参数,就是当前的环境上下文ctx,里面就有commit方法

  actions: {
    getData (ctx) {
      axios.get('http://localhost:9999').then((res) => {
        console.log(res);
        ctx.commit('setData', res.data);
      })
    }
  }
  state: {
    curIdx: 0,
    name: 'Ray',
    age: '21',
    data: []
  },
  mutations: {
    setCurIdx (state, index) {
      state.curIdx = index;
    },
    setData (state, data) {
      state.data = data
    }
  },

完成了这一系列操作之后,我们可以直接获取一下state中的data,看看是否正确。

<template>
    <div>
        Data: {{data}}
    </div>
</template>

<script>
import { mapState } from 'vuex';
    export default {
        name: 'MyPart2',
        mounted() {
            this.$store.dispatch('getData');
        },
        computed: {
            ...mapState(['data'])
        }
    }
</script>

31.miniprogram-computed安装步骤

安装

npm install --save miniprogram-computed

computed 基本用法

const computedBehavior = require("miniprogram-computed").behavior;

Component({
  behaviors: [computedBehavior],

  data: {
    a: 1,
    b: 1,
  },

  computed: {
    sum(data) {
      // 注意: computed 函数中不能访问 this ,只有 data 对象可供访问
      // 这个函数的返回值会被设置到 this.data.sum 字段中
      return data.a + data.b;
    },
  },

  methods: {
    onTap() {
      this.setData({
        a: this.data.b,
        b: this.data.a + this.data.b,
      });
    },
  },
});

watch 基本用法

const computedBehavior = require("miniprogram-computed").behavior;

Component({
  behaviors: [computedBehavior],

  data: {
    a: 1,
    b: 1,
    sum: 2,
  },

  watch: {
    "a, b": function (a, b) {
      this.setData({
        sum: a + b,
      });
    },
  },

  methods: {
    onTap() {
      this.setData({
        a: this.data.b,
        b: this.data.a + this.data.b,
      });
    },
  },
});

32.wx.request网络请求

小程序大多数 API 都是异步 API, wx.request()wx.login() 。这类 API 接口通常都接收一个 Object 对象类型的参数,参数中可以按需指定以下字段来接收接口调用结果:

wx.request({
  // 接口调用成功的回调函数
  success() {
    wx.request({
      success() {
        wx.request({
          success() {
            wx.request({
              success() {
                wx.request({
                  success() {
                    wx.request({
                      success() {
                        wx.request({
                          success() {
                            wx.request({
                              success() {}
                            })
                          }
                        })
                      }
                    })
                  }
                })
              }
            })
          }
        })
      }
    })
  },

  // 接口调用失败的回调函数
  fail() {},

  // 接口调用结束的回调函数(调用成功、失败都会执行)
  complete() {}
})

如果采用这种回调函数的方法接收返回的值,可能会出现多层 success 套用的情况,容易出现回调地狱问题,

为了解决这个问题,小程序基础库从 2.10.2 版本起,异步 API 支持 callback & promise 两种调用方式。

当接口参数 Object 对象中不包含 success/fail/complete 时,将默认返回 promise,否则仍按回调方式执行,无返回值。

但是部分接口如 downloadFile, request, uploadFile 等本身就有返回值,因此不支持 promise 调用方式,它们的 promisify 需要开发者自行封装。

Axios 是我们日常开发中常用的一个基于 promise 的网络请求库

我们可以参考 Axios 的 [使用方式] 来封装自己的网络请求模块,咱们看一下使用的方式:

import WxRequest from 'mina-request'

// 自定义配置新建一个实例
const instance = new WxRequest(({
  baseURL: 'https://some-domain.com/api/',
  timeout: 1000,
  headers: {'X-Custom-Header': 'foobar'}
})


// 通过 instance.request(config) 方式发起网络请求
instance.requst({
  method: 'post',
  url: '/user/12345',
  data: {
    firstName: 'Fred',
    lastName: 'Flintstone'
  }
})

// 通过 instance.get 方式发起网络请求
instance.get(url, data, config)

// 通过 instance.delete 方式发起网络请求
instance.delete(url, data, config)

// 通过 instance.post 方式发起网络请求
instance.post(url, data, config)

// 通过 instance.put 方式发起网络请求
instance.put(url, data, config)


// ----------------------------------------------


// 添加请求拦截器
instance.interceptors.request = (config) => {

  // 在发送请求之前做些什么
  return config
}

// 添加响应拦截器
instance.interceptors.response = (response) => {

  // response.isSuccess = true,代码执行了 wx.request 的 success 回调函数
  // response.isSuccess = false,代码执行了 wx.request 的 fail 回调函数
    
  // response.statusCode // http 响应状态码
    
  // response.config // 网络请求请求参数
    
  // response.data 服务器响应的真正数据
    
  // 对响应数据做点什么
  return response
}

封装后网络请求模块包含以下功能

1.包含 request 实例方法发送请求
2.包含 get、delete、put、post 等实例方法可以快捷的发送网络请求
3包含 请求拦截器、响应拦截器
4.包含 uploadFile 将本地资源上传到服务器 API
5.包含 all 并发请求方法
同时优化了并发请求时 loading 显示效果

33. observable 函数

在Vue中,observable是一个函数,它可以将一个普通的JavaScript对象或数组转换为可观察对象,使其具有响应式的特性。

要使用observable,首先需要从Vue的官方包中导入它:

import { observable } from 'vue';

现在,data对象的foo属性是可观察的,任何对它的修改都会被自动追踪并触发相应的更新。这意味着当foo的值发生改变时,Vue将自动重新渲染相关的组件。示例:

data.foo = 'baz';

在组件中使用可观察对象时,可以将其作为响应式数据的来源,例如:

export default {
  data() {
    return {
      myData: data
    };
  }
};

然后,可以在模板或计算属性中使用myData.foo来访问和更改可观察对象的属性。

需要注意的是,observable函数只能在Vue 3.x版本中使用。在Vue 2.x版本中,可以使用Vue.observable方法来实现类似的功能。

34.LBS逆地址解析

LBS逆地址解析,又称为逆地理编码或地址反查,是一种将经纬度坐标转换为具体地理位置信息(如街道、城市、建筑物等)的技术。以下是关于LBS逆地址解析的详细解释:

  1. 定义与原理
    • LBS逆地址解析是将经纬度坐标转换为对应地理位置信息的过程。
    • 原理是通过将经纬度坐标与地图服务提供商(如高德、百度、腾讯等)的地理数据进行匹配,从而确定该坐标所在的具体位置信息。
  2. 应用场景
    • 逆地址解析在多个领域有广泛应用,包括:
      • 定位服务:在移动设备应用中,根据用户的经纬度坐标提供准确的地理位置信息。
      • 位置导航:在导航系统中,通过逆地址解析将用户的经纬度坐标转换为具体的道路和地点信息,以便提供准确的导航服务。
      • 社交网络:在社交媒体应用中,用户可以分享自己的位置信息,通过逆地址解析将经纬度坐标转换为可读的地理位置信息,方便其他用户理解。
      • 电子商务:在电商应用中,根据用户的地理位置信息推荐附近的商家或商品,提高购物的便捷性。
  3. 技术实现
    • 地图服务提供商(如高德、百度、腾讯等)提供了逆地址解析的API接口,开发者可以通过调用这些接口实现经纬度坐标到地理位置信息的转换。
    • 逆地址解析的精度取决于地图服务提供商的地理数据质量和算法模型。一般来说,地图服务提供商会不断更新和优化其地理数据和算法模型,以提高逆地址解析的精度和可靠性。
  4. 优势与特点
    • 逆地址解析技术具有高精度、高可靠性和高效性等优点。
    • 地图服务提供商拥有大量的地理数据资源和算法模型,可以快速、准确地将经纬度坐标转换为地理位置信息。
    • 同时,逆地址解析技术还支持多种查询方式和查询参数,可以根据具体需求进行灵活配置和定制。
  5. 使用注意事项
    • 在使用逆地址解析技术时,需要注意保护用户隐私和数据安全。
    • 同时,需要遵守相关法律法规和规定,确保数据的合法性和合规性。

综上所述,LBS逆地址解析是一种重要的位置服务技术,可以为各种应用场景提供准确、可靠的位置信息服务。

35.async-validator

async-validator 是一个用于异步数据验证的库,主要用于表单验证等场景。以下是关于 async-validator 的详细解释:

1. 概述

  • async-validator 是一个支持异步验证的表单验证库。
  • 它不仅支持基础的同步验证规则,如必填项、长度限制等,还支持自定义的异步验证函数,如检查用户名是否已存在等。
  • Ant Design 和 Element UI 等前端框架的表单组件都使用了 async-validator 进行数据验证。

2. 基础用法

  • 定义验证规则:通过定义一个对象(通常称为 descriptor 或 schema)来描述验证规则。每个字段可以对应一个或多个验证规则。

 

javascript复制代码

const descriptor = {
username: [
{ required: true, message: '请填写用户名' },
{ min: 3, max: 10, message: '用户名长度为3-10' }
]
};
  • 创建验证器:使用定义的验证规则创建一个验证器对象。

 

javascript复制代码

import AsyncValidator from 'async-validator';
const validator = new AsyncValidator(descriptor);
  • 验证数据:调用验证器的 validate 方法来验证数据。

 

javascript复制代码

const data = { username: 'username' };
validator.validate(data, (errors, fields) => {
if (errors) {
console.log('验证不通过', errors, fields);
} else {
console.log('验证通过');
}
});

3. 自定义异步验证

  • 当内置的验证规则无法满足需求时,可以编写自定义的异步验证函数。

  • 自定义异步验证函数接受三个参数:rule(验证规则对象)、value(要验证的值)和 callback(处理验证结果的回调函数)。

 

javascript复制代码

const descriptor = {
userName: {
asyncValidator(rule, value, callback) {
// 模拟异步操作,例如网络请求
const isUsernameExists = await checkUsernameExists(value);
if (isUsernameExists) {
callback('该用户名已存在');
} else {
callback(); // 验证通过时不传入错误信息
}
}
}
};
// 模拟的异步操作函数,检查用户名是否存在
async function checkUsernameExists(username) {
// 在这里进行实际的检查逻辑,例如查询数据库或调用API
// 这里只是模拟返回一个结果
return true; // 假设用户名已存在
}

4. 其他特性

  • async-validator 还支持其他特性,如验证前的数据转换、错误提示信息的自定义等。
  • 验证规则可以是对象、函数或数组,提供了丰富的验证选项和灵活性。

5. 总结

async-validator 是一个功能强大的异步验证库,适用于各种表单验证场景。通过定义验证规则和创建验证器对象,可以方便地对数据进行验证,并支持自定义的异步验证函数来满足复杂的需求。

36.SwipeCell自动收起

SwipeCell自动收起的功能通常是在滑动单元格(swipe-cell)组件中实现的,用于在用户操作完成后自动关闭或收起滑动显示的区域。以下是根据参考文章提供的信息,关于SwipeCell自动收起功能的详细解释和归纳:

1. 触发机制

  • 异步关闭(async-close):当SwipeCell组件配置为async-close时,允许通过绑定close事件来实现自定义的关闭行为。这通常意味着在滑动内容被点击或用户执行了其他操作后,可以触发一个异步操作来关闭或收起SwipeCell。
  • 事件监听:开发者需要在相应的页面上监听SwipeCell的close事件。当这个事件被触发时,可以执行相应的逻辑来关闭或收起SwipeCell。

2. 编程实现

  • 小程序框架(参考文章2):
    • 使用<mx-swipe-cell>组件,并通过bind:open属性监听打开事件。
    • onOpen方法中,根据事件参数(如positionname)判断是左侧还是右侧滑动内容被展示,并可以执行相应的逻辑。
    • 如果需要自动收起,可以在适当的位置(如滑动内容被点击后)调用instance.close()方法。这里的instance通常是通过某种方式(如页面数据或组件实例)获取的SwipeCell实例。
  • Vue.js框架(参考文章3和4):
    • 使用van-swipe-cell组件,并通过设置right-widthleft-width属性来定义滑动区域的宽度。
    • 如果需要自动收起,可以在滑动内容被点击的处理函数中,通过编程方式触发关闭行为。具体实现可能依赖于你使用的Vue.js版本和框架(如Vue 2.x或Vue 3.x,以及是否使用了Vuex等状态管理库)。

3. 注意事项

  • 确保事件绑定正确:确保你已经正确地在页面上绑定了close事件,并且事件处理函数能够正确执行。
  • 处理异步操作:如果关闭行为涉及到异步操作(如网络请求),需要确保在异步操作完成后才关闭SwipeCell,以避免界面闪烁或不一致的状态。
  • 兼容性和性能:在不同的设备和浏览器上测试SwipeCell的自动收起功能,以确保良好的兼容性和性能。

4. 示例代码(小程序框架)

 

xml复制代码

<mx-swipe-cell id="swipe-cell" bind:close="onClose">
<!-- 滑动内容 -->
</mx-swipe-cell>
 

javascript复制代码

Page({
onClose(event) {
// 执行关闭逻辑,如调用instance.close()方法
},
// 其他页面逻辑...
});

请注意,上述示例代码是基于假设的,并且可能需要根据你实际使用的框架和组件库进行调整。

37.微信小程序节流阀

微信小程序中的“节流阀”技术通常指的是“函数节流”(throttle)的应用,它是一种编程策略,用于限制某个函数在一段时间内的执行频率。在微信小程序中,这尤其对于处理如页面滚动、窗口大小调整等高频触发的事件非常有用,可以有效避免资源的过度消耗和不必要的性能问题。

以下是关于微信小程序中函数节流的具体解释和应用:

1. 函数节流的概念

  • 函数节流(throttle)是指单位时间n秒内,第一次触发函数并执行,以后n秒内不管触发多少次,都不执行。直到下一个单位时间n秒,第一次触发函数并执行,这个n秒内不管函数多少次都不执行。
  • 它与函数防抖(debounce)不同,防抖是n秒后延迟执行;而节流是立马执行,n秒后再立马执行。

2. 函数节流的应用场景

  • 页面滚动(scroll)事件:当用户快速滚动页面时,可能会触发大量的scroll事件,使用节流可以避免频繁执行与滚动相关的函数。
  • 窗口大小调整(resize)事件:当窗口大小频繁变化时,可以使用节流来限制相关函数的执行频率。
  • 防止按钮重复点击:在用户连续点击按钮时,通过节流可以避免在短时间内多次触发点击事件。

3. 实现函数节流的方法

在微信小程序中,可以通过编写自定义的节流函数来实现这一功能。以下是一个简单的节流函数示例:

 

javascript复制代码

function throttle(fn, interval) {
var enterTime = 0; // 上次触发的时间
var gapTime = interval || 300; // 间隔时间,默认为300ms
return function() {
var context = this;
var backTime = new Date(); // 当前时间
if (backTime - enterTime > gapTime) {
fn.apply(context, arguments);
enterTime = backTime;
}
};
}

4. 在微信小程序中使用节流函数

假设你有一个页面滚动时触发的函数handleScroll,你可以使用节流函数来限制其执行频率:

 

javascript复制代码

Page({
data: {
// 页面数据
},
// 原始滚动处理函数
handleScroll: function(e) {
// 处理滚动事件的逻辑
},
// 使用节流函数包装后的滚动处理函数
throttledHandleScroll: throttle(this.handleScroll, 300), // 设置节流间隔为300ms
// 页面相关事件处理函数
onPageScroll: function(e) {
this.throttledHandleScroll(e); // 调用节流后的函数
},
// 其他页面逻辑...
});

5. 注意事项

  • 在使用节流函数时,需要注意其可能带来的延迟效果,即事件可能在n秒后才得到处理。因此,在设计应用时要充分考虑这一点。
  • 另外,由于节流函数需要存储上一次触发的时间,因此在使用闭包或类的方法时,需要注意其作用域和生命周期问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值