Loading... 这周主要学习的是一个小的通讯录API调用项目练习,主要学习JQuery、Axios、Ajax、Promise、Async、BootstrapValidator、MUI V3等前端组件的综合使用以及理解前端调用后端数据渲染到前端的过程。 另外再学习了些有关于JavaScript性能优化、函数式编程有关的内容。 # JavaScript ## Cookie 在JavaScript中,可以使用document.cookie来获取所有的cookie,这将返回一个由分号空格(; )分隔的cookie键值对字符串。 ```JavaScript console.log(document.cookie); ``` 在项目当中一般是封装cookie各种操作函数的JS来进行对cookie的增删改查以及调用操作。 一个简易的cookie.js: ```JavaScript /* * HTTP Cookie:存储会话信息 * 名称和值传送时必须是经过RUL编码的 * cookie绑定在指定的域名下,非本域无法共享cookie,但是可以是在主站共享cookie给子站 * cookie有一些限制:比如IE6 & IE6- 限定在20个;IE7 50个;Opear 30个...所以一般会根据【必须】需求才设定cookie * cookie的名称不分大小写;同时建议将cookie URL编码;路径是区分cookie在不同情况下传递的好方式;带安全标志cookie * 在SSL情况下发送到服务器端,http则不会。建议针对cookie设置expires、domain、 path;每个cookie小于4KB * */ //对cookie的封装,采取getter、setter方式 (function(global){ //获取cookie对象,以对象表示 function getCookiesObj(){ var cookies = {}; if(document.cookie){ var objs = document.cookie.split('; '); for(var i in objs){ var index = objs[i].indexOf('='), name = objs[i].substr(0, index), value = objs[i].substr(index + 1, objs[i].length); cookies[name] = value; } } return cookies; } //设置cookie function set(name, value, opts){ //opts maxAge, path, domain, secure if(name && value){ // var cookie = encodeURIComponent(name) + '=' + encodeURIComponent(value); var cookie = name + '=' + value; //可选参数 if(opts){ if(opts.maxAge){ cookie += '; max-age=' + opts.maxAge; } if(opts.path){ cookie += '; path=' + opts.path; } if(opts.domain){ cookie += '; domain=' + opts.domain; } if(opts.secure){ cookie += '; secure'; } } document.cookie = cookie; return cookie; }else{ return ''; } } //获取cookie function get(name){ return getCookiesObj()[name] || null; } //清除某个cookie function remove(name){ if(getCookiesObj()[name]){ document.cookie = name + '=; max-age=0'; } } //清除所有cookie function clear(){ var cookies = getCookiesObj(); for(var key in cookies){ document.cookie = key + '=; max-age=0'; } } //获取所有cookies function getCookies(name){ return getCookiesObj(); } //解决冲突 function noConflict(name){ if(name && typeof name === 'string'){ if(name && window['cookie']){ window[name] = window['cookie']; delete window['cookie']; return window[name]; } }else{ return window['cookie']; delete window['cookie']; } } global['cookie'] = { 'getCookies': getCookies, 'set': set, 'get': get, 'remove': remove, 'clear': clear, 'noConflict': noConflict }; })(window); ``` 这样就可以在页面当中通过: ```JavaScript let business = cookie.get('business') ? JSON.parse(cookie.get('business')) : {} ``` 获取cookie当中的business内容啦 ## MUI MUI是一套基于HTML5的移动端前端框架,全称是Mobile UI。MUI主要提供了一套常见的移动端UI组件。 通过尽可能简单的HTML,就能创建出高度优化的移动应用。MUI的设计理念是尽量贴近原生的体验,所以在动画上,MUI采用了很多原生动画,比如页面切换动画,列表点击涟漪效果等。 [MUI V3文档地址](https://v3.mui.com/getting-started/installation/) ## Axios Axios 是一个基于 Promise 的 HTTP 客户端,用于浏览器和 Node.js 中。支持 Promise API、拦截请求和响应、转换请求和响应数据、取消请求、自动转换 JSON 数据等。 Example: ```javascript // 发送 GET 请求 axios.get('https://api.example.com/items') .then(response => { console.log(response.data); }) .catch(error => { console.log(error); }); // 发送 POST 请求 axios.post('https://api.example.com/items', { itemName: 'Item name', itemDescription: 'This is an item.' }) .then(response => { console.log(response.data); }) .catch(error => { console.log(error); }); // 使用 async/await 发送请求 async function getItem() { try { const response = await axios.get('http://jsapi.example.com/items'); console.log(response.data); } catch (error) { console.error(error); } } getItem(); ``` 使用Axios封装个request.js来方便后续的GET、POST、UPLOAD之类的操作: ```JavaScript let cancel, promiseArr = {} const CancelToken = axios.CancelToken; //设置axios 携带cookie信息 axios.defaults.withCredentials = true //请求拦截器 axios.interceptors.request.use(config => { //发起请求时,取消掉当前正在进行的相同请求 if (promiseArr[config.url]) { promiseArr[config.url]('操作取消') promiseArr[config.url] = cancel } else { promiseArr[config.url] = cancel } return config }, error => { return Promise.reject(error) }) //响应拦截器即异常处理 axios.interceptors.response.use( response => { // return response return response.data }, err => { if (err && err.response) { switch (err.response.status) { case 400: err.message = '错误请求' break; case 401: err.message = '未授权,请重新登录' break; case 403: err.message = '拒绝访问' break; case 404: err.message = '请求错误,未找到该资源' break; case 405: err.message = '请求方法未允许' break; case 408: err.message = '请求超时' break; case 500: err.message = '服务器端出错' break; case 501: err.message = '网络未实现' break; case 502: err.message = '网络错误' break; case 503: err.message = '服务不可用' break; case 504: err.message = '网络超时' break; case 505: err.message = 'http版本不支持该请求' break; default: err.message = `连接错误${err.response.status}` } } else { err.message = "未知错误" } console.error(err.message) return Promise.resolve(err.response) } ) //请求的默认前缀 只要是发出去请求就会 默认带上这个前缀 axios.defaults.baseURL = 'http://jsapi.example.com/source/' //设置默认请求头 异步的 axios.defaults.headers = { 'X-Requested-With': 'XMLHttpRequest', } //设置超时请求时间 axios.defaults.timeout = 10000 //get请求 let GET = (data = {}) => { return new Promise((resolve, reject) => { axios({ method: 'get', url: data.url, params: data.params, cancelToken: new CancelToken(c => { cancel = c }) }).then(res => { resolve(res) }) }) } //post请求 let POST = (data = {}) => { return new Promise((resolve, reject) => { axios({ method: 'post', url: data.url, data: data.params, cancelToken: new CancelToken(c => { cancel = c }) }).then(res => { resolve(res) }) }) } // 文件上传请求 let UPLOAD = (data = {}) => { //封装表单数据对象 var RequestData = new FormData() if (JSON.stringify(data.params) != "{}") { for (var key in data.params) { RequestData.append(key, data.params[key]) } } return new Promise((resolve, reject) => { axios({ method: 'post', url: data.url, data: RequestData, headers: { 'Content-Type': 'multipart/form-data' }, cancelToken: new CancelToken(c => { cancel = c }) }).then(res => { resolve(res) }) }) } ``` ### BootstrapValidator 一款表单验证插件,支持大量的验证规则,可以满足绝大多数的表单验证需求。 Example: ```javascript $(document).ready(function() { $('#divID').bootstrapValidator({ // 配置 }); }); ``` 使用手机号+密码登录验证提交表单: ```JavaScript $('#login').bootstrapValidator({ message: '表单内容不能为空', feedbackIcons: { valid: 'glyphicon glyphicon-ok', invalid: 'glyphicon glyphicon-remove', validating: 'glyphicon glyphicon-refresh' }, fields: { mobile: { message: '手机号验证失败', validating: { notEmpty: { message: '手机号不能为空' }, stringLength: { mix: 11, max: 11, message: '手机号长度为11位' }, regexp: { regexp: /^1[3-9][0-9]{9}$/, message: '手机号码格式有误' } } }, password: { validating: { notEmpty: { message: '请输入密码' } } } } }).on('success.from.bv', (e) => { e.preventDefault() }) ``` 当提交表单的时候验证通过后再提交表单: ```JavaScript $('#login').on('submit', async (e) => { e.preventDefault() if (!$('#login').data('bootstrapValidator').isValid()) { this.data('bootstrapValidator').resetForm() return false } let data = { mobile: $.trim($('#mobile').val()), password: $.trim($('#password').val()) } let result = await POST({ url: 'business/login', params: data }) if (result.code === 1) { mui.toast(result.msg) cookie.set('business', JSON.stringify(result.data)) setTimeout(() => { location.href = 'UserIndex.html' }, 2000) } else { mui.toast(result.msg) $('#login').data('bootstrapValidator').resetForm() } return false }) ``` ## JavaScript性能优化 ### Core Web Vitals Google引入的一组用户体验的度量标准,主要关注三个方面的性能指标:加载性能、交互性能和视觉稳定性。 1. **Largest Contentful Paint (LCP)**:主要内容的加载性能。从页面开始加载到页面主要内容元素(如图片或文本块)渲染完成的时间。**理想的 LCP 时间是2.5秒或更短。** 2. **First Input Delay (FID)**:交互性能。从用户首次交互(如点击链接、点击按钮等)到浏览器开始处理该交互的时间。**理想的 FID 时间是100毫秒或更短。** 3. **Cumulative Layout Shift (CLS)**:视觉稳定性。网页在加载过程中,视觉元素(如图片、按钮、文本等)移动的总距离。**理想的 CLS 分数是0.1或更低。** ### Core Web Vitals Annotations CWV工具等 非公开的笔记 ## 函数式编程 数学函数的求值,并避免改变状态和可变数据。在 JavaScript 中,函数是一等公民,可以被当作参数传递给其他函数,也可以从其他函数中返回。 1. **纯函数**:纯函数是指相同的输入总是得到相同的输出,而且没有任何副作用。 2. **不变性**:在函数式编程中,数据是不可变的。这意味着一旦一个数据结构被创建,就不能再被改变。如果需要修改数据,必须创建一个新的数据结构。 3. **函数组合**:函数组合是把两个或多个函数组合成一个新的函数。这是通过将一个函数的输出作为另一个函数的输入来实现的。 4. **高阶函数**:高阶函数是接受其他函数作为参数或返回一个函数的函数。常见的高阶函数包括 `map`、`filter`、`reduce` 等。 5. **递归**:在函数式编程中,递归是一种常见的控制流方式。因为在函数式编程中,循环是副作用的一种,所以通常使用递归来代替循环。 6. **闭包**:闭包是一个函数和它的词法环境的组合。闭包使得一个函数可以访问到不在它自身作用域内的变量。 Example: 1. **使用纯函数:** ```javascript function add(a, b) { return a + b; } ``` `add`函数就是一个纯函数,对于相同的输入,它总是返回相同的结果,而且它并不会改变外部的任何状态。 2. **使用高阶函数:** ```javascript const array = [1, 2, 3, 4, 5]; const squared = array.map(x => x * x); const even = array.filter(x => x % 2 === 0); const sum = array.reduce((total, x) => total + x, 0); ``` 3. **函数组合:** ```javascript const compose = (f, g) => (x => f(g(x))); const toUpperCase = x => x.toUpperCase(); const exclaim = x => x + '!'; const shout = compose(exclaim, toUpperCase); shout('hello dracowyn'); //=> "HELLO DRACOWYN!"``` ``` Last modification:November 20, 2023 © Reprint prohibited Support Appreciate the author AliPayWeChat Like If you think my article is useful to you, please feel free to appreciate