首页
留言
友情链接
标签页
Search
1
那些顶级不落俗套的“美好祝福”
1,819 阅读
2
如何使用JavaScript获取和设置CSS root变量值
1,277 阅读
3
中国历史朝代顺序图
959 阅读
4
春和 《江海共余生》
892 阅读
5
唐诗三百首1-5
608 阅读
分享
Web前端
html&css
javascript
Vue
shopify
shoplazza
后端
ThinkPHP
YII2
服务器端
软件安装
问题合集
故事
诗词
生活
学习
学科
语文
数学
英语
物理
化学
生物
政治
历史
地理
自然
其他
抖音
快手
小视频
随笔
易经
书摘
今日话题
登录
/
注册
Search
标签搜索
一年级语文
sunshine
累计撰写
170
篇文章
累计收到
15
条评论
首页
栏目
分享
Web前端
html&css
javascript
Vue
shopify
shoplazza
后端
ThinkPHP
YII2
服务器端
软件安装
问题合集
故事
诗词
生活
学习
学科
语文
数学
英语
物理
化学
生物
政治
历史
地理
自然
其他
抖音
快手
小视频
随笔
易经
书摘
今日话题
页面
留言
友情链接
标签页
搜索到
26
篇与
的结果
2023-07-13
Javascript 判断是否移动端
function isMobile() { var ua = navigator.userAgent; var ipad = ua.match(/(iPad).*OS\s([\d_]+)/), isIphone = !ipad && ua.match(/(iPhone\sOS)\s([\d_]+)/), isAndroid = ua.match(/(Android)\s+([\d.]+)/); return isIphone || isAndroid; }
2023年07月13日
258 阅读
0 评论
1 点赞
2023-07-11
Shopify delivery date
Shopify delivery date<div class="sun-delivery"></div> <script> $(function () { const minDays = parseInt({{ block.settings.min_date | default: 0}}); const maxDays = parseInt({{ block.settings.max_date | default: 0 }}); const customText = '{{block.settings.custom_content}}'; const minDate = new Date(Date.now() + (minDays * 86400000)); const maxDate = new Date(Date.now() + (maxDays * 86400000)); const formatDate = (minDate.getFullYear() == maxDate.getFullYear() && minDate.getFullYear() == new Date().getFullYear()) ? new Intl.DateTimeFormat('en', {month: 'short', day: '2-digit'}) : new Intl.DateTimeFormat('en', {month: 'short', day: '2-digit', year: 'numeric'}); const tipText = customText.replace(/\{min_date\}/g, '<b>' + formatDate.format(minDate) + '</b>') .replace(/\{max_date\}/g, '<b>' + formatDate.format(maxDate) + '</b>'); $('.sun-delivery').html(tipText) }) </script>
2023年07月11日
249 阅读
0 评论
0 点赞
2023-07-08
axios 请求
安装使用 npm:$ npm install axios使用 bower:$ bower install axios使用 cdn:<script src="https://unpkg.com/axios/dist/axios.min.js"></script>案例执行 GET 请求// 为给定 ID 的 user 创建请求 axios.get('/user?ID=12345') .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); }); // 上面的请求也可以这样做 axios.get('/user', { params: { ID: 12345 } }) .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); });执行 POST 请求axios.post('/user', { firstName: 'Fred', lastName: 'Flintstone' }) .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); });执行多个并发请求function getUserAccount() { return axios.get('/user/12345'); } function getUserPermissions() { return axios.get('/user/12345/permissions'); } axios.all([getUserAccount(), getUserPermissions()]) .then(axios.spread(function (acct, perms) { // 两个请求现在都执行完成 }));axios API可以通过向 axios 传递相关配置来创建请求axios(config) // 发送 POST 请求 axios({ method: 'post', url: '/user/12345', data: { firstName: 'Fred', lastName: 'Flintstone' } }); // 获取远端图片 axios({ method:'get', url:'http://bit.ly/2mTM3nY', responseType:'stream' }) .then(function(response) { response.data.pipe(fs.createWriteStream('ada_lovelace.jpg')) }); axios(url[, config]) // 发送 GET 请求(默认的方法) axios('/user/12345');请求方法的别名axios.request(config) axios.get(url[, config]) axios.delete(url[, config]) axios.head(url[, config]) axios.options(url[, config]) axios.post(url[, data[, config]]) axios.put(url[, data[, config]]) axios.patch(url[, data[, config]])注意在使用别名方法时, url、method、data 这些属性都不必在配置中指定。请求配置这些是创建请求时可以用的配置选项。只有 url 是必需的。如果没有指定 method,请求将默认使用 get 方法。{ // `url` 是用于请求的服务器 URL url: '/user', // `method` 是创建请求时使用的方法 method: 'get', // default // `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。 // 它可以通过设置一个 `baseURL` 便于为 axios 实例的方法传递相对 URL baseURL: 'https://some-domain.com/api/', // `transformRequest` 允许在向服务器发送前,修改请求数据 // 只能用在 'PUT', 'POST' 和 'PATCH' 这几个请求方法 // 后面数组中的函数必须返回一个字符串,或 ArrayBuffer,或 Stream transformRequest: [function (data, headers) { // 对 data 进行任意转换处理 return data; }], // `transformResponse` 在传递给 then/catch 前,允许修改响应数据 transformResponse: [function (data) { // 对 data 进行任意转换处理 return data; }], // `headers` 是即将被发送的自定义请求头 headers: {'X-Requested-With': 'XMLHttpRequest'}, // `params` 是即将与请求一起发送的 URL 参数 // 必须是一个无格式对象(plain object)或 URLSearchParams 对象 params: { ID: 12345 }, // `paramsSerializer` 是一个负责 `params` 序列化的函数 // (e.g. https://www.npmjs.com/package/qs, http://api.jquery.com/jquery.param/) paramsSerializer: function(params) { return Qs.stringify(params, {arrayFormat: 'brackets'}) }, // `data` 是作为请求主体被发送的数据 // 只适用于这些请求方法 'PUT', 'POST', 和 'PATCH' // 在没有设置 `transformRequest` 时,必须是以下类型之一: // - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams // - 浏览器专属:FormData, File, Blob // - Node 专属: Stream data: { firstName: 'Fred' }, // `timeout` 指定请求超时的毫秒数(0 表示无超时时间) // 如果请求话费了超过 `timeout` 的时间,请求将被中断 timeout: 1000, // `withCredentials` 表示跨域请求时是否需要使用凭证 withCredentials: false, // default // `adapter` 允许自定义处理请求,以使测试更轻松 // 返回一个 promise 并应用一个有效的响应 (查阅 [response docs](#response-api)). adapter: function (config) { /* ... */ }, // `auth` 表示应该使用 HTTP 基础验证,并提供凭据 // 这将设置一个 `Authorization` 头,覆写掉现有的任意使用 `headers` 设置的自定义 `Authorization`头 auth: { username: 'janedoe', password: 's00pers3cret' }, // `responseType` 表示服务器响应的数据类型,可以是 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream' responseType: 'json', // default // `responseEncoding` indicates encoding to use for decoding responses // Note: Ignored for `responseType` of 'stream' or client-side requests responseEncoding: 'utf8', // default // `xsrfCookieName` 是用作 xsrf token 的值的cookie的名称 xsrfCookieName: 'XSRF-TOKEN', // default // `xsrfHeaderName` is the name of the http header that carries the xsrf token value xsrfHeaderName: 'X-XSRF-TOKEN', // default // `onUploadProgress` 允许为上传处理进度事件 onUploadProgress: function (progressEvent) { // Do whatever you want with the native progress event }, // `onDownloadProgress` 允许为下载处理进度事件 onDownloadProgress: function (progressEvent) { // 对原生进度事件的处理 }, // `maxContentLength` 定义允许的响应内容的最大尺寸 maxContentLength: 2000, // `validateStatus` 定义对于给定的HTTP 响应状态码是 resolve 或 reject promise 。如果 `validateStatus` 返回 `true` (或者设置为 `null` 或 `undefined`),promise 将被 resolve; 否则,promise 将被 rejecte validateStatus: function (status) { return status >= 200 && status < 300; // default }, // `maxRedirects` 定义在 node.js 中 follow 的最大重定向数目 // 如果设置为0,将不会 follow 任何重定向 maxRedirects: 5, // default // `socketPath` defines a UNIX Socket to be used in node.js. // e.g. '/var/run/docker.sock' to send requests to the docker daemon. // Only either `socketPath` or `proxy` can be specified. // If both are specified, `socketPath` is used. socketPath: null, // default // `httpAgent` 和 `httpsAgent` 分别在 node.js 中用于定义在执行 http 和 https 时使用的自定义代理。允许像这样配置选项: // `keepAlive` 默认没有启用 httpAgent: new http.Agent({ keepAlive: true }), httpsAgent: new https.Agent({ keepAlive: true }), // 'proxy' 定义代理服务器的主机名称和端口 // `auth` 表示 HTTP 基础验证应当用于连接代理,并提供凭据 // 这将会设置一个 `Proxy-Authorization` 头,覆写掉已有的通过使用 `header` 设置的自定义 `Proxy-Authorization` 头。 proxy: { host: '127.0.0.1', port: 9000, auth: { username: 'mikeymike', password: 'rapunz3l' } }, // `cancelToken` 指定用于取消请求的 cancel token // (查看后面的 Cancellation 这节了解更多) cancelToken: new CancelToken(function (cancel) { }) }响应结构某个请求的响应包含以下信息{ // `data` 由服务器提供的响应 data: {}, // `status` 来自服务器响应的 HTTP 状态码 status: 200, // `statusText` 来自服务器响应的 HTTP 状态信息 statusText: 'OK', // `headers` 服务器响应的头 headers: {}, // `config` 是为请求提供的配置信息 config: {}, // 'request' // `request` is the request that generated this response // It is the last ClientRequest instance in node.js (in redirects) // and an XMLHttpRequest instance the browser request: {} }使用 then 时,你将接收下面这样的响应 :axios.get('/user/12345') .then(function(response) { console.log(response.data); console.log(response.status); console.log(response.statusText); console.log(response.headers); console.log(response.config); });在使用 catch 时,或传递 rejection callback 作为 then 的第二个参数时,响应可以通过 error 对象可被使用配置默认值你可以指定将被用在各个请求的配置默认值全局的 axios 默认值axios.defaults.baseURL = 'https://api.example.com'; axios.defaults.headers.common['Authorization'] = AUTH_TOKEN; axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';自定义实例默认值// Set config defaults when creating the instance const instance = axios.create({ baseURL: 'https://api.example.com' }); // Alter defaults after instance has been created instance.defaults.headers.common['Authorization'] = AUTH_TOKEN; 配置的优先顺序配置会以一个优先顺序进行合并。这个顺序是:在 lib/defaults.js 找到的库的默认值,然后是实例的 defaults 属性,最后是请求的 config 参数。后者将优先于前者。这里是一个例子:// 使用由库提供的配置的默认值来创建实例// 此时超时配置的默认值是 0var instance = axios.create(); // 覆写库的超时默认值 // 现在,在超时前,所有请求都会等待 2.5 秒 instance.defaults.timeout = 2500; // 为已知需要花费很长时间的请求覆写超时设置 instance.get('/longRequest', { timeout: 5000 }); 拦截器 在请求或响应被 then 或 catch 处理前拦截它们。 // 添加请求拦截器 axios.interceptors.request.use(function (config) { // 在发送请求之前做些什么 return config; }, function (error) { // 对请求错误做些什么 return Promise.reject(error); }); // 添加响应拦截器 axios.interceptors.response.use(function (response) { // 对响应数据做点什么 return response; }, function (error) { // 对响应错误做点什么 return Promise.reject(error); }); 如果你想在稍后移除拦截器,可以这样: const myInterceptor = axios.interceptors.request.use(function () {/*...*/}); axios.interceptors.request.eject(myInterceptor); 可以为自定义 axios 实例添加拦截器 const instance = axios.create(); instance.interceptors.request.use(function () {/*...*/}); 错误处理 axios.get('/user/12345') .catch(function (error) { if (error.response) { // The request was made and the server responded with a status code // that falls out of the range of 2xx console.log(error.response.data); console.log(error.response.status); console.log(error.response.headers); } else if (error.request) { // The request was made but no response was received // `error.request` is an instance of XMLHttpRequest in the browser and an instance of // http.ClientRequest in node.js console.log(error.request); } else { // Something happened in setting up the request that triggered an Error console.log('Error', error.message); } console.log(error.config); });可以使用 validateStatus 配置选项定义一个自定义 HTTP 状态码的错误范围。axios.get('/user/12345', { validateStatus: function (status) { return status < 500; // Reject only if the status code is greater than or equal to 500 } })
2023年07月08日
240 阅读
0 评论
1 点赞
2023-06-13
浏览器禁止鼠标右键菜单
<script> if (document.images) { window.oncontextmenu = function () { return false; } }
2023年06月13日
304 阅读
0 评论
0 点赞
2023-03-04
jquery shoplazza 投递时间提示代码
<div class="tw-w-full tw-flex tw-items-center tw-mt-4 product-info__marketing-delivery-time {% if section.settings.delivery_time_show_as_date %}product-info__marketing-delivery-time_date{% endif %}" data-delivery-min="{{section.settings.delivery_time_min}}" data-delivery-max="{{section.settings.delivery_time_max}}" > {% include 'icon_sun_shipping',icon_class:"" %} <span class="tw-ml-2 tw-leading-none" > {% if section.settings.delivery_time_show_as_date %} {{ 'i18n.product.product_detail.marketing_delivery' | t: from: "<b></b>",to:"<b></b>"}}{% else %}{{'i18n.product.product_detail.marketing_delivery_days' | t: from: "<b></b>",to:"<b></b>" }} {% endif %} </span> </div><script> $(function () { var $delivery = $(".product-info__marketing-delivery-time"); if ($delivery.length) { var max = $delivery.attr("data-delivery-max"); var min = $delivery.attr("data-delivery-min"); if ($delivery.is(".product-info__marketing-delivery-time_date")) { var maxdate = new Date((new Date()).getTime() + (max * 86400000)); var mindate = new Date((new Date()).getTime() + (min * 86400000)); var formatter = new Intl.DateTimeFormat('en', { month: 'short', day: "2-digit" }); $delivery.find("b").eq(0).html(formatter.format(mindate)) $delivery.find("b").eq(1).html(formatter.format(maxdate)) } else { $delivery.find("b").eq(0).html(min); $delivery.find("b").eq(1).html(max); } } }); </script>
2023年03月04日
158 阅读
0 评论
1 点赞
2022-11-12
如何使用JavaScript获取和设置CSS root变量值
1.CSS全局变量:root { --color: #ccc; }2.js代码获取css全局变量getComputedStyle(document.documentElement).getPropertyValue('--color'); // #ccc 3.js代码设置css全局变量document.documentElement.style.setProperty('--color', '#fe000');
2022年11月12日
1,277 阅读
0 评论
3 点赞
2022-11-12
Javascript中使用Youtube
CSS部分<style> * { margin: 0; padding: 0; box-sizing: border-box; } :root { --container-title-fontsize: 30px; --article-content-fontsize: 14px; --article-link-fontsize: 13px; --video-title-fontsize: 14px; --colorTitle: #000; } .video-container { width: 99%; margin: auto; } .video-container-title { width: 100%; text-align: center; font-size: var(--container-title-fontsize); font-weight: bold; margin-top: 50px; color:var(--colorTitle); } .video-group { display: flex; justify-content: space-between; margin: 10px 0; flex-wrap: wrap; } .video-group:after { width: calc(100% / 3 - 20px); content: ''; height: 0; visibility: hidden; } .video-item { width: calc(100% / 3 - 20px); margin-top: 30px; } .video-content { width: 100%; text-align: center; } .video-title { font-size: var(--video-title-fontsize); } .youtube { background-color: #000; margin-bottom: 20px; position: relative; padding-top: 56.25%; overflow: hidden; cursor: pointer; } .youtube .play-button, .youtube .play-button:before { top: 50%; left: 50%; transform: translate3d(-50%, -50%, 0); } .youtube img, .youtube iframe, .youtube .play-button, .youtube .play-button:before { position: absolute; } .youtube img, .youtube .play-button { cursor: pointer; } .youtube img { width: 100%; top: 0; left: 0; opacity: 0.8; } .youtube .play-button { width: 90px; height: 60px; background-color: #333; box-shadow: 0 0 30px rgb(0 0 0 / 60%); z-index: 1; opacity: 0.8; border-radius: 6px; } .youtube .play-button:before { content: ""; border-style: solid; border-width: 15px 0 15px 26px; border-color: transparent transparent transparent #fff; } .youtube .play-button:hover { background-color: #f00; } .youtube iframe { height: 100%; width: 100%; top: 0; left: 0; } [data-max="false"] img { top: -47px; } </style>Html部分<div class="video-container"> <div class="video-container-title"> VIDEO REVIEW </div> <div class="video-group"> <div class="video-item"> <div class="video-content"> <div class="youtube" data-embed="cUdfHgzvHoQ" data-max="false"> <div class="play-button"></div> </div> </div> <p class="video-title">Full review of EnjoyBot 12v 100Ah LFP battery,Full review of EnjoyBot 12v 100Ah LFP battery</p> </div> <div class="video-item"> <div class="video-content"> <div class="youtube" data-embed="0jErmH2iEG4" data-max="false"> <div class="play-button"></div> </div> </div> <p class="video-title">EnjoyBot 12V 100Ah LiFePO4 Battery Review, Super Cheap, $256/kWh!</p> </div> </div> </div>JS部分<script> var youtube = document.querySelectorAll(".youtube"); // loop for (var i = 0; i < youtube.length; i++) { var source = ''; // thumbnail image source. if (youtube[i].dataset.max == 'false') { source = "https://img.youtube.com/vi/" + youtube[i].dataset.embed + "/0.jpg"; } else { source = "https://img.youtube.com/vi/" + youtube[i].dataset.embed + "/maxresdefault.jpg"; } var image = new Image(); image.src = source; image.addEventListener("load", function () { youtube[i].appendChild(image); }(i)); youtube[i].addEventListener("click", function () { console.log('click') var iframe = document.createElement("iframe"); iframe.setAttribute("frameborder", "0"); iframe.setAttribute("allowfullscreen", ""); iframe.setAttribute("src", "https://www.youtube.com/embed/" + this.dataset.embed + "?rel=0&autoplay=1&showinfo=1"); this.innerHTML = ""; this.appendChild(iframe); }); } </script>
2022年11月12日
118 阅读
0 评论
0 点赞
2022-10-13
javascript高级-node.js核心编程
第0章 Node介绍0.0 回顾 JavaScript历史及发展 1995年 网景公司的布兰登开发;1997年7月,ECMA组织发布ECMAScript 1.0版;2007年10月发布3.1版本后不久,ECMAScript 3.1改名为 ECMAScript 5。2008年,为Chrome浏览器而开发的V8编译器诞生2011年6月,ECMAscript 5.1版发布,现在使用最为广泛的版本;2015年6月,ECMAScript 6正式发布,并且更名为“ECMAScript 2015”;如何学习JavaScriptJavaScript 的核心语法部分相当精简,也就是语言本身,只包括两个部分:基本的语法构造(比如操作符、控制结构、语句)标准库(就是一系列具有各种功能的对象比如Array、Date、Math等)。想要实现其他复杂的操作和效果,都要依靠 宿主环境 提供API,目前,已经嵌入 JavaScript 的宿主环境有多种,最常见的环境就是 浏览器 和 操作系统 ;回顾 JavaScript 语法特性变量、数据类型、流程控制函数(基本声明参数,作用域,回调函数)、面向对象(原型,构造函数,this的指向,new的过程)0.1 Node是什么Node 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。Node 不是一种独立的语言、Node不是 JavaScript 框架,Node是一个除了浏览器之外的、可以让 JavaScript 运行的环境Node.js 是一个让 JavaScript 运行在服务端的开发平台,是使用 事件驱动, 异步非阻塞I/O,单线程,跨平台的 JS 运行环境;0.2. 为什么要学习 Node打开服务器的黑盒子企业需求大前端必备技能为了更好的学习前端框架0.3. Node 能做什么知乎 - Node.js能做什么,该做什么?Web 服务器(重点)命令行工具网络爬虫:是一种按照一定的规则,自动地抓取网站信息的程序桌面应用程序开发0.4. 一些资源文档Node.js 官方文档Node.js 中文文档(非官方)书籍深入浅出 Node.jsNode.js 权威指南Node.js 实战Node.js实战(第2季)github资源Node.js 包教不包会ECMAScript 6 入门七天学会 NodeJS社区Node.js 中文社区0.5. Node 发展历史聊聊 Node.js 的历史来自朴灵大大的 -- Node.js 简史第1章 NodeJS起步1.1 下载安装下载 https://nodejs.org/zh-cn/download/历史版本:https://nodejs.org/en/download/releases/windows下安装过程:对于已经装过的,重新安装就会升级安装成功后,打开命令行,输入node --version 或者 node -v (显示node的版本号)表示安装成功其他平台的安装方式:https://nodejs.org/zh-cn/download/package-manager/1.2 REPL环境node中的REPL环境类似于浏览器中的 Console控制台 ,可以做一些代码测试。按ctrl + 两次c 退出REPL环境但是, 我们写代码肯定不是在控制台中写,而是写在一个单独的.js文件中.1.3 node运行js代码1.4 Node 中的模块浏览器(客户端)中的JS 与 Node中的JS 第2章 核心模块的使用2.1.1 FS模块node核心模块之一,用于操作文件;中文手册 : http://nodejs.cn/api/fs.html文件读写// 引入模块 var fs = require('fs'); // console.log(typeof fs); //object // 向文件中写入内容 fs.writeFile('./2.1.txt','itcast',function(cb,cb2){ // 回调函数 (写入成功后执行的函数) console.log(cb); console.log(cb2); }) // 从文件中读取内容 fs.readFile('./2.1.txt','utf8',function(e,d){ // 回调函数 (读取成功后执行的函数) console.log(e); console.log(d); });追加内容// 引入模块 var fs = require('fs'); // 向文件中追加内容 fs.readFile('./2.1.txt','utf8',function(e,d){ d+='2344'; fs.writeFile('./2.1.txt',d,function(e){ if(e){ console.log('写入失败') }else{ console.log('写入成功') } }) });课堂作业:尝试操作json数据,时间15分钟var str = [ {id:1,names:'路飞',sex:'男',img:''}, {id:2,names:'乌索普',sex:'男',img:''}, {id:3,names:'娜美',sex:'女',img:''} ]要求1:将数据转为字符串存入文件 hzw.json要求2:向 hzw.json 文件中添加一条数据 {id:'4',names:'罗宾',sex:'女',img:''} ;要求3:删除 hzw.json 文件中 id 值为2的数据要求4:将 hzw.json 文件中id为3的数据中的names改为 ‘女帝’;2.1.2 http协议理论参见http部分课件2.2 HTTP模块node核心模块之一,用于搭建HTTP服务器;中文手册 http://nodejs.cn/api/http.html2.2.1 开启服务器// 1. 导入http模块 var http = require('http'); // 2. 使用http这个模块中的createServer()创建一个服务器实例对象 var server = http.createServer(); // 3. 绑定端口号,启动web服务器 server.listen(8000, function() { console.log(' 请访问http://localhost:8000'); }); // 4. 为这个服务器实例对象注册 request 请求处理函数 // 请求处理函数function(形参1,形参2){} // 形参1:request请求对象 获取到当前请求的路径,方法等本次请求的所有信息 // 形参2:response响应对象 发送响应数据 server.on('request', function(request, response) { console.log('服务端收到客户端的请求啦!!!'); // 向客户端页面返回字符串 response.write("hello node"); // 结束响应 response.end(); });因为我们的服务器接受请求处理并响应数据时,并没有指定响应数据的类型,所以出现了乱码;而在http中,我们可以通过服务器的响应头指定数据类型,在 http.ServerResponse 类 中为我们提供了setHeader 方法:2.2.2 响应 HTML 页面但是,我们不能一直将html代码写到服务器的方法中,而是需要建一个xx.html的文件,将html文件中的内容返回给客户端;2.2.2 .html :<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <h1>你好,我是西岭老湿</h1> <h2>另外,我还很帅……</h2> </body> </html>nodejs代码var http = require('http'); // 1:引入文件操作模块 var fs = require('fs'); var server = http.createServer(); server.on('request', function(request, response) { // 2:读取html文件中的内容 fs.readFile('./2.2.2.html','utf8',function(error,html_data){ // 设置响应头 response.setHeader('Content-Type', 'text/html;charset=utf-8'); // 将html中的内容响应回客户端,结束响应 response.end(html_data); }) });2.2.3 响应图片<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <h1>你好,我是西岭老湿</h1> <h2>另外,我还很帅……</h2> <img src="https://img.sunshine966.com/node/03.jpg" alt="野生脆脆.jpg"> </body> </html>server.on('request', function(request, response) { // url 属性返回请求的URL字符串 var urls = request.url; if( urls =='/'){ fs.readFile('./2.2.2.html','utf8',function(error,html_data){ // 设置响应头 response.setHeader('Content-Type', 'text/html;charset=utf-8'); // 将html中的内容响应回客户端,结束响应 response.end(html_data); }) }else if(urls.indexOf('jpg')>=0){ // 判断请求图片 fs.readFile('https://img.sunshine966.com/node/03.jpg',function(error,html_data){ response.end(html_data); }) } }2.2.4 响应其他静态资源<head> <meta charset="UTF-8"> <title>Document</title> <link rel="stylesheet" href="./public/h.css"> </head> <body> <h1>你好,我是西岭老湿</h1> <h2>另外,我还很帅……</h2> <img src="https://img.sunshine966.com/node/03.jpg" alt="野生脆脆.jpg"> </body> <script src="./public/h.js"></script> </html>server.on('request', function(request, response) { // url 属性返回请求的URL字符串 var urls = request.url; if( urls =='/'){ fs.readFile('./2.2.2.html','utf8',function(error,html_data){ // 设置响应头 response.setHeader('Content-Type', 'text/html;charset=utf-8'); // 将html中的内容响应回客户端,结束响应 response.end(html_data); }) }else{ fs.readFile('.'+urls,function(error,html_data){ response.end(html_data); }) } });2.3 服务器遍历文件及文件夹-案例模仿Apache服务器,遍历文件及文件,显示时间及大小;右键另存为,下载页面当作静态页面模板使用;使用node载入静态页面:使用ajax技术在页面中发送请求到后台,apache.html<script> var xhr = new XMLHttpRequest(); xhr.onreadystatechange=function(){ if(this.readyState == 4){ console.log(this.responseText); } } xhr.open('get','/file_list'); xhr.send(); </script>node:server.on('request', function(request, response) { // url 属性返回请求的URL字符串 var urls = request.url; if( urls =='/'){ fs.readFile('./apache.html','utf8',function(error,html_data){ // 设置响应头 response.setHeader('Content-Type', 'text/html;charset=utf-8'); // 将html中的内容响应回客户端,结束响应 response.end(html_data); }) }else if(urls == '/file_list'){ fs.readdir('./','utf8',function(err,files){ response.end(JSON.stringify(files)); }); }else{ fs.readFile('.'+urls,function(error,html_data){ response.end(html_data); }) } });apache.html --> ajaxxhr.onreadystatechange=function(){ if(this.readyState == 4){ var data = JSON.parse(this.responseText); var htmls = ''; for(var i = 0;i<data.length;i++){ htmls+='<tr><td valign="top">'; htmls+= '<img src="https://img.sunshine966.com/node/layout.gif" alt="[ ]"></td>'; htmls+='<td><a href="http://localhost/%e7%ac%94%e8%ae%b0-01.pdf">'; htmls+= data[i]+'</a> </td>'; htmls+= '<td align="right">2018-04-26 10:31 </td>'; htmls+= '<td align="right">3.2M</td><td> </td></tr>'; } var tb = document.getElementsByTagName('tbody')[0]; tb.innerHTML+=htmls; } }2.4 动态展示文件的其他属性获取文件的其他属性:var fs = require('fs'); fs.readdir('./','utf8',function(err,files){ fs.stat(files[0],function(er,st){ console.log(st.mtime); console.log(st.size); console.log(st.isFile()); }) });修改node代码server.on('request', function (request, response) { // url 属性返回请求的URL字符串 var urls = request.url; if (urls == '/') { fs.readFile('./apache.html', 'utf8', function (error, html_data) { // 设置响应头 response.setHeader('Content-Type', 'text/html;charset=utf-8'); // 将html中的内容响应回客户端,结束响应 response.end(html_data); }) } else if (urls == '/file_list') { fs.readdir('./', 'utf8', function (err, files) { // response.end(JSON.stringify(files)); var file_obj = []; // 判断条件:声明一个变量,这个变量用来记录两个数据的中数据的长度 var count = 0; for (var i = 0; i < files.length; i++) { file_obj[i] = {}; // 利用自调用匿名函数,保留i的变量值 (function (i) { fs.stat(files[i], function (er, st) { count ++; file_obj[i].name = files[i]; if(st.isFile()){ file_obj[i].type = 'file'; }else{ file_obj[i].type = 'dir'; } file_obj[i].mtime = st.mtime; file_obj[i].size = st.size; // 当读取的文件个数与所有文件个数相等时 if(count == files.length){ response.end(JSON.stringify(file_obj)); } }) // console.log(file_obj); })(i); // console.log(files[i]); } }); } else { fs.readFile('.' + urls, function (error, html_data) { response.end(html_data); }) } });修改 ajax代码var xhr = new XMLHttpRequest(); xhr.onreadystatechange=function(){ if(this.readyState == 4){ var data = JSON.parse(this.responseText); var htmls = ''; for(var i = 0;i<data.length;i++){ htmls+='<tr><td valign="top">'; if(data[i].type == 'file'){ htmls+= '<img src="https://img.sunshine966.com/node/layout.gif" alt="[ ]"></td>'; }else{ htmls+= '<img src="https://img.sunshine966.com/node/folder.gif" alt="[ ]"></td>'; } htmls+='<td><a href="">'; htmls+= data[i].name+'</a> </td>'; htmls+= '<td align="right">'+ data[i].mtime +'</td>'; htmls+= '<td align="right">'+ data[i].size +'</td><td> </td></tr>'; } var tb = document.getElementsByTagName('tbody')[0]; tb.innerHTML+=htmls; } } xhr.open('get','/file_list'); xhr.send();循环后 i 丢失的问题: // var arr = ['a', 'b', 'c']; // for (var i = 0; i < arr.length; i++) { // // 模拟延迟 // setTimeout(function () { // console.log(arr[i]); // }, 1000); // } /* * ******************************************* * 上面的代码 全部输出 undefined * ******************************************* */ var arr = ['a','b','c']; for(var i = 0; i < arr.length; i ++) { (function(i){ // 模拟延迟 setTimeout(function() { console.log(arr[i]); }, 1000); })(i); }解决方案2: 直接使用count 记录var fs = require('fs'); fs.readdir('./', 'utf8', function (err, files) { // console.log(files); var count = 0; var arr = [] for (var i = 0; i < files.length; i++) { fs.stat(files[i], 'utf8', function (err, stats) { // 在回调中声明对象 var obj = {}; // console.log(i); obj.size = stats.size obj.mtime = stats.mtime // 不在使用i变量,因为循环结束i 就会消失 // 但是count 不会 obj.name = files[count]; // 将对象的数据存入数组 arr.push(obj); // console.log(arr); // 自增count 下次使用 count++; // console.log(obj); if (files.length == count) { console.log(arr); } }) } })第3章 包管理器npm3.1 使用moment使用第三方包格式化时间3.2 npm 命令的使用上面的代码,我们使用npm安装了moment来进行格式化时间的处理,这就是使用第三方模块;而我们使用的npm就是node中自带的包(模块)管理工具;借助NPM可以帮助我们快速安装和管理依赖包,使Node与第三方模块之间形成了一个良好的生态系统;我们也可以直接输入npm,查看帮助引导:PS C:\xamp\htdocs\ceshi\09> npm Usage: npm <command> where <command> is one of: access, adduser, audit, bin, bugs, c, cache, ci, cit, completion, config, create, ddp, dedupe, deprecate, dist-tag, docs, doctor, edit, explore, get, help, help-search, hook, i, init, install, install-test, it, link, list, ln, login, logout, ls, outdated, owner, pack, ping, prefix, profile, prune, publish, rb, rebuild, repo, restart, root, run, run-script, s, se, search, set, shrinkwrap, star, stars, start, stop, t, team, test, token, tst, un, uninstall, unpublish, unstar, up, update, v, version, view, whoami npm <command> -h quick help on <command> npm -l display full usage info npm help <term> search for help on <term> npm help npm involved overview Specify configs in the ini-formatted file: C:\Users\Administrator\.npmrc or on the command line via: npm <command> --key value Config info can be viewed via: npm help config npm@6.4.1 C:\Program Files\nodejs\node_modules\npm3.3 使用npm初始化项目一个项目,不可能只是使用一个第三方包,而包越多,管理起来就越麻烦,而 npm init 给我们提供了项目初始化的功能,也解决了多个包的管理问题:"name": "usenpm", // 项目名 "version": "1.0.0", // 版本号 "description": "这是我们第一次使用npm", // 描述信息 "main": "index.js", // 入口文件 "scripts": { // npm 设置的一些指令 "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [ // 关键字 "第一次" ], "author": "itheima6期", // 作者 "license": "ISC" // 当前项目的协议3.4 解决 npm 被墙问题npm 存储包文件的服务器在国外,有时候会被墙,速度很慢,所以我们需要解决这个问题。http://npm.taobao.org/ 淘宝的开发团队把 npm 在国内做了一个备份。安装淘宝的 cnpm:# 在任意目录执行都可以 # --global 表示安装到全局,而非当前目录 # --global 不能省略,否则不管用 npm install --global cnpm接下来你安装包的时候把之前的 npm 替换成 cnpm。举个例子:# 这里还是走国外的 npm 服务器,速度比较慢 npm install jquery # 使用 cnpm 就会通过淘宝的服务器来下载 jquery cnpm install jquery如果不想安装 cnpm 又想使用淘宝的服务器来下载:npm install jquery --registry=https://registry.npm.taobao.org但是每一次手动这样加参数很麻烦,所我们可以把这个选项加入配置文件中:# 配置到淘宝服务器 npm config set registry https://registry.npm.taobao.org # 查看 npm 配置信息 npm config list只要经过了上面命令的配置,则你以后所有的 npm install 都会默认通过淘宝的服务器来下载。3.5 package.json 与 package-lock.json 文件如果后期开发过程中,需要项目迁移,我们只需要将package.json文件迁移即可,在新项目下执行npm install ,所有第三方包会自动安装;package.json的作用就是用来记录当前项目及包的使用情况;不能在package.json中添加注释package-lock.json 保存第三方包的版本和下载路径等详细信息;当我们使用npm管理包时,package.json 及package-lock.json 的内容都会自动更新3.6 服务端页面渲染之前的案例中,我们时通过前端浏览器发送ajax请求获取服务器数据的,前端获取数据后进行遍历展示;缺点就是发送多次请求、不利于搜索引擎查找;我们修改为后端渲染数据;art-template: https://www.npmjs.com/package/art-templatevar art = require('art-template'); art.defaults.root = './'; var html = art('./art-test.html',{data:[{name:123,age:345},{a:678,b:987}]}); console.log(html);<body> <h1>nihoa</h1> <h2>{{data[0].name}}</h2> </body>1:重新创建目录,并初始化项目: npm init 2:将之前写好的后台文件 http.js 和 前台模板页面 apache.html 复制到新项目目录中;3:安装时间处理模块: npm install moment4:安装模板引擎模块: npm install art-template 5: 修改 后台文件 http.js 和 前台模板页面 apache.html 文件http.js :apache.html :那么我们在项目中应该使用 客户端渲染还是服务端渲染:答:两者都用,根据数据的不同作用而定;第4章 Node模块化及CommonJS规范通过前面几个章节的学习, 我们基本掌握了NodeJS编程的基础知识, 但是我们也直观的发现了一个问题,和我们之前学习浏览器编程时JS, 差异还是很大的; 都是JavaScript编程, 为何有这种差异? 前面写过的防Apache服务器的案例中, 使用过内置fs模块, 使用过 moment 模块, 而这些模块都不是我们写的, 都是直接拿过来使用, 那么我们能不能自己写一个模块, 应该怎么写, 有哪些规矩, 如果我们自己写了一个模块, 能不能提供给其他编程人员直接使用, 应该怎么用?Electron 跨平台的桌面应用框架: https://electronjs.org/4.1 CommonJS规范的由来JS 的表现的表现能力取决于宿主环境提供的API, 在web1.0 时代, W3C 组织提供了浏览器的规范支持, 在web2.0 时代, 随着HTML5的发展, 更多的标准API 出现在了浏览器中, 但是, 在后端 JS 中标准的制定纹丝不动 ;由 Mozilla 工程师Kevin Dangoor于2009年1月提出名为 ServerJS 的规范; 2009年8月,更名为CommonJS,以显示 API 的更广泛适用性。What I’m describing here is not a technical problem. It’s a matter of people getting together and making a decision to step forward and start building up something bigger and cooler together.我在这里描述的不是一个技术问题。这是一个人们聚在一起,决定向前一步,开始一起建立更大更酷的东西的问题。--Kevin Dangoor4.2 CommonJS 的模块规范CommonJS对模块的定义十分简单,主要分为:1、模块引用:使用 require() 方法引入一个模块API ;2、模块定义:在模块中使用 exports 对象导出当前模块数据或方法;在模块中还存在一个module对象,它代表模块自身,module对象有一个exports 属性,用于数据导出;其实exports 对象就是module.exports 的引用; exports === module.exports3、模块标识:其实就是模块的文件名,必须符合小驼峰法命名规则,使用require() 引入时使用 . 或 .. 开头的相对路径或/ 绝对路径,引入时可以不写文件后缀名;重点注意 : 模块中的方法和变量的作用域仅在模块内部,每个模块具有独立的空间,互不干扰;CommonJS 构建的模块机制中的引入与导出是我们完全不用考虑变量污染或者替换的问题,相比与命名空间的机制,是有巨大差距的;4.3 Node对CommonJS的实现 (Node模块化)以上代码就是自定义模块的基本规则 这是重点4.4 模块加载的顺序和规则在 CommonJS 规范中,使用 require() 加载(引入) 模块时,模块标识必须使用相对路径或绝对路径指明模块位置,但是在node的实现中,我们可以不指明模块路径;如: require('fs')、require('moment') ;如果没有指明路径,那就是加载核心模块或第三方模块,指明加载路径一般就是加载自定义模块;不管加载什么模块,都是优先从缓存中加载:Node 加载模块时,如果这个模块已经被加载过了,则会直接缓存起来,将来再次引用时不会再次加加载这个模块(即:如果一个模块被加载两次,则模块中的代码只会被执行一次)而核心模块和第三方模块的的加载顺序就是:先加载核心模块,核心模块的内容都是在安装node时已经编译好的可执行的二进制代码,加载执行的速度,仅次于缓存加载,如果核心模块中没有,则加载第三方模块第三方模块的加载规则:先在当前文件的模块所属目录去找 node_modules目录如果找到,则去该目录中找 模块名的目录 如 : moment如果找到 moment 目录, 则找该目录中的 package.json文件如果找到 package.json 文件,则找该文件中的 main属性如果找到main 属性,则拿到该属性对应的文件如果找到 moment 目录之后,没有package.json或者有 package.json 没有 main 属性或者有 main 属性,但是指向的路径不存在则 node 会默认去看一下 moment 目录中有没有 index.js --> index.json--> index.node 文件如果找不到index 或者 找不到 moment 或者找不到 node_modules则进入上一级目录找 node_moudles 查找(规则同上)如果上一级还找不到,继续向上,一直到当前文件所属磁盘的根目录如果到磁盘概目录还没有找到,直接报错4.5 模块化封装案例思路:1:服务器功能 --> apache2:监听请求 --> 路由3:根据请求处理业务 --> Controller4:获取数据(处理数据) --> model5:显示数据 --> view客户端渲染方式的案例重构修改 http.js --- 服务器模块var http = require('http'); var router = require('./router'); var server = http.createServer(); router(server); server.listen(8000,function(){ console.log('欢迎来到node世界') })添加自定义模块 router.js -- 路由模块var controller = require('./controller'); module.exports = function(server){ server.on('request',function(req,res){ var urls = req.url; if(urls == '/'){ // 需要获取html文件中的内容 // 响应给客户端 // 业务层模块的调用 controller.index(function(data){ // 利用回调函数获取数据 res.end(data); }); }else if(urls == '/getnames'){ // 业务层模块的调用 // 将请求对象及响应对象传入业务层方法,在业务层做http响应处理 controller.getNames(req,res); }else{ // 响应静态资源 require('fs').readFile('.'+urls,function(err,data){ res.end(data); }) } }) }contrllor.js --- 业务模块var fs = require('fs'); var moment = require('moment'); module.exports = { index: function (callback) { // 返回静态页面 fs.readFile('./index.html', 'utf8', function (err, data) { callback(data); }) // console.log('index'); }, getNames: function (req, res) { // console.log('getnamesssss'); fs.readdir('./', 'utf8', function (err, data) { var filearr = []; var cont = 0; for (var i = 0; i < data.length; i++) { // 2: (function (i) { // 3: fs.stat(data[i], function (err, stats) { cont++; // 获取文件名 // 问题:文件名为 undefined // 原因:在循环结束之后,函数才会被调用,而此时i已经被修改为最后的值 // 解决:在每次循环中形成一个独立的作用域保留i的值, // 当异步函数调用时,获取到的是独立作用域中的i filearr[i] = {}; filearr[i].name = data[i]; // 获取文件的其他属性 filearr[i].type = stats.isFile(); filearr[i].size = stats.size; // filearr[i].mtime = stats.mtime; filearr[i].mtime = moment(stats.mtime).format("YYYY-MM-DD hh:mm:ss"); // 异步函数调用次数与文件数相等时,服务器作出响应并断开 if (cont == data.length) { res.end(JSON.stringify(filearr)); } }) })(i); } }) } }本文档大量参考相关书籍、文档、博客、手册等资源,最终解释权归 吴明仕 所有;参考资源相关列表:https://nodejs.org/zh-cn/ node.js官网http://nodejs.cn/ node.js中文网《深入浅出Node.js》 朴灵著 ,人民邮电出版社https://en.wikipedia.org/wiki/CommonJS 维基百科《ECMAScript 6 入门》(第三版) 阮一峰著 ,电子工业出版社《你不知道的JavaScript》(上、中、下卷) [美] Kyle Simpson 著 ,人民邮电出版社http://www.expressjs.com.cn/ express中文网
2022年10月13日
127 阅读
0 评论
1 点赞
2022-10-13
javascript高级-jQuery中的Ajax
第9章 jQ中的Ajax9.1 认识jQ中ajax的封装jQ 对于ajax的封装有两层实现;$.ajax 为底层封装实现;基于 $.ajax ,分别实现了$.get 与$.post 的高层封装实现;9.2 ajax 的底层实现基本语法:$.ajax(obj)对象的参数设置及含义:async: 布尔类型,代表是否异步,true代表异步,false同步,默认为truecache: 是否缓存,布尔类型,true代表缓存,false代表不缓存,默认为truecomplete: 当Ajax状态码(readyState)为4的时候所触发的回调函数contentType: 发送信息至服务器时内容编码类型;(默认: "application/x-www-form-urlencoded")data: 要求是一个字符串格式,Ajax发送时所传递的数据dataType: 期待的返回值类型,可以是text,xml,json,默认为text类型success: 当Ajax状态码为4且响应状态码为200时所触发的回调函数type: Ajax发送网络请求的方式,(默认: "GET");url: 请求的url地址案例代码:GET 请求<body> <input type="button" value="点击" id="btu"> </body> <script> $('#btu').click(function(){ //get请求 $.ajax({ url:'9-2.php?id=11', success:function(data){ alert(data); } }); }); </script>POST 请求//POST请求及同步异步 $.ajax({ url:'9-2.php', type:'post', data:'id=1111', success:function(data){ alert(data); }, // async:false, }); // alert(22); //检验同步异步设置返回值类型//设置返回值类型 $.ajax({ url:'9-2.php?id=11', success:function(data){ alert(data.a); }, //jq接到后台的json字符串,转成对象后呈现给用户 dataType:'json', });PHP后台代码// sleep(3); if($_GET['id']==11){ //get // if($_POST['id']==11){ //post // echo 'jq_ajax'; echo json_encode(['a'=>'2222']); //json 返回 }else{ echo 'hhh'; }9.3 ajax 的高层实现9.3.1 GET 应用基本语法:$.get(url, [data], [callback], [type])url:待载入页面的URL地址data:待发送 Key/value 参数。callback:载入成功时回调函数。type:返回内容格式,xml, html, script, json, text, _default。案例代码:<script> $('#btu').click(function(){ $.get('9-2.php',function(data){ alert(data.a); },'json'); }); </script>但是注意:IE浏览器存在缓存问题;解决缓存问题 修改:<script> $('#btu').click(function(){ var da = {_:new Date().getTime()}; $.get('9-2.php',da,function(data){ alert(data.a); },'json'); }); </script>9.3.2 POST 应用$.post(url, [data], [callback], [type])url:发送请求地址。data:待发送 Key/value 参数。callback:发送成功时回调函数。type:返回内容格式,xml, html, script, json, text, _default。案例代码:<script> $('#btu').click(function(){ $.post('9-2.php', {id:'11'}, function(data){ alert(data.a); },'json'); }); </script>第10章 jQ中的跨域问题Ajax技术受到浏览器同源策略的限制,禁止从一个域上向另外一个域发送请求。也就是说,受到请求的 URL 的域必须与当前 Web 页面的域相同。这意味着浏览器隔离来自不同源的内容,以防止它们之间的操作。后台不同域下的PHP代码$arr = ['a'=>1,'b'=>'san','c'=>'wu','d'=>4]; $str = json_encode($arr); echo $_GET['fn']."($str)";前端jq跨域的三种用法<script> $('#btu').click(function(){ //$.ajax 方法的jsonp跨域 $.ajax({ url:'http://bbs.com/1.php?fn=?', dataType:'jsonp', success:function(data){ alert(data.b); } }); //$.get 方法的jsonp跨域 $.get('http://bbs.com/1.php?fn=?',function(data){ alert(data.b); },'jsonp'); // $.getJSON 方法的jsonp跨域 $.getJSON( 'http://bbs.com/1.php?fn=?', function(data){ alert(data.b); }, ); }); </script>
2022年10月13日
135 阅读
0 评论
1 点赞
2022-10-13
javascript高级-Ajax技术
Ajax 技术作者:西岭老湿第1章 认识Ajax1.1 初识 ajax我们平常上网,不管是注册账号,还是浏览网页,其本质就是通过客户端向服务器发送请求,服务器接到请求后返回处理后的数据给客户端;在我们之前学习代码中,向服务器提交数据典型的应用是就是 form 表单,其中的 action 就是我们提交数据的服务器端地址;完成一个 form 表单;当我们点击提交按钮时,页面就会跳转到服务器页面;但是,我本不想让页面跳转,数据也能被发送到服务器端,同时,还可以接受服务器返回的数据;当我注册一个网站的账号时,填写完用户名并没有点击提交,但是,用户名如果有重复,文本框的傍边便会提示我更换用户名;类似的功能还有 验证短信的发送、百度搜索的关键字推举、无刷新的分页等等……想要完成这些类似的功能实现,我们今天所要学习的ajax技术,就是核心技术;ajax 也是技术名词的缩写:Asynchronous [ə'sɪŋkrənəs; eɪ-] :异步的;JavaScript :JavaScript语言And :和、与XML :数据传输格式1998年微软公司(Microsoft)的Outlook Web Access第一次使用了ajax技术,允许客户端脚本发送HTTP请求,并随后集成在IE4.0中应用(XMLHTTP),到2005年,谷歌(Google)把Ajax成功应用于自家的多款Web系统中(Gmail邮箱、Google Map、Google 搜索建议),从此Ajax被越来越多的人所接受…客户端通过HTTP向服务器发送请求1.2 快速入门<body> <form action="1-1-1.php" method="get"> <input type="text" name="names" value=""><br> <input type="button" value="提交"> </form> </body> <script> //获取DOM对象 var inp = document.getElementsByTagName('input'); //绑定点击事件 inp[1].onclick = function(){ //获取文本值 var v = inp[0].value; //获取ajax对象 var xhr = new XMLHttpRequest(); //监听状态变化 xhr.onreadystatechange = function(){ //判断状态值 if(xhr.readyState == 4){ //获取服务器返回信息 alert(xhr.responseText); } } //打开链接 xhr.open('get','/test'); //发送连接 xhr.send(); } </script>http.jsvar fs = require('fs'); // 服务器模块 var http = require('http'); var server = http.createServer(); server.listen(8080,function(){ console.log('服务器启动成功,请访问:http://127.0.0.1:8080') }) server.on('request',function(req,res){ var method = req.method; var urls = require('url').parse(req.url); if(method == 'GET'){ if(urls.pathname.indexOf('.html')>=0){ fs.readFile('.'+urls.pathname,function(err,data){ res.end(data); }) }else if(urls.pathname == '/test'){ res.end('123') } // console.log(urls.pathname); }else if(method == 'POST'){ }else{ res.end('err_method') } })第2章 Ajax对象2.1 获取对象通过上一节我们发现,想要使用 ajax 的一系列功能,我们就必须先得到 ajax 对象基于 W3C标准 浏览器:var xhr = new XMLHttpRequest();基于IE内核的浏览器:var xhr = new ActiveXObject('Microsoft.XMLHTTP');<script> var btu = document.getElementById('btu'); btu.onclick = function(){ //基于 W3C标准 浏览器 var xhr = new XMLHttpRequest(); alert(xhr); //基于IE内核的浏览器, W3C标准浏览器中报错 var xhr = new ActiveXObject('Microsoft.XMLHTTP'); alert(xhr); } </script>浏览器标准不一样,得到的对象也不一样,我们也不知道客户使用什么样的浏览器,因此,我们需要解决兼容性问题;修改上述代码并测试,具有兼容性:<script> var btu = document.getElementById('btu'); btu.onclick = function(){ try{ var xhr = new XMLHttpRequest() }catch(e){}; try{ var xhr = new ActiveXObject('Microsoft.XMLHTTP') }catch(e){}; alert(xhr); } </script>再次对代码进行修改 兼容代码封装进函数调用<script> var btu = document.getElementById('btu'); btu.onclick = function(){ //封装进函数供其他程序调用 function cXHR(){ try{return new XMLHttpRequest()}catch(e){}; try{return new ActiveXObject('Microsoft.XMLHTTP')}catch(e){}; } alert(cXHR()); } </script>将函数写入单独的文件,共其他地方引入调用创建createXHR.js将函数复制到文件 createXHR.js 内并保存, 如图:使用://文件引入 <script src="createXHR.js"></script> <script> var btu = document.getElementById('btu'); btu.onclick = function(){ //函数调用 alert(cXHR()); } </script>顺便封装一个方法:使用id属性获取DOM对象,方便后面使用function gid(id){ return document.getElementById(id); }2.2 ajax对象的属性、方法 *火狐开发者文档:https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest2.2.1 属性readyState: Ajax状态码 * 0:表示对象已建立,但未初始化,只是 new 成功获取了对象,但是未调用open方法1:表示对象已初始化,但未发送,调用了open方法,但是未调用send方法2:已调用send方法进行请求3:正在接收数据(接收到一部分),客户端已经接收到了一部分返回的数据4:接收完成,客户端已经接收到了所有数据 * status :http响应状态码200代表成功获取服务器端数据404未找到页面等等……statusText :http响应状态文本responseText:如果服务器端返回字符串,使用responseText进行接收responseXML :如果服务器端返回XML数据,使用responseXML进行接收onreadystatechange:当 readyState 状态码发生改变时所触发的回调函数2.2.2 方法open(method,url,[aycs]):初始化Ajax对象 (打开)method:http请求方式,get/posturl:请求的服务器地址aycs:同步与异步setRequestHeader(header,value):设置请求头信息header :请求头名称value :请求头的值xhr.getAllResponseHeaders() 获取全部响应头信息xhr.getResponseHeader('key') 获取指定头信息send([content]) :发送Ajax请求content : 如果是get请求时,此参数为null;如果是post请求时,此参数就是要传递的数据注意: 所有相关的事件绑定必须在调用send()方法之前进行.2.2.3 同步与异步例如,小明去餐馆排队点餐,前台服务员将小明的菜单告诉厨师进行制作,此时小明后面排队的人就一直等着,直到厨师制作完成,把饭菜送到小明手里后离开,后面的人才能继续点餐;这就是同步处理但是,如果前台服务员将小明的菜单告诉厨师后,服务员发给小明一个好牌去旁边等待,后面的人继续点餐,厨师将小明的饭菜做好后,随时呼唤小明就餐;这就是异步处理服务器的不同做法,就代表着 Ajax 的同步或异步处理;小明就是客户端;厨师就是后台服务器;图示:前台代码:<script src="createXHR.js"></script> <script> function t1(){ var xhr = cXHR(); xhr.onreadystatechange = function(){ if(this.readyState == 4){ alert(this.responseText); } } //false同步 //true 异步 xhr.open('get','/test',false); xhr.send(null); } function t2(){ alert('t2'); } t1(); t2(); </script>第3章 判断用户名是否可用--案例百度注册效果用户名被占用:用户名没有没占用:前台代码<body> <input type="text" value="" id="names"> <span id="tip"></span> </body> <script> var inp = document.getElementById('names'); inp.onblur = function () { var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { if (xhr.readyState == 4) { // alert(xhr.responseText); if (xhr.responseText == 1) { var h = '<font color="red">用户名已经被占用</font>'; document.getElementById('tip').innerHTML = h; } else { var h = '<font color="green">用户名可用</font>'; document.getElementById('tip').innerHTML = h; } } } xhr.open('get', '/baidu?names=' + inp.value); xhr.send(); } </script>http.jselse if(urls.pathname == '/test'){ res.end('123') }else if(urls.pathname == '/baidu'){ if(urls.query.names == 'admin'){ res.end('1') }else{ res.end('0') } }第4章 缓存问题4.1 缓存的产生以上一节的案例为模板,使用IE9以下版本浏览器测试,有缓存问题;原因:在Ajax的get请求中,如果运行在IE内核的浏览器下,其如果向同一个url发送多次请求时,就会产生所谓的缓存问题。缓存问题最早设计初衷是为了加快应用程序的访问速度,但是其会影响Ajax实时的获取服务器端的数据。4.2 客户端解决缓存问题产生缓存的问题就是 我们的客户端向同一个 url 发送了多次请求;如果我们每次请求的url不同,那么,缓存问题就不会存在了;我们可以在请求地址的后面加上一个无意义的参数,参数值使用随机数即可,那么每次请求都会产生随机数,URL就会不同,缓存问题就被解决了;Math.random():返回 0--1 之间的随机数,包括 0 但不包括 1;修改代码如下:var url = '03-1.php?names='+inp.value+'&_='+Math.random(); xhr.open('get',url); 但是,随机数虽然解决了问题,但是,我们不能保证每次生成的随机数都不一样;也就是说,使用随机数存在一定的隐患;new Date().getTime() : 获取当前时间的毫秒时间戳修改代码如下:var url = '03-1.php?names='+inp.value+'&_='+new Date().getTime(); xhr.open('get',url); 4.3 设置响应头禁用客户端缓存服务器端在相应客户端请求时,可以设置相应头详细,如:header(‘Content-type:text/html; charset=utf-8’) :告诉客户端浏览器,使用utf-8的编码格式解析html页面信息。设置不缓存的响应头标识即可://告诉客户端浏览器不要缓存数据 res.setHeader('Cache-Control','no-cache');第5章 Ajax发送POST请求5.1 post请求复制第3章案例代码,将 get 请求修改为 post 请求;//请求地址 var url = 'baidu'; //open参数为post xhr.open('post',url); //设置请求头 *** xhr.setRequestHeader('Content-type','application/x-www-form-urlencoded'); //设置post请求参数值 xhr.send('names='+inp.value); 5.2 无刷新修改信息将海贼王项目修改用户信息操作,改为ajax方式;第6章 Ajax框架的封装如果一个页面中有十几个地方用到Ajax,那么我们需要写十几次open()、十几次send()、十几次获取xhr对象;代码重复相当多,而凡是有代码重复的地方,就有封装的可能;创建新文件: ajax.js6.1 餐前甜点之前我们为了方便使用,封装过使用指定 id 获取DOM对象及获取xhr对象;我们对之前的代码进行一次修改,使其更加优雅;定义一个自调用匿名函数(function(){ //code…… })();为什么 定义一个自调用匿名函数?在实际项目开发中,如果一个项目同时引入了多个javascript框架,可能会产生命名的冲突问题,如果使用自调用匿名函数来封装javascript框架,所有变量处于封闭状态,就可以避免这个问题。封装一个$函数,用于获取指定id的dom对象(function(){ //封装$函数,获取指定 id 的DOM对象并返回给调用者 var $ = function(id){ return document.getElementById(id); } })();我们在前台代码中引入并使用ajax.js<body> <div id="d">div</div> </body> <script src="ajax.js"></script> <script> alert($('d')); </script>报错原因: 函数 $ 为局部变量;让 $ 局部变量全局化(function(){ //封装$函数,获取指定 id 的DOM对象并返回给调用者 var $ = function(id){ return document.getElementById(id); } //将局部变量 $ 复制给顶层window对象,使其成为全局变量 window.$ = $; })();6.2 封装get方法ajax代码我们都会写,问题是:如何把代码放进匿名函数中并且外部可以调用?(function(){ //封装$函数,获取指定 id 的DOM对象并返回给调用者 var $ = function(id){ return document.getElementById(id); } //将局部变量 $ 复制给顶层window对象,使其成为全局变量 window.$ = $; //声明gets方法 var gets = function(url){ var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function(){ if(xhr.readyState == 4){ alert(xhr.responseText); } } xhr.open('get',url); xhr.send(); } //将局部变量 gets 复制给顶层window对象,使其成为全局变量 window.ajax_get = gets; })();这样写并没有语法错误,也可以正常调用,但是,随着功能的不断增加,我们的window对象也会被赋予各种各样的值,最终还是会导致混乱;在JavaScript中一切都是对象$ 也可以被当作对象,我们就可以将ajax函数赋值给 $ ;(function(){ //封装$函数,获取指定 id 的DOM对象并返回给调用者 var $ = function(id){ return document.getElementById(id); } //声明ajax函数,并复制给$; $.get = function(url){ var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function(){ if(xhr.readyState == 4){ alert(xhr.responseText); } } xhr.open('get',url); xhr.send(); } window.$ = $; })();前台调用<script> $.get('/test'); </script>6.3 解决获取Ajax对象的兼容性修改上节代码://获取Ajax对象 $.init = function(){ try{return new XMLHttpRequest()}catch(e){}; try{return new ActiveXObject('Microsoft.XMLHTTP')}catch(e){}; } //声明ajax函数,并复制给$; $.get = function(url){ var xhr = $.init(); //调用init,获取ajax对象 xhr.onreadystatechange = function(){ if(xhr.readyState == 4){ alert(xhr.responseText); } } xhr.open('get',url); xhr.send(); }6.4 获取Ajax的返回值前台调用:<script> var cb = function(msg){ $('d').innerHTML = msg; } $.get('/test',cb); </script> 修改 ajax.js$.get = function(url,callback){ var xhr = $.init(); //调用init,获取ajax对象 xhr.onreadystatechange = function(){ if(xhr.readyState == 4){ callback(xhr.responseText); } } xhr.open('get',url); xhr.send(); }前台调用修改:<script> // var cb = function(msg){ // $('d').innerHTML = msg; // } $.get('09-1.php',function(msg){ $('d').innerHTML = msg; }); </script>6.5 配合后台获取不同的返回值类型修改 ajax.js//声明ajax函数,并复制给$; $.get = function(url,callback,type=null){ var xhr = $.init(); //调用init,获取ajax对象 xhr.onreadystatechange = function(){ if(xhr.readyState == 4){ if(type==null){ callback(xhr.responseText); } if(type=='json'){ var t = JSON.parse(xhr.responseText); callback(t); } } } xhr.open('get',url); xhr.send(); }前台调用,代码修改:<script> $.get('/test',function(msg){ console.log(msg); },'json'); </script>6.6 练习封装 POST 方法到 ajax.js第10章 跨域问题的解决方案10.1 认识jsonp<script src="ajax.js"> </script> <script> $.get('http://127.0.0.1:9000',function(){}); </script>ajax 请求的URL地址,不在当前域名下,就会出现一下错误:同源策略,也叫跨域禁止策略;阻止从一个域上加载的脚本,获取或操作另一个域上的资源;但是,公司内部系统的数据交互就无法进行:公司OA系统 :http://oa.itcast.cn公司ERP系统 :http://erp.itcast.cn公司ESM系统 :http://esm.itcast.cn而Web页面上调用js文件时则不受是否跨域的影响(不仅如此,我们还发现凡是拥有"src"这个属性的标签都拥有跨域的能力,比如script、img、iframe);src 的能力就是把远程的数据资源加载到本地(图片、JS代码等);前台代码:<script src="ajax.js"> </script> <script> //提前写好函数,调用函数需要传参 function cb(msg){ console.log(msg); } </script> <!--src加载进来的代码就是一个JS的函数调用,cb函数调用 --> <script src="http://bbs.com/1.php"></script>后台PHP代码:$arr = ['a'=>1,'b'=>'san','c'=>'wu','d'=>4]; $str = json_encode($arr); //返回字符串,JS代码的函数调用 //要返回的数据作为函数传参传递 echo "cb(".$str.")";修改前后台代码,增加灵活性;前台代码:<script src="ajax.js"> </script> <script> //提前写好函数,调用函数需要传参 function callback(msg){ console.log(msg); } </script> <!--src加载进来的代码就是一个JS的函数调用,cb函数调用 --> <!--地址get传参,告知后台函数调用名称 --> <script src="http://bbs.com/1.php?cb=callback"></script>后台PHP代码:$arr = ['a'=>1,'b'=>'san','c'=>'wu','d'=>4]; $str = json_encode($arr); //返回字符串,JS代码的函数调用 //要返回的数据作为函数传参传递 //接受参数拼接,作为函数调用名称 echo $_GET['cb']."($str)";10.2 如何使用JSONP<body> <input type="button" id="btu" value="点击"> </body> <script src="ajax.js"> </script> <script> //提前写好函数,调用函数需要传参 function callback(msg){ console.log(msg); } //动态添加script标签及src属性 $('btu').onclick = function(){ var sc = document.createElement('script'); sc.src = "http://bbs.com/2.php?cb=callback"; document.getElementsByTagName('head')[0].appendChild(sc); } </script>就是在远程服务器上设法动态的把数据装进js格式的文本代码段中,供客户端调用和进一步处理;在前台通过动态添加script标签及src属性,表面看上去与ajax极为相似,但是,这和ajax并没有任何关系;为了便于使用及交流,逐渐形成了一种 非正式传输协议,人们把它称作 JSONP ;该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。10.3 跨域资源共享( CORS)机制https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORSphp代码中添加一下header头声明:Access-Control-Allow-Origin: //域名, 允许所有php:(服务端代码)<?php header('Access-Control-Allow-Origin:http://localhost'); echo 1
2022年10月13日
174 阅读
0 评论
1 点赞
1
2
3