首页
留言
友情链接
标签页
Search
1
如何使用JavaScript获取和设置CSS root变量值
1,072 阅读
2
中国历史朝代顺序图
677 阅读
3
那些顶级不落俗套的“美好祝福”
560 阅读
4
春和 《江海共余生》
531 阅读
5
hyperf常用命令
411 阅读
分享
Web前端
html&css
javascript
Vue
shopify
shoplazza
后端
ThinkPHP
YII2
服务器端
软件安装
问题合集
故事
诗词
生活
学习
学科
语文
数学
英语
物理
化学
生物
政治
历史
地理
自然
其他
抖音
快手
小视频
随笔
易经
书摘
登录
/
注册
Search
标签搜索
一年级语文
sunshine
累计撰写
162
篇文章
累计收到
15
条评论
首页
栏目
分享
Web前端
html&css
javascript
Vue
shopify
shoplazza
后端
ThinkPHP
YII2
服务器端
软件安装
问题合集
故事
诗词
生活
学习
学科
语文
数学
英语
物理
化学
生物
政治
历史
地理
自然
其他
抖音
快手
小视频
随笔
易经
书摘
页面
留言
友情链接
标签页
搜索到
161
篇与
的结果
2022-10-31
常用偏门CSS汇总
常用偏门CSS汇总
2022年10月31日
153 阅读
0 评论
1 点赞
2022-10-27
Shopify,Shoplaza平台全局参数一览
shopifypurchase事件中:订单号:{{ order.order_number }} 订单金额:{{ total_price | times: 0.01 }} 运费:{{ shipping_price | times: 0.01 }} 币种:{{ order.currency }}Shoplazapurchase事件中订单号:{{ checkout.order_id }} 金额:{{ checkout.total_price }} 订单总金额(check.total_price) = 商品优惠后的总价(check.line_items_subtotal_price) + 税费(check.tax_price) + 物流费(check.shipping_price)计算销售额Shopify: sale = subtotal_price + total_shipping Shoplaza: sale = sub_total - total_discount + total_tax + total_shipping获取collection产品信息shopify: {% assign collection = section.settings.collection %} {% assign products = collections[collection].products %} {% for product in products %} {% assign price = product.price | money_with_currency %} {% assign retailPrice = product.compare_at_price | money_with_symbol %} {% assign productImage = product.images[0].src | img_url: '640x' %} {% assign url = product.url %} {% endfor %}shoplaza: {% assign collection = section.settings.collection %} {% assign products = collections[collection.id].products %} {% for product in products %} {% assign price = product.price | money_with_symbol %} {% assign retailPrice = product.compare_at_price | money_with_symbol %} {% assign productImage = product.image.src | img_url: '640x' %} {% assign url = product.url %} {% endfor %}shoplaza获取单个产品自定义属性(json格式时)和其他产品参数信息 {% assign product = all_products[section.settings.product.id] %} {% assign icons = product.metafields.sunshine.show_case.value.icons %}
2022年10月27日
105 阅读
0 评论
4 点赞
2022-10-15
唐诗三百首(6-10)
危楼高百尺,手可摘星辰。不敢高声语,恐惊天上人。
2022年10月15日
57 阅读
0 评论
0 点赞
2022-10-13
javascript框架-Vue
Vue.js西岭老湿第0章 Vue介绍0.0 开发工程发展历史通过前面的介绍,我们对目前的项目工程化有了大体了了解,那么其中,在第二阶段的工程化演进中,有一个重要的工程设计理念诞生,他就是著名的 MVC 设计模式,简单点,MVC 其实就是为了项目工程化的一种分工模式;MVC 中的最大缺点就是单项输入输出,所有的 M 的变化及 V 层的变化,必须通过 C 层调用才能展示;随着前端技术及前端工程化体系的发展成熟,参考MVC的设计理念,前端出现了 MVVM 的设计思想,简单理解就是在前端实现数据层与展示层的相互调用,降低业务层面的交互逻辑;后面再进行详细介绍;0.1 Vue 介绍Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的 渐进式框架。注意:Vue是一个框架,相对于 jq 库来说,是由本质区别的;https://cn.vuejs.org/Vue 不支持 IE8 及以下版本,因为 Vue 使用了 IE8 无法模拟的 ECMAScript 5 特性。但它支持所有兼容 ECMAScript 5 的浏览器。0.2 Vue 初体验直接下载引入:https://cn.vuejs.org/v2/guide/installation.htmlCDN 引入:<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>CDN 加速: https://www.bootcdn.cn/<body> <div id="div"> {{user_name}} </div> </body> // 两种引入方式,任意选择 <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script> <script src="./vue.js"></script> <script> var app = new Vue({ el:'#div', // 设置要操作的元素 // 要替换的额数据 data:{ user_name:'我是一个div' } }) </script>第1章 Vue 实例对象每个 Vue 应用都是通过用 Vue 函数创建一个新的 Vue 实例 开始的:var vm = new Vue({ // 选项 })<body> <div id="div"> {{user_name}} </div> </body> <script src="./vue.js"></script> <script> var app = new Vue({ el:'#div', // 设置要操作的元素 // 要替换的额数据 data:{ user_name:'我是一个div' } }) // 打印Vue实例对象 console.log(app); </script>通过打印实例对象发现,其中 el 被Vue 放入了公有属性中,而data 则被放入了 私有属性中,而 data 中的数据,需要被外部使用,于是 Vue 直接将data 中的属性及属性值,直接挂载到 Vue 实例中,也就是说,data中的数据,我们可以直接使用 app.user_name 直接调用;var app = new Vue({ el:'#div', // 设置要操作的元素 // 要替换的额数据 data:{ user_name:'我是一个div', user:222222 } }) console.log(app.user_name);第 2 章 模板语法-插值我们在前面的代码中,使用 {{}} 的形式在 html 中获取实例对象对象中 data 的属性值;这种使用 {{}} 获取值得方式,叫做 插值 或 插值表达式 ;2.1 文本数据绑定最常见的形式就是使用“Mustache”语法 (双大括号) 的文本插值:<span>Message: {{ msg }}</span>Mustache 标签将会被替代为对应数据对象上 msg 属性的值。无论何时,绑定的数据对象上 msg 属性发生了改变,插值处的内容都会更新。即便数据内容为一段 html 代码,仍然以文本内容展示<body> <div id="div"> 文本插值 {{html_str}} </div> </body> <script> var app = new Vue({ el:'#div', data:{ html_str:'<h2>Vue<h2>' } }) </script>浏览器渲染结果:<div id="div">文本插值 <h2>Vue<h2></div>打开浏览器的 REPL 环境 输入 app.html_str = '<s>vue</s>'浏览器渲染结果就会立刻发生改变: <div id="div">文本插值 <s>vue</s></div>2.2 使用 JavaScript 表达式迄今为止,在我们的模板中,我们一直都只绑定简单的属性键值。但实际上,对于所有的数据绑定,Vue.js 都提供了完全的 JavaScript 表达式支持,但是不能使用 JS 语句;(表达式是运算,有结果;语句就是代码,可以没有结果)<body> <div id="div" > {{ un > 3 ? '大' : '小'}} {{ fun() }} </div> </body> <script> var app = new Vue({ el:'#div', data:{ un:2, fun:()=> {return 1+2} } }) </script>第3章 模板语法-指令指令 (Directives) 是带有 v- 前缀的特殊 特性 相当于自定义html属性。指令特性的值预期是单个 JavaScript 表达式 (v-for 是例外情况,稍后我们再讨论)。指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM;参考 手册 、 API<body> <div id="div" > <p v-if="seen">现在你看到我了</p> </div> </body> <script> var app = new Vue({ el:'#div', data:{ seen:false } }) </script>这里,v-if 指令将根据表达式 seen 的值的真假来插入/移除 <p> 元素。3.1 v-text / v-html 文本https://cn.vuejs.org/v2/api/#v-texthttps://cn.vuejs.org/v2/api/#v-html<body> <div id="div" {{class}}> <p v-text="seen"></p> <p v-html="str_html"></p> </div> </body> <script> var app = new Vue({ el:'#div', data:{ seen:'<h1>Vue</h1>', str_html:'<h1>Vue</h1>', class:'dd', } }) </script>注意:v-textv-text和差值表达式的区别v-text 标签的指令更新整个标签中的内容(替换整个标签包括标签自身)差值表达式,可以更新标签中局部的内容v-html可以渲染内容中的HTML标签尽量避免使用,否则会带来危险(XSS攻击 跨站脚本攻击)HTML 属性不能用 {{}} 语法3.2 v-bind 属性绑定https://cn.vuejs.org/v2/api/#v-bind可以绑定标签上的任何属性。动态绑定图片的路径<img id=“app” v-bind:src="src" /> <script> var vm = new Vue({ el: '#app', data: { src: '1.jpg' } }); </script>绑定a标签上的id<a id="app" v-bind:href="'del.php?id=' + id">删除</a> <script> var vm = new Vue({ el: '#app', data: { id: 11 } }); </script>绑定class对象语法和数组语法对象语法如果isActive为true,则返回的结果为 <div id="app" class="active"></div><div id="app" v-bind:class="{active: isActive}"> hei </div> <script> var vm = new Vue({ el: '#app', data: { isActive: true } }); </script>数组语法渲染的结果: <div id="app" class="active text-danger"></div><div id="app" v-bind:class="[activeClass, dangerClass]"> hei </div> <script> var vm = new Vue({ el: '#app', data: { activeClass: 'active', dangerClass: 'text-danger' } }); </script>绑定style对象语法和数组语法对象语法渲染的结果: <div id="app" style="color: red; font-size: 40px;">hei</div><div id="app" v-bind:style="{color: redColor, fontSize: font + 'px'}"> hei </div> <script> var vm = new Vue({ el: '#app', data: { redColor: 'red', font: 40 } }); </script>数组语法渲染结果:<div id="app" style="color: red; font-size: 18px;">abc</div><div id="app" v-bind:style="[color, fontSize]">abc</div> <script> var vm = new Vue({ el: '#app', data: { color: { color: 'red' }, fontSize: { 'font-size': '18px' } } }); </script>v-bind 简化语法<div id="app"> <img v-bind:src="imageSrc"> <!-- 缩写 --> <img :src="imageSrc"> </div> <script> var vm = new Vue({ el: '#app', data: { imageSrc: '1.jpg', } }); </script>3.3 数据绑定3.3.1 单向数据绑定<div id="div"> <input type="text" :value="input_val"> </div> <script> var app = new Vue({ el: '#div', data: { input_val: 'hello world ' } }) </script>浏览器渲染结果: <div id="div"><input type="text" value="hello world"></div>通过浏览器 REPL 环境可以进行修改 app.input_val = 'Vue'浏览器渲染结果: <div id="div"><input type="text" value="Vue"></div>我们通过 vue 对象修改数据可以直接影响到 DOM 元素,但是,如果直接修改 DOM 元素,却不会影响到 vue 对象的数据;我们把这种现象称为 单向数据绑定 ;3.3.2 双向数据绑定 v-modelhttps://cn.vuejs.org/v2/api/#v-model<div id="div"> <input type="text" v-model="input_val" > </div> <script> var app = new Vue({ el: '#div', data: { input_val: 'hello world ' } }) </script>通过 v-model 指令展示表单数据,此时就完成了 双向数据绑定 ;不管 DOM 元素还是 vue 对象,数据的改变都会影响到另一个;注意:数据绑定是目前所有MVVM前端框架的核心特性;甚至可以说,没有数据绑定就不能算是框架;3.3.3 双向数据绑定的应用范围文本框 & 文本域<div id="div"> <textarea v-model="inp_val"></textarea> <div>{{ inp_val }}</div> </div> <script> var app = new Vue({ el: '#div', data: { inp_val: '' } }) </script>绑定复选框<div id="div"> 吃饭:<input type="checkbox" value="eat" v-model="checklist"><br> 睡觉:<input type="checkbox" value="sleep" v-model="checklist"><br> 打豆豆:<input type="checkbox" value="ddd" v-model="checklist"><br> {{ checklist }} </div> <script> var vm = new Vue({ el: '#div', data: { checklist: '' // checklist: [] } }); </script>绑定单选框<div id="app"> 男<input type="radio" name="sex" value="男" v-model="sex"> 女<input type="radio" name="sex" value="女" v-model="sex"> <br> {{sex}} </div> <script> var vm = new Vue({ el: '#app', data: { sex: '' } }); </script>修饰符.lazy - 取代 input 监听 change 事件.number - 输入字符串转为有效的数字.trim - 输入首尾空格过滤<div id="div"> <input type="text" v-model.lazy="input_val"> {{input_val}} </div> <script> var app = new Vue({ el: '#div', data: { input_val: 'hello world ' } }) </script>3.4 v-on 绑定事件监听https://cn.vuejs.org/v2/api/#v-onhttps://cn.vuejs.org/v2/guide/events.html3.4.1 基本使用<div id="app"> <input type="button" value="按钮" v-on:click="cli"> </div> <script> var vm = new Vue({ el: '#app', data: { cli:function(){ alert('123'); } } }); </script>上面的代码运行是没有问题的,但是,我们不建议这样做,因为 data 是专门提供数据的对象,事件触发需要执行的是一段代码,需要的是一个方法 (事件处理程序) ;修改代码如下:<div id="app"> <!-- 使用事件绑定的简写形式 --> <input type="button" value="按钮" @click="cli"> </div> <script> var vm = new Vue({ el: '#app', data: {}, // 将事件处理程序写入methods对象 methods: { cli: function () { alert('123'); } } }); </script>向事件处理器中传参<div id="app"> <!-- 直接调用传参即可 --> <input type="button" value="按钮" @click="cli(1,3)"> </div> <script> var vm = new Vue({ el: '#app', data: {}, methods: { // 接受参数 cli: function (a,b) { alert(a+b); } } }); </script>而此时,如果在处理器中需要使用事件对象,则无法获取,我们可以用特殊变量 $event 把它传入方法<input type="button" value="按钮" @click="cli(1,3,$event)">methods: { // 接受参数 cli: function (a,b,ev) { alert(a+b); console.log(ev); } }3.4.2 事件修饰符原生 JS 代码,想要阻止浏览器的默认行为(a标签跳转、submit提交),我们要使用事件对象的 preventDefault() 方法<div id="app"> <a href="http://www.qq.com" id="a">腾百万</a> </div> <script> document.getElementById('a').onclick = (ev)=>{ // 组织浏览器的默认行为 ev.preventDefault(); } </script>使用修饰符 阻止浏览器的默认行为<div id="app"> <a href="http://www.qq.com" @click.prevent="cli">腾百万</a> </div> <script> var vm = new Vue({ el: '#app', data: {}, // 将事件处理程序写入methods对象 methods: { cli: function () { alert('123'); } } }); </script>使用修饰符绑定一次性事件<div id="app"> <a href="http://www.qq.com" @click.once="cli($event)">腾百万</a> </div> <script> var vm = new Vue({ el: '#app', data: {}, // 将事件处理程序写入methods对象 methods: { cli: function (ev) { ev.preventDefault(); alert('123'); } } }); </script>3.4.3 按键修饰符绑定键盘抬起事件,但是只有enter 键能触发此事件<div id="app"> <input type="text" @keyup.enter="keyup"> </div> <script> var vm = new Vue({ el: '#app', data: {}, methods: { keyup:()=>{ console.log('111') } } }); </script>3.4.4 系统修饰符按住 shift 后才能触发点击事件<div id="app"> <input type="button" value="按钮" @click.shift="cli"> </div> <script> var vm = new Vue({ el: '#app', data: {}, methods: { cli:()=>{ console.log('111') } } }); </script>3.4.5 鼠标修饰符鼠标中键触发事件<div id="app"> <input type="button" value="按钮" @click.middle="cli"> </div> <script> var vm = new Vue({ el: '#app', data: {}, methods: { cli:()=>{ console.log('111') } } }); </script>3.4.6 为什么在 HTML 中监听事件?你可能注意到这种事件监听的方式违背了关注点分离 (separation of concern) 这个长期以来的优良传统。但不必担心,因为所有的 Vue.js 事件处理方法和表达式都严格绑定在当前视图的 ViewModel 上,它不会导致任何维护上的困难。实际上,使用 v-on 有几个好处:扫一眼 HTML 模板便能轻松定位在 JavaScript 代码里对应的方法。因为你无须在 JavaScript 里手动绑定事件,你的 ViewModel 代码可以是非常纯粹的逻辑,和 DOM 完全解耦,更易于测试。当一个 ViewModel 被销毁时,所有的事件处理器都会自动被删除。你无须担心如何清理它们。3.5 v-show 显示隐藏https://cn.vuejs.org/v2/api/#v-show根据表达式之真假值,切换元素的 display CSS 属性。<div id="app"> <p v-show="is_show">Vue</p> </div> <script> var vm = new Vue({ el:'#app', data:{ is_show:false }, methods:{}, }) </script>案例:点击按钮切换隐藏显示<div id="app"> <input type="button" value="按钮" @click="isshow"> <p v-show="is_show">Vue</p> </div> <script> var vm = new Vue({ el:'#app', data:{ is_show:false }, methods:{ isshow:function(){ this.is_show = !this.is_show; } }, }) </script>3.6 v-if / v-else / v-else-if 条件判断https://cn.vuejs.org/v2/api/#v-if<div id="app"> <div v-if="type === 'A'"> A </div> <div v-else-if="type === 'B'"> B </div> <div v-else-if="type === 'C'"> C </div> <div v-else> Not A/B/C </div> </div> <script> var vm = new Vue({ el: '#app', data: { type: 'F' }, }) </script>3.7 v-for 循环https://cn.vuejs.org/v2/api/#v-for<div id="app"> <ul> <li v-for="(val,key) in arr">{{val}}---{{key}}</li> </ul> <ul> <li v-for="(val,key) in obj">{{val}}---{{key}}</li> </ul> </div> <script> var vm = new Vue({ el: '#app', data: { arr: ['a', 'b', 'c'], obj: { id: 1, name: '李四' } }, }) </script>3.8 v-cloakhttps://cn.vuejs.org/v2/api/#v-cloak和 CSS 规则如 [v-cloak] { display: none } 一起用时,这个指令可以隐藏未编译的 Mustache 标签直到实例准备完毕。<div id="app"> <p>{{obj.id}}</p> </div> <script src="./vue.js"></script> <script> setTimeout(() => { var vm = new Vue({ el: '#app', data: { arr: ['a', 'b', 'c'], obj: { id: 1, name: '李四' } }, }) }, 2000); </script>当我们的网络受阻时,或者页面加载完毕而没有初始化得到 vue 实例时,DOM中的 {{}} 则会展示出来;为了防止现象,我们可以使用 CSS 配合 v-cloak 实现获取 VUE 实例前的隐藏;<style> [v-cloak] { display: none; } </style> <div id="app"> <p v-cloak>{{obj.id}}</p> </div> <script src="./vue.js"></script> <script> setTimeout(() => { var vm = new Vue({ el: '#app', data: { obj: { id: 1, name: '李四' } }, }) }, 2000); </script>3.9 v-oncehttps://cn.vuejs.org/v2/api/#v-once只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过<div id="app"> <p v-once>{{msg}}</p> </div> <script> var vm = new Vue({ el: '#app', data: { msg:'kkk' }, }) </script>第4章 TodoList 案例上市产品: ToDoList 、奇妙清单 、滴答清单学习练手项目 : TodoMVC 、 Vue官方示例为什么选择这样的案例:产品功能简洁,需求明确,所需知识点丰富;实现基本功能容易,涵盖所学基础知识;而可扩展性强,完善所有功能比较复杂,所需技术众多;在学习中,可以灵活取舍;4.1 项目初始化在项目目录中执行 npm install 命令,下载所需静态资源 ; 将Vue.js框架代码,复制到 js 目录,在index.html中引入 vue : <script src="./js/vue.js"></script>同时 在 index.html 最下方,项目引入了app.js ; 而我们要写的 vuejs 代码,都放在这个文件中;4.2 数据遍历const list_data = [ {id:1,title:'吃饭',stat:true}, {id:2,title:'睡觉',stat:false}, {id:3,title:'打豆豆',stat:true}, ] new Vue({ el:'#todoapp', data:{ // list_data:list_data, list_data,// es6属性简写 } })<ul class="todo-list"> <li v-for="(val,key) in list_data"> <div class="view"> <input class="toggle" type="checkbox" v-model="val.stat"> <label>{{val.title}}</label> <button class="destroy"></button> </div> <input class="edit" value="Rule the web"> </li> </ul>4.3 展示无数据状态标签及内容都是在 section footer 两个标签中的,当 list_data 中没有数据时,我们只需要隐藏这个两个标签即可:<section v-if="list_data.length" class="main"> …… </section> <footer v-if="list_data.length" class="footer"> …… </footer>两个标签都有 v-if 判断 ,因此我们可以使用一个 div 包裹两个标签,使 div 隐藏即可:<div v-if="list_data.length"> <section class="main"> …… </section> <footer class="footer"> …… </footer> </div>如果有内容,那么 DOM 书中就会多出一个 div 标签,那么我们可以选择使用 template (vue中的模板标识),有内容时,浏览器渲染不会有此节点;<template v-if="list_data.length"> <section class="main"> …… </section> <footer class="footer"> …… </footer> </template>4.3 添加任务绑定 enter 键盘事件:<input @keyup.enter="addTodo" class="new-todo" placeholder="请输入" autofocus>new Vue({ el:'#todoapp', data:{ // list_data:list_data, list_data,// es6属性简写 }, //添加事件处理器 methods:{ // addTodo:function(){} // 简写形式 addTodo(){ console.log(123); } } })修改代码完成任务添加:methods: { // 添加任务 // addTodo:function(){} // 简写形式 addTodo(ev) { // 获取当前触发事件的元素 var inputs = ev.target; // 获取value值,去除空白后判断,如果为空,则不添加任务 if (inputs.value.trim() == '') { return; } // 组装任务数据 var todo_data = { id: this.list_data.length + 1 + 1, title: inputs.value, stat: false }; // 将数据添加进数组 this.list_data.push(todo_data); // 清空文本框内容 inputs.value = ''; } }4.4 任务的全选与反选点击文本框左边的下箭头,实现全选和反选操作为元素绑定点击事件:<input @click="toggleAll" id="toggle-all" class="toggle-all" type="checkbox">添加处理程序:toggleAll(ev){ // 获取点击的元素 var inputs = ev.target; // console.log(inputs.checked); // 循环所有数据为状态重新赋值 // 因为每个元素的选中状态都是使用 v-model 的双向数据绑定, // 因此 数据发生改变,状态即改变,状态改变,数据也会改变 for(let i=0;i<this.list_data.length;i++){ this.list_data[i].stat = inputs.checked; } }4.5 完成任务如果任务完成,状态改为选中, li 的 class 属性为 completed 时文字有中划线;<li v-for="(val,key) in list_data" v-bind:class="{completed:val.stat}">4.6 删除任务绑定点击事件,将当前索引值传入事件处理程序:<button @click="removeTodo(key)" class="destroy"></button>按照索引,删除相应的数据:removeTodo(key){ this.list_data.splice(key,1); },4.7 删除已完成的任务绑定事件<button @click="removeAllDone" class="clear-completed">Clear completed</button>循环遍历所有数据,删除已被标记为完成的任务:removeAllDone(){ for(let i=0;i<list_data.length;i++){ if(list_data[i].stat == true){ this.list_data.splice(i,1); } } }循环的代码看起来很不舒服, Array.prototype.filter() 方法创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。var arr = [1,4,6,2,78,23,7,3,8]; // 原始写法 // var new_arr = arr.filter(function(v){ // // if(v>8){ // // return true; // // } // return v>8; // }) // 箭头函数写法 // var new_arr = arr.filter((v)=>{ // return v>8; // }) // 精简写法 var new_arr = arr.filter((v)=> v>8); console.log(new_arr);修改项目代码:removeAllDone(){ // 原始循环判断用法 // for(let i=0;i<list_data.length;i++){ // if(list_data[i].stat == true){ // this.list_data.splice(i,1); // } // } // 上面是循环删除符合条件的数据 // 下面是保留不符合条件的数据 // 原始标准库对象方法 // this.list_data = this.list_data.filter(function(v){ // if(v.stat == false){ // return true; // } // }) // 箭头函数方法 // this.list_data = this.list_data.filter(function(v){ // return !v.stat; // }) // 精简方法 this.list_data = this.list_data.filter((v)=>!v.stat); },TodoList案例暂时告一段落,我们并没有将产品做完,因为我们需要用到其他知识了;第5章 MVVM设计思想MVC 设计思想:M: model 数据模型层 提供数据V: Views 视图层 渲染数据C: controller 控制层 调用数据渲染视图MVVM 设计思想:M: model 数据模型层 提供数据V: Views 视图层 渲染数据VM:ViewsModel 视图模型层 调用数据渲染视图 由数据来驱动视图(不需要过多考虑dom操作,把重心放在VM)第6章 其他知识点汇总6.1 计算属性与侦听器6.1.1 计算属性<div id="div"> <input type="text" v-model="xing"> <input type="text" v-model="ming"> {{xing + ming}} </div> <script> var app = new Vue({ el: '#div', data: { xing:'', ming:'', } }) </script>模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。因此我们可以使用方法,来进行运算并返回数据:<div id="div"> <input type="text" v-model="xing"> <input type="text" v-model="ming"> {{ fullname() }} <!-- 一百次调用,观察时间结果--> {{ fullname() }} </div> <script> var app = new Vue({ el: '#div', data: { xing:'', ming:'', }, methods:{ fullname(){ return this.xing+this.ming+Date.now(); } } }) </script>注意,每次在模板中使用 {{ fullname() }} fullname方法就会被调用执行一次;所以,对于任何复杂逻辑,你都应当使用计算属性 ,因为计算属性,会自动缓存数据:<div id="div"> <input type="text" v-model="xing"> <input type="text" v-model="ming"> <br> {{fulln}} <!-- 一百次调用 --> {{fulln}} </div> <script> var app = new Vue({ el: '#div', data: { xing:'', ming:'', }, computed:{ fulln(){ return this.xing+this.ming+Date.now(); } } }) </script>我们可以将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。然而,不同的是计算属性是基于它们的依赖进行缓存的。只在相关依赖发生改变时它们才会重新求值;多次调用,计算属性会立即返回之前的计算结果,而不必再次执行函数。6.1.2 利用计算属性获取未完成任务个数<span class="todo-count"><strong>{{getNu}}</strong> item left</span>computed: { // 未完成任务个数 getNu() { return (this.list_data.filter((v) => !v.stat)).length; } }6.1.3 使用侦听器<div id="div"> <input type="text" v-model="xing"> <input type="text" v-model="ming"> {{ fullname }} </div> <script> var app = new Vue({ el: '#div', data: { xing: '', ming: '', fullname:'' }, // 设置侦听器 watch: { // 侦听器中的方法名和要真挺的数据属性名必须一致 // xing 发生变化,侦听器就会被执行,且将变化后的值和变化前的值传入 xing:function(newVal,old_val){ this.fullname = newVal+this.ming; }, ming:function(newVal,oldVal){ this.fullname = this.xing+newVal; } } }) </script>通过上面的案例,我们基本掌握了侦听器的使用,但是我们也发现,与计算属性相比,侦听器并没有优势;也不见得好用,直观上反而比计算属性的使用更繁琐;虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。这就是为什么 Vue 通过 watch 选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。<div id="div"> <input type="text" v-model="xing"> <input type="text" v-model="ming"> {{ fullname }} </div> <script src="./jq.js"></script> <script> var app = new Vue({ el: '#div', data: { xing: '', ming: '', fullname:'' }, // 设置侦听器 watch: { // 侦听器中的方法名和要真挺的数据属性名必须一致 // xing 发生变化,侦听器就会被执行,且将变化后的值和变化前的值传入 xing:function(newVal,old_val){ // this.fullname = newVal+this.ming; var t = this; // 在侦听器中执行异步网络请求 $.get('./xx.php',(d)=>{ t.fullname = d; }) }, } }) </script>6.2 使用ref操作DOM在学习 jq 时,我们首要任务就是学习选择的使用,因为选择可以极其方便帮助我们获取节点查找dom,因为我们要通过dom展示处理数据。而在Vue中,我们的编程理念发生了变化,变为了数据驱动dom;但有时我们因为某些情况不得不脱离数据操作dom,因此vue为我们提供了 ref 属性获取dom节点;<div id="app"> <input type="button" @click='click' value="按钮"> <br> <p ref="pv">123</p> </div> <script> var app = new Vue({ el: '#app', methods: { click: function () { // 使用原生JS获取dom数据 // var p = document.getElementsByTagName('p')[0].innerHTML; // console.log(p); // 使用vue ref 属性获取dom数据 var d = this.$refs.pv.innerHTML; console.log(d); } } }) console.log(app.$refs); </script>但是在项目开发中,尽可能不要这样做,因为从一定程度上,ref 违背的mvvm设计原则;6.3 过滤器的使用6.3.1 私有(局部)过滤器定义过滤器var app = new Vue({ el: '#app', data:{msg:'UP'}, //定义过滤器 filters:{ // 过滤器的名称及方法 myFilters:function(val){ return val.toLowerCase(); } } })过滤器的使用:Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化转义等操作。过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 (后者从 2.1.0+ 开始支持)。过滤器要被添加到操作值得后面,使用 管道符 | 分割;vue会自动将操作值,以实参的形式传入过滤器的方法中;{{msg|myFilters}}过滤敏感词汇<div id="app"> <input type="text" v-model="msg"> <br> {{msg|myFilters|get3}} </div> <script> var app = new Vue({ el: '#app', data:{ msg:'' }, //定义过滤器 filters:{ // 过滤器的名称及方法 myFilters:function(val){ return val.toLowerCase(); }, get3:function(val){ // 遇到数字替换为 0 // var reg = /\d/g; // return val.replace(reg,0); return val.replace('苍井空','***'); } } }) </script>6.3.2 全局过滤器上面的代码中,myFilters 及 get3 两个过滤器,仅在当前 vue 实例中可用;如果在代码 再次 var app2 = new Vue() 得到变量为 app2 的 vue 实例,则两个过滤器在 app2中都不可用;如果需要过滤器在所有实例对象中可用,我们需要声明 全局过滤器 Vue.filter(名称,处理器)<div id="app"> <input type="text" v-model="msg"> <br> {{msg|myFilters}} </div> <!-- 定义两个DOM节点 --> <div id="app2"> <input type="text" v-model="msg"> <br> {{msg|myFilters|get3}} </div> <script> Vue.filter('myFilters', function (val) { return val.toLowerCase(); }) // 定义两个全局过滤器 Vue.filter('get3', function (val) { return val.replace('苍井空','***'); }) // 两个Vue 实例 var app = new Vue({ el: '#app', data: { msg: '' } }) var app2 = new Vue({ el: '#app2', data: { msg: '' } }) </script>6.4 自定义指令前面我们学过 v-on 、v-model、v-show 等指令,在操作 dom 时使用了 ref 属性,其实之前学过的指令也是操作dom 的一种方式,但有时,这些指令并不能满足我们的需求,因此 vue 允许我们自定义指令来操作 dom6.4.1 全局自定义指令<div id="app"> <p v-setcolor>自定义指令的使用</p> </div> <script> // 注册一个全局自定义指令 `v-focus` Vue.directive('setcolor', { // 当被绑定的元素插入到 DOM 中时…… inserted: function (el) { // 聚焦元素 el.style.color = 'red'; } }) var app = new Vue({ el: '#app', }) </script>6.4.2 私有(局部)自定义指令<div id="app"> <p v-setcolor>自定义指令的使用</p> </div> <script> var app = new Vue({ el: '#app', // 注册 局部(私有)指令 directives: { // 定义指令名称 setcolor: { // 当被绑定的元素插入到 DOM 中时…… inserted: function (el) { // 聚焦元素 el.style.color = 'red'; } } } }) </script>6.4.3 利用自定义指令使TodoList获取焦点<input @keyup.enter="addTodo" v-getfocus class="new-todo" placeholder="请输入" >// 注册 局部(私有)指令 directives: { // 定义指令名称 getfocus: { // 当被绑定的元素插入到 DOM 中时…… inserted: function (el) { // 聚焦元素 el.focus() } } },6.4.4 为自定义指令传值之前学习的指令中,有的指令可以传值,有的则没有,而我们自定的指令中是没有值的,如果想为自定义指令赋值,如下即可:<div id="app"> <p v-setcolor='colors'>自定义指令的使用</p> </div> <script> var app = new Vue({ el: '#app', data:{ colors:'yellow' }, // 注册 局部(私有)指令 directives: { // 定义指令名称 setcolor: { // 自定义指令可以接受第二个参数 inserted: function (el,val) { // 第二个参数中包含了指令名称、挂载名称及数据键值 console.log(val); // 聚焦元素 el.style.color = val.value; } } } }) </script>6.5 过度及动画我们可以使用v-if或者v-show控制dom元素的显示和隐藏<div id="app"> <button @click="go">显示/隐藏</button> <p v-show="is">pppppp1111</p> </div> <script> var app = new Vue({ el: '#app', data: { isShow: true, }, methods: { go() { this.isShow = !this.isShow; } } }) </script>而在显示和隐藏的过程中,我们加入一些动画效果:在进入/离开的过渡中,会有 6 个 class 切换。v-enter:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。v-enter-active:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。v-enter-to: 2.1.8版及以上 定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时 v-enter 被移除),在过渡/动画完成之后移除。v-leave: 定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。v-leave-active:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。v-leave-to: 2.1.8版及以上 定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 v-leave 被删除),在过渡/动画完成之后移除。对于这些在过渡中切换的类名来说,如果你使用一个没有名字的 <transition>,则 v- 是这些类名的默认前缀。如果你使用了 <transition name="my-transition">,那么 v-enter 会替换为 my-transition-enter。<style> .fade-enter-active, .fade-leave-active { transition: opacity 1s; } .fade-enter, .fade-leave-to { opacity: 0; } .man-enter-active, .man-leave-active { transition: opacity 4s; } .man-enter, .man-leave-to { opacity: 0; } </style> <div id="app"> <button @click="go">显示/隐藏</button> <transition name="fade"> <p v-show="isShow">pppppp1111</p> </transition> <transition name="man"> <p v-show="isShow">pppppp222</p> </transition> </div> <script> var app = new Vue({ el: '#app', data: { isShow: true, }, methods: { go() { this.isShow = !this.isShow; } } }) </script>这就是Vue中动画及过渡的基本使用方式,因为这些动画效果都需要我们自己写CSS样式,相对比较麻烦,在项目中,大多情况下,我们会借助第三方 CSS 动画库来实现,如:Animate.css ;后面项目中具体使用时,我们在进一步学习第三方 CSS 动画库的使用;第7章 json-server与axios一个项目从立项开始,一般都是前后端同时进行编码工作的,而此时前端需要的接口和数据后台都是无法提供的;7.1 json-server 使用使用全局安装 :npm install json-server -gjson-server 会将一个json文件作为数据库来存储数据,对json数据的格式是有要求的,如data.json的内容:{ "tb1": [ { "id": 1, "title": "标题1", "author": "描述信息1" }, { "id": 2, "title": "标题2", "author": "描述信息2" } ], "tb2": [ { "id": 1, "body": "some comment", "postId": 1 } ], "tb3": { "name": "typicode" } }启动服务: json-server --watch data.json启动成功后,提示信息如下:$ json-server --watch data.json \{^_^}/ hi! Loading data.json Done Resources http://localhost:3000/tb1 http://localhost:3000/tb2 http://localhost:3000/tb3 Home http://localhost:3000 Type s + enter at any time to create a snapshot of the database Watching...得到tb1所有的数据 GET: http://localhost:3000/tb1根据id得到数据 GET : http://localhost:3000/tb1/2添加一条数据 POST: http://localhost:3000/tb1删除一条数据 DELETE: http://localhost:3000/tb1/2模糊查找 GET : http://localhost:3000/tb1?title_like=标题根据id修改数据 PUT: http://localhost:3000/tb1/1注意:json-server 严格遵循 HTTP 请求语义进行数据处理7.2 axios我们在构建应用时需要访问一个 API 并展示其数据。做这件事的方法有好几种,而使用基于 Promise 的 HTTP 客户端 axios 则是其中非常流行的一种。<script src="./axios.js"></script> <script> // 获取全部数据 axios.get('http://localhost:3000/list_data') .then((data)=>{ console.log(data); }); // 获取一条数据 axios.get('http://localhost:3000/list_data/2') .then((data)=>{ console.log(data); }) // 添加一条数据 axios.post('http://localhost:3000/list_data',{stat:false,title:'喝水'}) .then((d)=>{ console.log(d); }).catch(error => console.log(error)) // 删除一条数据 axios.delete('http://localhost:3000/list_data/4') .then((d)=>{ console.log(d); }).catch(error => console.log(error)) // 修改一条数据 axios.put('http://localhost:3000/list_data/6',{title:'hhhhhh'}) .then((d)=>{ console.log(d); }).catch(error => console.log(error)) </script>第8章 重构TodoList案例8.1 启动API接口及数据db.json:{ "list_data": [ { "id": 1, "title": "吃饭", "stat": true }, { "id": 2, "title": "睡觉", "stat": false }, { "id": 3, "title": "打豆豆", "stat": true } ] }启动服务: json-server --watch db.json8.2 获取全部任务el: '#todoapp', data: { // list_data:list_data, list_data:[]// es6属性简写 }, // 当vue实例获取到 el:'#todoapp' 自动调用执行 mounted 方法 mounted:function(){ let url = 'http://localhost:3000/list_data'; axios.get(url).then((backdata)=>{ // console.log(backdata.data); this.list_data = backdata.data; }) },8.3 添加任务…… methods: { // 添加任务事件处理器 // addTodo:function(){} // 简写形式 addTodo(ev) { // 获取当前触发事件的元素 var inputs = ev.target; // 获取value值,去除空白后判断,如果为空,则不添加任务 if (inputs.value.trim() == '') { return; } // 组装任务数据 var todo_data = { // 通过服务器添加数据时,不需要id值 // id: this.list_data.length + 1 + 1, title: inputs.value, stat: false }; let url = 'http://localhost:3000/list_data'; // 将数据提交保存到服务器 axios.post(url,todo_data).then((back_data)=>{ let {data,status} = back_data; if(status == 201){ // console.log(this.list_data); // 数据保存成功后,将数据添加到任务列表展示 this.list_data.push(data); } }) // 清空文本框 inputs.value = ''; }, …… 8.4 删除任务<button @click="removeTodo(key,val.id)" class="destroy"></button>// 删除操作 removeTodo(key,id) { let url = 'http://localhost:3000/list_data/'+id; axios.delete(url).then((back_data)=>{ // 结构对象 let {data,status} = back_data; // console.log(back_data); if(status == 200){ this.list_data.splice(key, 1); } }) },8.5 完成任务<li v-for="(val,key) in list_data" @click="todoDone(key,val.id)" v-bind:class="{completed:val.stat}">// 完成任务 事件处理器(新添加,原案例中没有) todoDone(key,id){ let url = 'http://localhost:3000/list_data/'+id; // 组装数据准备修改服务器数据 setdata = {}; // 注意:事件优先于浏览器渲染执行,获取当前状态 var chestat = this.list_data[key].stat; // 状态取反 setdata.stat = !chestat; setdata.title = this.list_data[key].title; // console.log(setdata); axios.put(url,setdata).then((backdata)=>{ var {data,status} = backdata; // 如果服务器修改失败,则重新渲染DOM节点样式,改回原始状态 // 服务器返回状态有误 if(status != 200){ this.list_data[key].stat = chestat; } // 如果异步执行失败失败,则重新渲染DOM节点样式,改回原始状态 }).catch((err)=>{ if(err){ this.list_data[key].stat = chestat; } }) },8.6 案例中的Bug修改:<button @click.stop="removeTodo(key,val.id)" class="destroy"></button>第9章 组件https://cn.vuejs.org/v2/guide/components.htmlhttps://cn.vuejs.org/v2/guide/components-registration.html9.1 认识组件组件系统是 Vue 的一个重要概念,因为它是一种抽象,允许我们使用小型、独立和通常可复用的组件构建大型应用。通常一个应用会以一棵嵌套的组件树的形式来组织:例如,你可能会有页头、侧边栏、内容区等组件,每个组件又包含了其它的像导航链接、博文之类的组件。9.2 基本使用组件是可复用的 Vue 实例,且带有一个名字。把这个组件作为自定义元素来使用。组件的好处是写一次可以进行任意次数的复用。<div id="app"> <!-- 使用组件 --> <!-- 将组件名直接当做标签名在html代码中使用即可 --> <mytemp></mytemp> <!-- 组件可以进行任意次数的复用 --> <mytemp></mytemp> </div> <script> // 定义一个名为 mytemp 的新组件 Vue.component('mytemp',{ // template属性的值,作为组件的内容 // vue 会把这个值替换到html中并会被浏览器渲染 template:"<h2>我是一个组件</h2>" }) var app = new Vue({ el: '#app', }) </script>上面代码中我们直接使用 Vue.component() 方法定义了组件,而这个 mytemp 组件可以用在所有 vue 实例中,这种组件被称为 全局组件在具体的某个vue实例中,也可以定义组件,但是组件仅会在具体的 vue 实例中起作用,这种组件被称为 局部(私有)组件<div id="app"> <!-- 使用组件 --> <!-- 将组件名直接当做标签名在html代码中使用即可 --> <mytemp></mytemp> </div> <div id="app2"> <!-- 不可用 --> <mytemp></mytemp> </div> <script> var app = new Vue({ el: '#app', // app 的私有组件,其他实例对象不可用 components: { mytemp: { template: "<h2>我是一个组件</h2>", } } }) var app2 = new Vue({ el: '#app2', }) </script>9.3 使用注意组件名如果是驼峰法命名,使用组件时要将大写字母改为小写,并且在前面加上 -组件中的tamplate属性必须有一个唯一的根元素,否则会报错<div id="app"> <!-- 使用组件 --> <!-- 将组件名直接当做标签名在html代码中使用即可 --> <my-temp></my-temp> <!-- 单标签方式使用 --> <my-temp/> </div> <div id="app2"> <!-- 不可用 --> <mytemp></mytemp> </div> <script> var app = new Vue({ el: '#app', // app 的私有组件,其他实例对象不可用 components: { // 驼峰法命名 myTemp: { // 必须有唯一的根标签,多标签报错 template: "<div><h2>我是一个组件</h2><h3>df</h3></div>", } } }) var app2 = new Vue({ el: '#app2', }) </script>9.4 组件的使用CSS 代码* { margin: 0; padding: 0; } .top { width: 100%; height: 80px; background-color: #ccc; } .left { margin-top: 20px; width: 800px; height: 600px; background-color: #ccc; float: left; } .right { margin-top: 20px; width: 400px; height: 600px; background-color: #ccc; float: right; }原始HTML代码<div id="app"> <div class="top">我是顶</div> <div class="left">我是左</div> <div class="right">我是右</div> </div>组件化代码<div id="app"> <tops></tops> <lefts></lefts> <rights></rights> </div> <script> var app = new Vue({ el: '#app', components:{ tops:{ template:'<div class="top">我是顶</div>' }, lefts:{ template:'<div class="left">我是左</div>', }, rights:{ template:'<div class="right">我是右</div>' } } }) </script>9.5 组件中的数据及方法组件是带有名字的可复用的 Vue 实例 ,所以它们与 new Vue 实例对象接收相同的参数选项 data、computed、watch、methods , 但 el例外;虽然组件和实例对象可以接收相同的参数选项,但在具体使用中,vue实例对象的 data 与组件中的 data 还是有差异的, 在我们自己写的组件中,data 必须是一个函数 一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回的对象;<div id="app"> <my-temp></my-temp> </div> <script> var app = new Vue({ el: '#app', components: { myTemp: { // 一个组件的 data 选项必须是一个函数 data:function(){ // 将 数据 装入 对象 返回 return {msg:'我是data选项'} }, // 其他选项的使用不受影响 methods:{ cli(){ alert(123); } }, template: "<div @click='cli'>{{msg}}</div>", } } }) </script>除 data 选项外,其他选项的使用都是一样的;9.6 vue实例也是组件通过new Vue() 可以得到一个实例对象,其实这个实例对象就是一个特殊的组件,也有 template 参数,也可以当做组件来使用;<div id="app"> {{msg}} </div> <script> var app = new Vue({ el: '#app', data:{msg:'数据'}, template:'<h2>组件</h2>' }) </script>上面的代码中直接为Vue 实例对象传入了 template 参数,那么 vue 会使用template中的数据替换 el 选中的整个 DOM 节点 , 因此 data 选项中的的数据也不会绑定,因为在绑定数据之前,整个 DOM 节点包括节点中 {{msg}} 都会被替换;如果想让数据正常绑定,我们可以在 template 数据中加入 {{msg}}<div id="app"> {{msg}} </div> <script> var app = new Vue({ el: '#app', data:{msg:'数据'}, template:'<h2>组件{{msg}}</h2>' }) </script>9.7 通过 Prop 向子组件传递数据 *https://cn.vuejs.org/v2/guide/components.html<div id="app"> <mytemp></mytemp> </div> <script> var app = new Vue({ el: '#app', data:{msg:'数据'}, components:{ mytemp:{ template:'<h2>data:{{msg}}</h2>' } } }) </script>运行上面的代码,我们发现,组件 mytemp 并不能获取实例中 data 的数据,这是因为组件与组件之间都拥有各自独立的作用域;vue 在组件中提供了props 选项,props 接受一个在组件中自定义属性的值;<div id="app"> <mytemp cc="我是cc"></mytemp> </div> <script> var app = new Vue({ el: '#app', data:{msg:'数据'}, components:{ mytemp:{ template:'<h2>data:{{cc}}</h2>', props:['cc'], } } }) </script>我们知道了props的用法后,怎么才能将vue实例对象中的数据传入组件中呢?我们可以借助 v-bind 指令来进行传值;<div id="app"> <mytemp v-bind:cc="msg" v-bind:kk="msg2"></mytemp> </div> <script> var app = new Vue({ el: '#app', data:{ msg:'数据', msg2:'数据二' }, components:{ mytemp:{ template:'<h2>data:{{cc}}<br>{{kk}}</h2>', props:['cc','kk'], } } }) </script>vue实例对象也是一个组件,而 mytemp 组件就是运行在 实例对象下面的,这时我们也会将 实例对象称为 父组件,将 mytemp 组件称为 子组件; 而我们上面的代码,实际上已经实现了 父组件向子组件传递数据的 功能;第10章 Vue的生命周期每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。比如 created 钩子可以用来在一个实例被创建之后执行代码:new Vue({ data: { a: 1 }, created: function () { // `this` 指向 vm 实例 console.log('a is: ' + this.a) } }) // => "a is: 1"也有一些其它的钩子,在实例生命周期的不同阶段被调用,如 mounted、updated 和 destroyed。生命周期钩子的 this 上下文指向调用它的 Vue 实例。下图展示了实例的生命周期。你不需要立马弄明白所有的东西,不过随着你的不断学习和使用,它的参考价值会越来越高。<div id="app"> {{ msg }} <input type="text" ref="txt" v-model="msg"> </div> <script> var vm = new Vue({ el: "#app", data: { msg: 'hello vue', dataList: [] }, // 在vue对象初始化过程中执行 beforeCreate(){ console.log('beforeCreate'); console.log(this.msg);// undefined }, // 在vue对象初始化完成后执行 created() { console.log('created'); console.log(this.msg);//hello vue } // …… }); </script>第11章 单页应用11.1 单页应用什么是单页应用单页应用(single page web application,SPA),是在一个页面完成所有的业务功能,浏览器一开始会加载必需的HTML、CSS和JavaScript,之后所有的操作都在这张页面完成,这一切都由JavaScript来控制。单页应用优缺点优点操作体验流畅完全的前端组件化缺点首次加载大量资源(可以只加载所需部分)对搜索引擎不友好学习难度相对较高优缺点都很明显,但是我们都还没尝试过就来评价,就会显得空口无凭;接下来我们先来学习制作单页应用,然后再来进行点评;11.2 vue路由插件vue-routerhttps://cn.vuejs.org/v2/guide/routing.htmlhttps://router.vuejs.org/zh/<!-- 引入路由 --> <script src="./vue.js"></script> <script src="./vue-router.js"></script> <div id="app"> <ul> <li><a href="#/login">登录</a></li> <li><a href="#/register">注册</a></li> </ul> <!-- 路由中设置的组件会替换router-view标签 --> <router-view></router-view> </div> <script> // 1:定义路由组件 var login = { template: '<h2>我是登录页面</h2>' } var register = { template: '<h2>注册有好礼</h2>' } // 2:获取路由对象 var router = new VueRouter({ // 定义路由规则 routes: [ // {请求的路径,componet是模板} { path: "/register", component: register }, { path: "/login", component: login }, ] }) var app = new Vue({ el: '#app', // ES6 属性简写 // 3:将router对象传入Vue router }) </script>上例中,在HTML中我们直接使用了 a 标签,但是这样并不好,因为官方为我们提供了 router-link 标签<div id="app"> <ul> <li><router-link to="/login">登录</router-link></li> <li><router-link to="/register">注册</router-link></li> <!-- <li><a href="#/login">登录</a></li> <li><a href="#/register">注册</a></li> --> <!-- router-link 会被解析为a标签 --> <!-- 不同的是,router-link在解析为a标签后, 会自动为点击的 a 标签添加class属性 --> </ul> <!-- 路由中设置的组件会替换router-view标签 --> <router-view></router-view> </div>使用 router-link 的一大好处就是,每当我们点击时,在标签内就会自动帮我们添加 class 属性,而此时,我们就可以利用 class 属性,来定义样式:<style> .router-link-active { color: red; } </style>11.3 动态路由匹配假设有一个用户列表,想要删除某一个用户,需要获取用户的id传入组件内,如何实现呢?此时可以通过路由传参来实现,具体步骤如下:通过 传参,在路径上传入具体的值<router-link to="/users/120">用户管理</router-link>路由规则中增加参数,在path最后增加 :id{ name: 'users', path: '/users/:id', component: Users },在组件内部可以使用,this.$route 获取当前路由对象var Users = { template: '<div>这是用户管理内容 {{ $route.params.id }}</div>', mounted() { console.log(this.$route.params.id); } };第12章 构建一个项目12.0 命令行工具 (CLI)https://cn.vuejs.org/v2/guide/installation.html#%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%B7%A5%E5%85%B7-CLIVue 提供了一个官方的 CLI,为单页面应用 (SPA) 快速搭建繁杂的脚手架。它为现代前端工作流提供了 batteries-included 的构建设置。只需要几分钟的时间就可以运行起来并带有热重载、保存时 lint 校验,以及生产环境可用的构建版本。更多详情可查阅 Vue CLI 的文档。12.1 初始化项目安装 cli 命令工具:npm install -g @vue/cli @vue/cli-init安装成功后,使用 vue -V 命令,查看版本号;使用 vue init webpack myapp 构建一个名为 myapp 的项目:Vue 依然使用询问的方式,让我们对项目有一个初始化的信息Project name:项目名Project description: 项目描述Author: 作者Vue build:第一种:配合大部分的开发人员第二种:仅仅中有runtimeInstall vue-router? 是否安装vue-routerUse ESLint to lint your code?是否使用ESLint来验证我们的语法。Pick an ESLint preser:使用哪种语法规范来检查我们的代码:Standard: 标准规范Airbnb: 爱彼迎规范Set up unit test: 设置单元测试Setup e2e tests: 设置端对端测试Should we run 'npm install':要不要帮忙你下载这个项目需要的第三方包使用npm来下载使用yarn来下载To get started: cd myapps npm run dev // 使用命令启动项目 ----- Your application is running here: http://localhost:8080 打开浏览器,访问 http://localhost:8080 看到浏览器的欢迎界面,表示项目运行成功12.2 项目结构介绍├── build webpack打包相关配置文件目录 ├── config webpack打包相关配置文件目录 ├── node_modules 第三方包 ├── src 项目源码(主战场) │ ├── assets 存储静态资源,例如 css、img、fonts │ ├── components 存储所有公共组件 │ ├── router 路由 │ ├── App.vue 单页面应用程序的根组件 │ └── main.js 程序入口,负责把根组件替换到根节点 ├── static 可以放一些静态资源 │ └── .gitkeep git提交的时候空文件夹不会提交,这个文件可以让空文件夹可以提交 ├── .babelrc 配置文件,es6转es5配置文件,给 babel 编译器用的 ├── .editorconfig 给编辑器看的 ├── .eslintignore 给eslint代码风格校验工具使用的,用来配置忽略代码风格校验的文件或是目录 ├── .eslintrc.js 给eslint代码风格校验工具使用的,用来配置代码风格校验规则 ├── .gitignore 给git使用的,用来配置忽略上传的文件 ├── index.html 单页面应用程序的单页 ├── package.json 项目说明,用来保存依赖项等信息 ├── package-lock.json 锁定第三方包的版本,以及保存包的下载地址 ├── .postcssrc.js 给postcss用的,postcss类似于 less、sass 预处理器 └── README.md 项目说明文档12.3 语法检查注意 :如果我们在 构建项目时 选择了 Use ESLint to lint your code 那么我们在写代码时必须严格遵守 JavaScript Standard Style 代码风格的语法规则:使用两个空格 – 进行缩进字符串使用单引号 – 需要转义的地方除外不再有冗余的变量 – 这是导致 大量 bug 的源头!无分号 – 这没什么不好。不骗你!行首不要以 (, [, or ` 开头这是省略分号时唯一会造成问题的地方 – 工具里已加了自动检测!详情关键字后加空格 if (condition) { ... }函数名后加空格 function name (arg) { ... }坚持使用全等 === 摒弃 == 一但在需要检查 null || undefined 时可以使用 obj == null。一定要处理 Node.js 中错误回调传递进来的 err 参数。使用浏览器全局变量时加上 window 前缀 – document 和 navigator 除外避免无意中使用到了这些命名看上去很普通的全局变量, open, length, event 还有 name。说了那么多,看看这个遵循了 Standard 规范的示例文件 中的代码吧。或者,这里还有一大波使用了此规范的项目 代码可供参考。注意: 如果你不适应这些语法规则,可以在构建项目时不使用 ESLint 的语法检查12.4 项目代码预览12.4.1 知识储备严格模式http://javascript.ruanyifeng.com/advanced/strict.html严格模式主要有以下限制。变量必须声明后再使用函数的参数不能有同名属性,否则报错不能使用with语句不能对只读属性赋值,否则报错不能使用前缀 0 表示八进制数,否则报错不能删除不可删除的属性,否则报错不能删除变量delete prop,会报错,只能删除属性delete global[prop]eval不会在它的外层作用域引入变量eval和arguments不能被重新赋值arguments不会自动反映函数参数的变化不能使用arguments.callee不能使用arguments.caller禁止this指向全局对象不能使用fn.caller和fn.arguments获取函数调用的堆栈增加了保留字(比如protected、static和interface)ES6模块化http://es6.ruanyifeng.com/#docs/module总结:CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用;CommonJS 模块是运行时加载,ES6 模块是编译时输出接口;ES6 的模块自动采用严格模式,不管你有没有在模块头部加上"use strict";;ES6 模块之中,顶层的this指向undefined;CommonJS 模块的顶层this指向当前模块;12.4.2 代码加载执行main.js// 入口文件 // 以es6模块的方式引入 vue APP router 三个模块; import Vue from 'vue' import App from './App' import router from './router' Vue.config.productionTip = false; /* eslint-disable no-new */ new Vue({ // 获取节点对象 el: '#app', // 引入路由 router, // 本实例的私有组件 components: { App }, // el 与 template 在同一个实例中出现, // 根据生命周期的执行顺序可知,template中的内容会替换el选中的内容 template: '<App/>' }) roter/index.jsimport Vue from 'vue' import Router from 'vue-router' import HelloWorld from '@/components/HelloWorld' // Vue 中插件引入语法 // https://cn.vuejs.org/v2/guide/plugins.html Vue.use(Router) // ES6模块导出语法 export default new Router({ routes: [ // 定义一个路由规则 { path: '/', // 请求路径 name: 'HelloWorld', // 路由名称标识 component: HelloWorld //请求此路由时,使用的组件 } ] }) components/HelloWorld.vueexport default { // 模块名字 name: 'HelloWorld', // 组件中 data 数据必须是一个有返回值的方法 data () { return { msg: 'Welcome to Your Vue.js App' } } }(main.js->template: '<App/>')替换 (index.html->div#app); (index.html-><App/>) --> (components: { App }) ( components: { App }) --> (import App from './App' -> src/App.vue) (App.vue -> <router-view/> -> 路由组件) --> (main.js-> router) ========此项决定了页面展示那个组件内容 ======== ({path: '/',name: 'HelloWorld', component: HelloWorld }) --> (import HelloWorld from '@/components/HelloWorld') (src/components/HelloWorld.vue) --> <router-view/> 12.5 添加自己的路由组件修改 router/index.js ,添加自己的路由import Vue from 'vue' import Router from 'vue-router' import HelloWorld from '@/components/HelloWorld' // 引入(导入) 组件 import MyRouter from '@/components/MyRouter' Vue.use(Router) // ES6模块导出语法 export default new Router({ routes: [ {path: '/',name: 'HelloWorld', component: HelloWorld }, // 添加自己的路由及组件 { path:'/myrouter', name:'MyRouter', component:MyRouter } ] })在 components 文件夹中添加 MyRouter.vue 文件,写自己的组件代码:<template> <div class="mypage"> {{mydatas}} </div> </template> <script> // 模块化导出 export default { data(){ return {mydatas:'lksadjflks'} } } </script> <style> .mypage{ width: 200px; height: 50px; background: pink } </style> 浏览器渲染效果如下:
2022年10月13日
26 阅读
0 评论
1 点赞
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日
53 阅读
0 评论
1 点赞
2022-10-13
Http通信协议
第一章 前言我们现实生活中的协议是指相互遵守的规定,单方面违背,协议不成立;而在互联网交互的过程中,也存在这许多协议,例如FTP、HTTP、STMP、TCP/IP等。而HTTP协议则是web服务器和web客户端达成的一种可靠的数据传输协议,通过HTTP可以从遍布全世界的Web服务器上将JPEG图片,HTML页面,文本文件,MPEG电影,WAV音频文件和其他资源信息块迅速、便捷、可靠地搬移到人们桌面上的Web浏览器上去。它能够确保数据在传输的过程当中不会损坏或者产生混乱。这样,对用户来说是个好事,同样对internet应用的开发人员来说也是一件好事。因为我们在开发过程中也不需要担心自己的页面和数据会在传输过程中发生破坏和畸变了。第二章 WEB客户端和服务器Web内容都是存储在Web服务器上的。Web服务器所使用的是HTTP协议,因此经常会被称为HTTP服务器。这些HTTP服务器存储了因特网中的数据,如果HTTP客户端发出请求的话,它们会提供数据。客户端向服务器发送HTTP请求,服务器会在HTTP响应中回送所请求的数据。那么一次请求和响应的过程中发生了什么?HTTP属于无状态链接协议,即是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间和服务器资源。当然也有有状态链接,那就是我们常用的QQ。H5新增的特性中也包含Websocket帮助我们构建长链接。第三章 资源和媒体类型web服务器是web资源的宿主,而web资源就是我们常见的web内容的源头,最简单的web资源就是我们服务器中的静态文件:文本文件,HTML文档,JPEG图片文件,mp4文件等等。当然web资源也可以是动态生成的,类似搜索引擎生成的页面,qq空间的动态等,总之,所有类型的内容来源都是资源。因特网上有数千种不同类型的数据类型,HTTP在传输的过程中为每个传输的数据都打上了名为MIME类型的数据类型标签,描述并标记多媒体内容。web浏览器请求一个网站的时候往往会发布多个HTTP请求,比如我们在浏览一个具有丰富图片的的web页面的时候,浏览器会执行一次HTTP请求来获取描述页面布局的HTML,然后发布另外的请求来获取每个嵌入式的图片,这些图片甚至可能位于不同的服务器上。因此,一个web页面通常不是单个资源,而是一组资源的集合。web服务器会为所有的HTTP对象数据附加一个MIME类型,当浏览器从服务器中取回一个对象的时候,会查看相关的MIME类型。看看它是否知道应该如何处理这个对象。对象的类型写在响应的content-type头中;同样,请求的时候浏览器也会告知服务器请求数据类型。常见的MIME类型:HTML 格式的文本文档由 text/html 类型来标记。普通的 ASCII 文本文档由 text/plain 类型来标记。JPEG 格式的图片为 image/jpeg 类型。GIF 格式的图片为 image/gif 类型。以application开头的媒体格式类型:application/xhtml+xml :XHTML格式application/xml : XML数据格式application/atom+xml :Atom XML聚合格式application/json : JSON数据格式application/octet-stream : 二进制流数据(如常见的文件下载)application/x-www-form-urlencoded : <form encType=''>中默认的encType,form表单数据被编码为key/value格式发送到服务器(表单默认的提交数据的格式)multipart/form-data : 需要在表单中进行文件上传使用的数据格式。当然还有很多类型,我们就不一一列举了。MIME 参考手册:http://www.w3school.com.cn/media/media_mimeref.asp第四章 URL统一资源定位符(Uniform Resource Locator)是资源标识符最常见的形式。URL描述了一台特定服务器上某资源的特定位置。它们可以明确说明如何从一个精确、固定的位置获取资源。互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。大部分 URL 都遵循一种标准格式, 这种格式包含三个部分。URL 的第一部分被称为方案(scheme), 说明了访问资源所使用的协议类型。 这部分通常就是 HTTP 协议(http://)。第二部分给出了服务器的因特网地址(比如,http://www.itheima.com)。其余部分指定了 Web 服务器上的某个资源(比如, /static/image/common/zixuelogo.png)。URL可以更为细致的进行划分。 foo://username:password@xxx.xx.xx:8080/over/there/index.html?type=answer&name=yanshiba#nose \_/ \_______________/ \_________/ \__/ \___/ \_/ \______________________/ \__/ | | | | | | | | | userinfo host port | | query fragment | \________________________________/\_____________|____|/ \__/ \__/ scheme | | | | | | name authority | | | | | path | | interpretable as keys | | \_______________________________________________|____|/ \____/ \_____/ | | | | | hierarchical part | | interpretable as values | | interpretable as filename | | | interpretable as extension第五章 方法HTTP支持几种不同请求和命令,这些命令被称为HTTP方法,每条HTTP请求报文都包含一个方法。 这个方法会告诉服务器要执行什么动作(获取一个Web页面、发送一段信息、删除一个文件等);我们在学习form表单的时候也知道method可以写作post和get。这就是HTTP请求的方法。请求方法如下:请求方法描述GET获取一个URL指定的资源,即资源实体POST向服务器提交数据PUT向服务器提交数据DELETE请求源服务器删除Request-URI标志的资源HEAD获取一个指定资源的头信息OPTIONS获取服务器支持的方法我们随后学习的node和ajax中都会用到HTTP请求具体的方法实现。第六章 状态码每条HTTP响应报文返回时都会携带一个状态码。状态码是一个三位数字的代码,告知客户端请求是否成功, 或者是否需要采取其他动作。状态码分成如下几个系列:状态码定义说明1XX请求被接受一般只在实验环境下使用2XX成功操作成功的收到,理解和接收3XX重定向为了完成请求,进行进一步措施4XX客户端错误请求的语法有错误或者不能完全被满足5XX服务器错误服务器无法完成明显有效的请求常见的HTTP状态码:HTTP状态码描述200OK。文档正确返回301/2永久/临时重定向304not modified 未修改(原有的缓存可以继续使用)404请求的网页不存在503服务器暂时不可用500服务器内部错误第七章 报文HTTP报文是由一行一行的简单字符串组成的。HTTP报文都是纯文本,不是二进制代码,所以人们可以很方便地对其进行读写。从Web客户端发往Web服务器的HTTP报文称为请求报文(request message)。从服务器发往客户端的报文称为响应报文(response message)。HTTP 报文包括以下三个部分:起始行报文的第一行就是起始行, 在请求报文中用来说明要做些什么, 在响应报文中说明出现了什么情况。请求行部分由 请求方法(GET,POST等),请求路径,协议版本组成。响应行部分由 协议版本,状态码,状态文字组成。首部字段起始行后面有零个或多个首部字段。 每个首部字段都包含一个名字和一个值, 为了便于解析, 两者之间用冒号来分隔。 首部以一个空行结束。主体空行之后就是可选的报文主体了, 其中包含了所有类型的数据。 请求主体中包括了要发送给 Web 服务器的数据; 响应主体中装载了要返回给客户端的数据。 起始行和首部都是文本形式且都是结构化的, 而主体则不同, 主体中可以包含任意的二进制数据(比如图片、视频、音轨、软件程序)。 当然, 主体中也可以包含文本。HTTP报文常见的内容:http://www.cnblogs.com/Joans/p/3956490.html\使用火狐浏览器打开一个网页,找到其中一个网络请求查看报文:
2022年10月13日
38 阅读
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日
45 阅读
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日
49 阅读
0 评论
1 点赞
2022-10-13
javascript高级-jQuery
jQuery第1章 jQuery简介1.1 JavaScript库的概念JavaScript开发的过程中,处理浏览器的兼容很复杂而且很耗时,于是一些封装了这些操作的库应运而生。这些库还会把一些常用的代码进行封装。把一些常用到的方法写到一个单独的js文件,使用的时候直接去引用这js文件就可以了。(animate.js、common.js)常见的JavaScript 库 - jQuery、Prototype、MooTools。其中jQuery是最常用的一个jQuery其实就是一个js文件,里面封装了一大堆的方法方便我们的开发,其实就是一个加强版的common.js,因此我们学习jQuery,其实就是学习jQuery这个js文件中封装的一大堆方法。1.2 jQuery的优点好处jQuery设计的宗旨是'Write Less,Do More',即倡导写更少的代码,做更多的事情。它封装JavaScript常用的功能代码,提供一种简便的操作,优化HTML文档操作、事件处理、动画设计和Ajax交互。 jQuery的核心特性可以总结为:具有独特的链式语法和短小清晰的多功能接口;具有高效灵活的css选择器,并且可对CSS选择器进行扩展;拥有便捷的插件扩展机制和丰富的插件。jQuery兼容各种主流浏览器。 极大地简化了 JavaScript 编程。1.3 jQuery的版本jQuery版本有很多,分为1.x 2.x 3.x 1.x版本:能够兼容IE678浏览器 2.x版本:不兼容IE678浏览器 1.x和2.x版本jquery都不再更新版本了,现在只更新3.x版本。 3.x版本:不兼容IE678,更加的精简(在国内不流行,因为国内使用jQuery的主要目的就是兼容IE678) 国内多数网站还在使用1.x的版本jQuery官网1.4 体验jQuery案例:显示与设置内容 <input type="button" value="显示" id="btn1"> <input type="button" value="结束" id="btn2"> <div>请欣赏动画</div> <div>千呼万唤始出来</div> <img src="img/1.jpg" style="display:none"> <img src="img/2.jpg" style="display:none"> <script type="text/javascript" src="jquery.js"></script> <script> $(document).ready(function () { $('#btn1').click(function () { $('img').show(2000); }); $('#btn2').click(function () { $('div').text('下集再见'); $('img').hide(2000); }); }); </script>优点总结:-查找元素的方法多种多样,非常灵活 -拥有隐式迭代(自动循环遍历)特性,因此不再需要手写for循环了。 -完全没有兼容性问题。 -实现动画非常简单,而且功能更加的强大。 -代码简单、粗暴。1.5 jQuery中顶级对象jQuery中的顶级对象是$或jQuery用于: 获取jQuery对象 入口函数(页面加载事件) 高级功能注意:jQuery中的$和JQuery关键字本身为同一对象;$ 可以认为就是 一个特殊构造函数 ; 可以使用$(选择器) 方式调用$,得到一个对象,在对象上可以调用$的实例方法 也可以使用$.方法名 调用静态方法。 比如 遍历数组对象的 $.each() 相当于for循环1.6 jQuery中页面加载事件使用jQuery的三个步骤:引入jQuery文件 入口函数(定义页面加载事件) 功能实现关于jQuery的入口函数:// 第一种写法 $(document).ready(function() { }); // 第二种写法 $().ready(function() { }); // 第三种写法 $(function() { });jQuery入口函数与window.onload的对比JavaScript的入口函数要等到页面中所有资源(包括图片、文件)加载完成才开始执行。 jQuery的入口函数只会等待文档树加载完成就开始执行,并不会等待图片、文件的加载。第2章 选择器jQuery选择器是jQuery为我们提供的一组方法,让我们更加方便的获取到页面中的元素。注意:jQuery选择器返回的是jQuery对象。jQuery选择器有很多,基本兼容了CSS所有的选择器,并且jQuery还添加了很多更加复杂的选择器。(查看jQuery文档)jQuery选择器虽然很多,但是选择器之间可以相互替代,就是说获取一个元素,你会有很多种方法获取到。所以我们平时真正能用到的只是少数的最常用的选择器。2.1 jQuery基本选择器(重点)名称用法描述ID选择器$('#id');获取指定ID的元素类选择器$('.class');获取同一类class的元素标签选择器$('div');获取同一类标签的所有元素并集选择器$('div,p,li');使用逗号分隔,只要符合条件之一就可。交集选择器$('div.redClass');获取class为redClass的div元素总结:跟css的选择器用法一模一样。语法模板: 00-语法模板.html(需要包含jquery.js) <script type="text/javascript"> //常用选择器 //根据id获取元素 获取到的结果:类数组对象 console.log( $('#div0') ); console.log( $('#div0')[0] ); //根据class获取元素 console.log( $('.div_1') ); //根据标签名称来获取元素 console.log( $('div') ); //根据属性获取元素 console.log( $('input[name=username]') ); //根据表单元素属性获取元素 console.log( $(':checked') ); </script>2.2 jQuery层级选择器(重点)名称用法描述子代选择器$('ul > li');使用-号,获取儿子层级的元素,注意,并不会获取孙子层级的元素后代选择器$('ul li');使用空格,代表后代选择器,获取ul下的所有li元素,包括孙子等跟CSS的选择器一模一样。2.3 jQuery过滤选择器(了解为主)这类选择器都带冒号:名称用法描述:eq(index)$('li:eq(2)').css('color', 'red');获取到的li元素中,选择索引号为2的元素,索引号index从0开始。:odd$('li:odd').css('color', 'red');获取到的li元素中,选择索引号为奇数的元素:even$('li:even').css('color', 'red');获取到的li元素中,选择索引号为偶数的元素2.4 jQuery筛选方法(重点)筛选选择器的功能与过滤选择器有点类似,但是用法不一样,筛选选择器主要是方法。名称用法描述children(selector)$('ul').children('li')相当于$('ul-li'),子类选择器find(selector)$('ul').find('li');相当于$('ul li'),后代选择器siblings(selector)$('#first').siblings('li');查找兄弟节点,不包括自己本身。parent()$('#first').parent();查找父亲eq(index)$('li').eq(2);相当于$('li:eq(2)'),index从0开始next()$('li').next()找下一个兄弟prev()$('li').prev()找上一次兄弟closest$('li').closest('ul')找最近一个祖先元素语法模板: 00-语法模板.html(需要包含jquery.js)<script type="text/javascript"> //常用筛选方法 //获取爱好对应的div var hobby = $('#hobby'); //获取 hobby 父元素 console.log( $('#hobby').parent() ); //获取 hobby 子元素 console.log( $('#hobby').children() ); //获取 hobby 最近的祖先元素 console.log( $('#hobby').closest('form') ); //获取 hobby 所有后代元素 console.log( $('#hobby').find('input') ); //获取 hobby 下一个兄弟元素 console.log( $('#hobby').next() ); //获取 hobby 前一个兄弟元素 console.log( $('#hobby').prev() ); //获取 hobby 所有兄弟元素 console.log( $('#hobby').siblings() ); </script>第3章 jQuery对象和DOM对象3.1 jQuery对象和DOM对象的区别DOM对象用原生JavaScript获取的DOM对象 通过document.getElementById() 反馈的是元素(DOM对象) 通过document.getElementsByTagName()获取到的是什么? 伪数组(集合),集合中的每一个对象是DOM对象jQuery对象jQuery对象 用$()的方式获取的对象 jQuery对象又可以叫做包装集(包装的DOM对象的集合)区别jQuery对象不能使用DOM对象的成员,DOM对象不能使用jQuery对象的成员<div id="box"></div> <script> // DOM对象 var box = document.getElementById('box'); // 错误 box.text('hello'); // 正确 box.innerText = 'hello'; // jQuery对象,jQuery对象加前缀$,用以区分DOM对象 var $box = $('#box'); // 错误 $box.innerText = 'hello'; // 正确 $box.text('hello'); </script>3.2 jQuery对象和DOM对象的相互转换jQuery对象转换成DOM对象: jQuery对象.get(索引值); jQuery对象[索引值] jQuery对象是包装集(集合),从集合中取数据可以使用索引的方式 DOM对象转换成jQuery对象: $(DOM对象) 只有这一种方法;第4章 简单事件绑定所有事件在jquery中都是jquery对象的方法 click(handler) 单击事件 mouseover(handler) 鼠标悬浮事件 mouseout(handler) 鼠标离开事件 ...<input type="button" value="我是一个按钮" id="btn"> <script> $(function(){ $('#btn').click(function(){ alert("来了老弟~"); }); }); </script>绑定事件时,jquery对象中有多个dom元素,则自动给所有元素均绑定事件。第5章 jQuery操作属性5.1 attr操作设置单个属性 attribute// 第一个参数:需要设置的属性名 // 第二个参数:对应的属性值 // $obj.attr(name, value); // 用法举例 $('img').attr('title','哎哟,不错哦'); $('img').attr('alt','哎哟,不错哦');设置多个属性// 参数是一个对象,包含了需要设置的属性名和属性值 // $obj.attr(obj) // 用法举例 $('img').attr({ title:'哎哟,不错哦', alt:'哎哟,不错哦', style:'opacity:.5' });获取属性// 传需要获取的属性名称,返回对应的属性值 // $obj.attr(name) // 用法举例 var oTitle = $('img').attr('title'); alert(oTitle);移除属性// 参数:需要移除的属性名, // $obj.removeAttr(name); // 用法举例 $('img').removeAttr('title');5.2 prop操作在jQuery1.6之后支持,对于checked、selected、disabled这类boolean类型的属性来说,不能用attr方法,只能用prop方法。// 设置属性 $(':checked').prop('checked',true); // 获取属性 $(':checked').prop('checked');// 返回true或者false5.3 val()/text()/html()值操作$obj.val() 获取或者设置表单元素的value属性的值 $obj.html() 对应innerHTML $obj.text() 对应innerText 以上三个方法:不传参数 表示获取值; 传递一个参数值,表示设置5.4 class操作添加样式类// name:需要添加的样式类名,注意参数不要带点. // $obj.addClass(name); // 例子,给所有的div添加one的样式。 $('div').addClass('one');移除样式类// name:需要移除的样式类名 // $obj.removeClass('name'); // 例子,移除div中one的样式类名 $('div').removeClass('one');判断是否有某个样式类// name:用于判断的样式类名,返回值为true false // $obj.hasClass(name) // 例子,判断第一个div是否有one的样式类 $('div').hasClass('one');切换样式类// name:需要切换的样式类名,如果有,移除该样式,如果没有,添加该样式。 // $obj.toggleClass(name); // 例子 $('div').toggleClass('one');5.5 隐式迭代(批量操作自动遍历)设置操作的时候(绑定事件),如果是多个元素,那么给所有的元素设置相同的值获取操作的时候,如果是多个元素,那么只会返回第一个元素的值。如果想要获取多个值,需要手动进行遍历操作。第6章 jQuery操作样式6.1 CSS操作功能:设置或者修改样式,操作的是style属性。操作单个样式// name:需要设置的样式名称 // value:对应的样式值 // $obj.css(name, value); // 使用案例 $('#one').css('background','gray');// 将背景色修改为灰色设置多个样式// 参数是一个对象,对象中包含了需要设置的样式名和样式值 // $obj.css(obj); // 使用案例 $('#one').css({ 'background':'gray', 'width':'400px', 'height':'200px' });获取样式// name:需要获取的样式名称 // $obj.css(name); // 案例 $('div').css('background-color');注意:获取样式操作只会返回第一个元素对应的样式值。6.2 jQuery尺寸和位置操作(了解)6.2.1 width方法与height方法设置或者获取高度,不包括内边距、边框和外边距width() height() 不传参数表示获取,传递参数表示设置。(传递参数时,可以不用带单位px)// 带参数表示设置高度 $('img').height(200); // 不带参数获取高度 $('img').height();获取网页的可视区宽高// 获取可视区宽度 $(window).width(); // 获取可视区高度 $(window).height();6.2.2 innerWidth/innerHeight/outerWidth/outerHeightinnerWidth()/innerHeight() 方法返回元素的宽度/高度(包括内边距)。 outerWidth()/outerHeight() 方法返回元素的宽度/高度(包括内边距和边框)。 outerWidth(true)/outerHeight(true) 方法返回元素的宽度/高度(包括内边距、边框和外边距)。6.2.3 scrollTop与scrollLeft设置或者获取垂直滚动条的位置// 获取页面被卷曲的高度 $(window).scrollTop(); // 获取页面被卷曲的宽度 $(window).scrollLeft();6.2.4 offset方法与position方法offset方法获取元素距离document的位置,position方法获取的是元素距离有定位的父元素(offsetParent)的位置。// 获取元素距离document的位置,返回值为对象:{left:100, top:100} $(selector).offset(); // 获取相对于其最近的有定位的父元素的位置。 $(selector).position();第7章 each方法遍历jQuery的隐式迭代会对所有的DOM对象设置相同的值,但是如果我们需要给每一个对象设置不同的值的时候,就需要自己进行迭代了。作用:遍历jQuery对象集合,为每个匹配的元素执行一个函数// 函数中的参数 // 参数一表示当前元素在所有匹配元素中的索引号 // 参数二表示当前元素(DOM对象) $(selector).each(function(index,element){}); $.each(数组或对象, function(index, value){});第8章 jQuery事件机制JavaScript中已经学习过了事件,jQuery对JavaScript事件进行了封装,增加并扩展了事件处理机制。jQuery不仅提供了更加优雅的事件处理语法,而且极大的增强了事件的处理能力。8.1 jQuery事件发展历程(了解)简单事件绑定--bind事件绑定--delegate事件绑定--on事件绑定(推荐)简单事件注册click(handler) 单击事件 mouseenter(handler) 鼠标进入事件 mouseleave(handler) 鼠标离开事件bind方式注册事件(不用)// 第一个参数:事件类型 // 第二个参数:事件处理程序 $('p').bind('click mouseenter', function(){ // 事件响应方法 });delegate注册委托事件(不用)// 第一个参数:selector,要绑定事件的元素 // 第二个参数:事件类型 // 第三个参数:事件处理函数 $('.parentBox').delegate('p', 'click', function(){ // 为 .parentBox下面的所有的p标签绑定事件 });8.2 on注册事件(重点)jQuery1.7之后,jQuery用on统一了所有事件的处理方法。强烈建议使用。on注册简单事件// 表示给$(selector)绑定事件,并且由自己触发,不支持动态绑定。 $(selector).on( 'click', function() {});on注册事件委托// 表示给$(selector)绑定代理事件,当必须是它的内部元素span才能触发这个事件,支持动态绑定 $(selector).on( 'click','span', function() {});on注册事件的语法:// 第一个参数:events,绑定事件的名称可以是由空格分隔的多个事件(标准事件或者自定义事件) // 第二个参数:selector, 执行事件的后代元素(可选),如果没有后代元素,那么事件将由自己执行。 // 第三个参数:data,传递给处理函数的数据,事件触发的时候通过event.data来使用(不常使用) // 第四个参数:handler,事件处理函数 $(selector).on(events[,selector][,data],handler);8.3 事件解绑unbind方式(不用)$(selector).unbind(); // 解绑所有的事件 $(selector).unbind('click'); // 解绑指定的事件undelegate方式(不用)$( selector ).undelegate(); // 解绑所有的delegate事件 $( selector).undelegate( 'click' ); // 解绑所有的click事件off方式(推荐)// 解绑匹配元素的所有事件 $(selector).off(); // 解绑匹配元素的所有click事件 $(selector).off('click');8.5 触发事件$(selector).click(); // 触发 click事件 $(selector).trigger('click');8.6 jQuery事件对象jQuery事件对象其实就是js事件对象的一个封装,处理了兼容性。// screenX和screenY 对应屏幕最左上角的值 // clientX和clientY 距离页面左上角的位置(忽视滚动条) // pageX和pageY 距离页面最顶部的左上角的位置(会计算滚动条的距离) // event.keyCode 按下的键盘代码 // event.data 存储绑定事件时传递的附加数据 // event.stopPropagation() 阻止事件冒泡行为 // event.preventDefault() 阻止浏览器默认行为 // return false:既能阻止事件冒泡,又能阻止浏览器默认行为。第9章 jQuery动画效果jQuery提供了三组基本动画,这些动画都是标准的、有规律的效果,jQuery还提供了自定义动画的功能。演示动画效果 [08-演示jQuery动画(animate).html]9.1 三组基本动画(重点)显示(show)与隐藏(hide)与切换(toggle)是一组动画:滑入(slideUp)与滑出(slideDown)与切换(slideToggle),效果与卷帘门类似淡入(fadeIn)与淡出(fadeOut)与切换(fadeToggle)$obj.show([speed], [callback]); // speed(可选):动画的执行时间 // 1.如果不传,就没有动画效果。如果是slide和fade系列,会默认为normal // 2.毫秒值(比如1000),动画在1000毫秒执行完成(推荐) // 3.固定速度字符串,slow(200)、normal(400)、fast(600),如果传其他字符串,则默认为normal。 // callback(可选):执行完动画后执行的回调函数 slideDown()/slideUp()/slideToggle();同理 fadeIn()/fadeOut();fadeToggle();同理 $('img').show(2000);fadeTo 淡入淡出到指定透明度$obj.fadeTo(speed, opacity, callback) $('img').fadeTo(1000, 0.5);9.2 自定义动画animate: 自定义动画$(selector).animate({params},[speed],[easing],[callback]); // {params}:要执行动画的CSS属性,带数字(必选) // speed:执行动画时长(可选) // easing:执行效果,默认为swing(缓动) 可以是linear(匀速) // callback:动画执行完后立即执行的回调函数(可选)9.3 动画队列与停止动画在同一个元素上执行多个动画,那么对于这个动画来说,后面的动画会被放到动画队列中,等前面的动画执行完成了才会执行(联想:火车进站)。// stop方法:停止动画效果 stop(clearQueue, jumpToEnd); // 第一个参数:是否清除队列 // 第二个参数:是否跳转到最终效果延迟动画:delay方法$obj.delay(2000).show(200); //延迟后续的动画第10章 jQuery节点操作10.1 创建节点document.createElement()// $(htmlStr) // htmlStr:html格式的字符串 $('<span>这是一个span元素</span>');10.2 添加节点append appendTo 在被选元素的结尾插入内容 父.append(子) 子.appendTo(父) prepend prependTo 在被选元素的开头插入内容 父.prepend(子) 子.prependTo(父) before insertBefore 在被选元素之后插入内容 后.before(前) 前.insertBefor(后) after insertAfter 在被选元素之前插入内容 前.after(后) 后.insertAfter(前) 推荐记 前面的一列方法 append prepend before after10.3 清空节点与删除节点empty:清空指定节点的所有元素,自身保留(清理门户)$('div').empty(); // 清空div的所有内容(推荐使用,会清除子元素上绑定的事件) $('div').html('');// 使用html方法来清空元素,不推荐使用,绑定的事件不会被清除。remove:相比于empty,自身也删除(自杀)$('div').remove();10.4 克隆节点作用:复制匹配的元素// 复制$(selector)所匹配到的元素(深度复制) // cloneNode(true) //原生js cloneNode 不传参数 克隆标签本身,传参数true 克隆标签本身以及内容 // 返回值为复制的新元素,和原来的元素没有任何关系了。即修改新元素,不会影响到原来的元素。 $(selector).clone();//克隆元素本身及后代 $(selector).clone(true);//克隆元素本身及后代以及绑定的事件第11章 jQuery工具方法11.1 数组和对象操作①$.inArray(value, array, [fromIndex])确定第一个参数在数组中首次出现的位置,从0开始计数(如果没有找到则返回 -1 )。value:用于在数组中查找是否存在array:待处理数组。fromIndex:用来搜索数组队列,默认值为0。$.inArray(1,[1,2,3,1]); $.inArray(1,[1,2,3,1],2);②$(‘选择器’).toArray(); 把jQuery集合中所有DOM元素恢复成一个数组。$('div').toArray();③$.merge(first, second); 合并数组$.merge([1,2,3], [4,3,2]);④$.parseJSON(str); 解析json字符串为对象,等价于 JSON.parse(str);$.parseJSON('{"name":"zhangfei","age":30}');JSON就是一种 以键值对方式描述数据的数据格式。 可以是对象格式,也可以使字符串格式。11.2 字符串操作$.trim(str) 去除字符串两边的空格, 等价于 str.trim()$.trim(' 123 ');11.3 类型操作$.type(obj) 判断数据类型 typeof $.isArray(obj) 判断是否数组 obj instanceof Array $.isFunction(obj) 判断是否函数 obj instanceof Function $.isEmptyObject(obj) 判断是否空对象(没有成员) $.isPlainObject(obj) 判断是否纯对象(字面量语法{}或实例化new Object() 定义的对象) 纯对象:不包括 实例化的数组对象等 $.isNumeric(obj) 判断是否数字(数字型或字符串型数字)第12章 插件12.1 jQuery插件开发语法给jQuery增加方法的两种方式$.method = fn 静态方法 $.fn.method = fn 实例方法 $.fn.extend({}) 批量扩展实例方法 参数是一个对象12.2 常用插件弹出层插件 layerlayer插件放大镜插件jQuery.zoom轮播图插件http://sorgalla.com/jcarousel/https://github.com/OwlCarousel2/OwlCarousel2图片懒加载插件jQuery.lazyloadjQueryUI常用的2-3个功能演示图片放大github上搜索案例增加一个静态方法,实现两个数的和,插件(function ($) { $.add = function (a, b) { return a + b; } })(jQuery) $.add(5, 6);
2022年10月13日
125 阅读
0 评论
0 点赞
2022-10-13
javascript高级-正则表达式
第1章 什么是正则表达式1、概述正则表达式(regular expression)正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来对字符串的进行匹配。用途:检查一个字符串中是否含有某种子串将匹配的某种子串做替换从某个字符串中取出符合某个条件的子串等。“996.icu”1、判断有没有992、判断有没有小数点.3、icu 替换为 tsc // ‘996.icu’.replace(/icu/, ‘tsc’)4、获取其中的9 和 u2、应用场景(1)表单验证里面,验证字符的合法性,如邮箱是否合法,手机号是否合法等等。(2)信息过滤,如论坛帖子或者评论中的非法字符,例如 sql注入、js脚本注入、煽动性的言论。(3)信息采集,采集别人网站上面的内容,例如整页采集时 筛选出需求的部分(4)信息替换。(5)页面伪静态的规则(url重写)。3、入门案例 //匹配str字符串中p是否存在 var str = 'php'; var result = str.match(/p/); //var result = str.match(/参数就是正则表达式/); //返回包含匹配结果的数组或者null其中,正则表达式前后的 斜杠/ 叫做定界符,是固定格式。 //匹配str字符串中所有p var str = 'php'; var result = str.match(/p/g);//进行全局匹配,匹配所有g是global,表示全局的意思,它是正则表达式语法中的修饰符,修饰符应该放到定界符(/)的后面。第2章 正则语法-元字符正则表达式中的字符:元字符:一些具有特殊含义的特殊符号。普通字符:包括所有大写和小写字母、所有数字、所有标点符号和一些其他符号。正则表达式三步走① 匹配符(查什么)(等价符、字符簇、修饰符、转义符)② 限定符(查多少)③ 定位符(从哪查)1、限定符限定符(量词)用来指定正则表达式的一个给定组件必须要出现多少次才能满足匹配。有 * 或 + 或 ? 或 {n} 或 {n,} 或 {n,m} 共6种。*匹配前面的子表达式零次或多次。例如,zo 能匹配 "z" 以及 "zoo"。 等价于{0,}。+匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。?匹配前面的子表达式零次或一次。例如,"do(es)?" 可以匹配 "do" 、 "does" 中的 "does" 、 "doxy" 中的 "do" 。? 等价于 {0,1}。{n}n 是一个非负整数。匹配确定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。{n,}n 是一个非负整数。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。{n,m}m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 将匹配 "foooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。 var str = 'phpphp'; var res = str.match(/p+/g);//匹配所有的一个p或多个连在一起的p console.log(res);//["p", "pp", "p"]贪婪匹配与非贪婪匹配:默认情况下,正则表达式执行贪婪匹配(尽可能取多的情况)非贪婪匹配:相对于贪婪匹配来说的。设置方式:将?加在其他限定符之后。 var str = 'phpphp'; var res = str.match(/p+?/g);//+后面有? 执行非贪婪匹配(最少匹配) console.log(res);//["p", "p", "p", "p"] 非贪婪匹配使用场景举例:<div id="div1"><div id="div2">abc</div></div>匹配div2标签2、等价符.匹配除换行符(\n、\r)之外的任何单个字符。要匹配包括 '\n' 在内的任何字符,请使用像"**(.\\n)**"的模式。\d匹配一个数字字符。等价于 [0-9]。\D匹配一个非数字字符。等价于 [ ^0-9]。\w匹配一个字母、数字、下划线。等价于[A-Za-z0-9_]。\W匹配非(字母、数字、下划线)。等价于 [ ^A-Za-z0-9_]。\s匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。\S匹配任何非空白字符。等价于 [ ^ \f\n\r\t\v]。\n匹配一个换行符。等价于 \x0a 和 \cJ。\r匹配一个回车符。等价于 \x0d 和 \cM。\t匹配一个制表符。等价于 \x09 和 \cI。常用的: . \d \w var str = 'php1js22'; var res = str.match(/\d+/g);//匹配所有的数字 console.log(res);//["1", "22"]3、定位符定位符用来描述字符串或单词的边界,^ 和 $ 分别指字符串的开始与结束,\b 描述单词的前或后边界,\B 表示非单词边界。^匹配输入字符串开始的位置。如果设置了 RegExp 对象的 Multiline 属性,^ 还会与 \n 或 \r 之后的位置匹配。$匹配输入字符串结尾的位置。如果设置了 RegExp 对象的 Multiline 属性,$ 还会与 \n 或 \r 之前的位置匹配。\b匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。\B匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。注意: 通常在表单数据验证时,严格检测字符串格式,需要使用^$ var str = '1234'; var res = str.match(/^\d+$/);//匹配整个数字字符串(匹配id参数值) console.log(res);//["1234"] 4、字符簇(方括号)方括号表示一个范围,也称为字符簇,匹配满足条件的一个字符。[xyz]字符集合。匹配所包含的任意一个字符。例如, [abc]可以匹配 "plain" 中的 'a'。[^xyz]负值字符集合。匹配未包含的任意字符。例如, [^abc] 可以匹配 "plain" 中的'p'、'l'、'i'、'n'。[a-z]字符范围。匹配指定范围内的任意字符。例如, [a-z] 可以匹配 'a' 到 'z' 范围内的任意小写字母字符。[^a-z]负值字符范围。匹配任何不在指定范围内的任意字符。例如,[^a-z]可以匹配任何不在 'a' 到 'z' 范围内的任意字符。x | y或的用法:匹配 x | y。例如,'z | food' 能匹配 "z" 或 "food"。'(z | f)ood' 则匹配 "zood" 或 "food"。字符范围 参考ASCII码表示例:[0-9] 查找任何从 0 至 9 的一个数字。[a-z] 查找任何从小写 a 到小写 z 的字符。[A-Z] 查找任何从大写 A 到大写 Z 的字符。[A-z] 查找任何从大写 A 到小写 z 的字符。包括[ \ ]^_`等六个字符。[A-Za-z]查找任何从大写 A 到小写 z 的字符,不包括[ \ ]^_`等六个字符。var str = 'adcd1234ABCD'; var res = str.match(/[a-z]+/g);//匹配所有小写字母字符串 console.log(res);//["abcd"] 5、修饰符修饰符的用法,修饰符一定要写到正则表达式末尾/之后,可以一次性使用多个修饰符。i 执行对大小写不敏感的匹配。实际上就是不区分大小写的匹配(默认区分大小写)g 执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)。m 执行多行匹配(^和$能匹配每行的开始与结束)。/i用法示例:var str = 'adcd1234ABCD'; var res = str.match(/[a-z]+/gi);//匹配所有字母字符串(忽略大小写) console.log(res);//["adcd", "ABCD"]/m用法示例 var str = '1234\r\n5678'; var res = str.match(/^\d+$/gm);//匹配整个数字字符串 console.log(res);//["1234", "5678"]6、转义字符(\)\将下一个字符标记为一个特殊字符、或一个原义字符、或一个 向后引用、或一个八进制转义符。例如,'n' 匹配字符 "n"。'\n' 匹配一个换行符。序列 '\ \ ' 匹配 "\ " 而 "\ (" 则匹配 "("。 如果匹配的字符串在正则中有特殊含义的都必须加转义字符。如[]$.*?+|^{}()但是不要乱加转义。 var str = 'php.php';//目标字符串中包含普通字符. var res = str.match(/p\.p/g);//匹配普通字符. 需要转义 console.log(res);//["p.p"]匹配图片名称 var str = '123.jpg';//目标字符串中包含普通字符. var res = str.match(/.*\.jpg/g);//匹配jpg后缀的图片名称 console.log(res);//["123.jpg"]练习题:匹配字符串开始和结束的数字 预期结果 123 789; ^ \d | $var str = '123abc456def789'; var res = str.match(/(^\d+)|(\d+$)/g);//匹配开始或结束的数字 console.log(res);//["123","789"]第3章 js中正则对象正则对象两种定义方式:js中正则表达式两边不用加引号 var pattern = /[a-z]/;//将正则表达式直接当做对象使用。 var pattern = new RegExp(/[a-z]/);//实例化RegExp对象1、test方法test方法检测目标字符串和正则表达式是否匹配,如果匹配返回true,不匹配返回false。正则表达式中,一般不需要加全局修饰符g。 var str = 'php1js22'; var pattern = /^[a-z]/;//以小写字母开头 var res = pattern.test(str);//匹配字符串是否以小写字母开头 console.log(res);//true2、exec方法exec方法执行一个正则匹配,只匹配一次,匹配到结果就返回一个数组类型的结果,匹配不到就返回null。正则表达式中,一般不需要加全局修饰符g。即使正则表达式中,使用了全局匹配修饰符g,也只匹配一次。 var str = 'php1js22'; var pattern = /[a-z]/;//匹配小写字母字符串 //var pattern = /[a-z]/g;//全局匹配小写字母字符串 var res1 = pattern.exec(str); console.log(res1);//["p"] 只匹配一次,返回数组3、lastIndex属性表示正则表达式,上一次匹配结束后的位置(目标字符串中的索引),即下一次匹配开始的位置。lastIndex是一个整数,。没有更多匹配重置lastIndex为0.test 方法和exec方法默认都只匹配一次。匹配后lastIndex 被自动重置为0.特殊情况:如果正则表达式使用了全局匹配修饰符g,则lastIndex不会被重置为0. var str = 'php1js22'; //var pattern = /[a-z]/;//匹配小写字母字符串 var pattern = /[a-z]/g;//全局匹配小写字母字符串 var res1 = pattern.exec(str); console.log(res1);//["p"] 只匹配一次,返回数组 console.log(pattern.lastIndex);//1 下一次匹配开始的位置 var res2 = pattern.exec(str); console.log(res2);//["h"] //从位置1开始匹配案例一1、检测手机号格式手机号特点:11位,纯数字,1开头, [23位号段,具体咨询各大运营商]简单版(限制前两位):1开头,第二位3-9,后面9位数字/^1[3-9]\d{9}$/精确版(限制前三位):(如果出现新的手机号段,则不适用,需更新)示例:13[0-9]开头、14[579]开头、15[0-3,5-9]开头、166开头、17[0135678]开头、18[0-9]开头、19[89]开头/^1(3[0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|8[0-9]|9[89])\d{8}$/手机号检测案例:register.html2、检测邮箱格式邮箱特点:2342.3s_-df@sina.com.cn通用的邮箱的特点:简单版:必须有@ 正则 /@/精确版: 必须有@和. @前面是邮箱名,要求至少一个字符,要求是数字、字母、下划线、[还可以用.-],但是开头必须是数字字母下划线 @和点之间:是一个域名,要求至少一个字符,可以是数字字母中横线,要求开头是数字或字母 点后面:要求是至少一个字符,必须是字母 点xxx,这部分可以出现一次,也可以出现多次最后一个点后面,字符长度为2-6的字母var pattern = /^\w[\w\.-]*@[0-9a-z][0-9a-z-]*(\.[a-z]+)*\.[a-z]{2,6}$/i;register-email.html第4章 分组/捕获和反向引用捕获和反向引用的语法的解释:子表达式在正则表达式中,通过一对圆括号括起来的内容,我们就称之为“子表达式”。如:`var reg = /\d(\d)\d/gi;`捕获(分组)在正则表达式中,子表达式匹配到相应的内容时,系统会自动捕获这个行为,然后将子表达式匹配到的内容放入系统的缓存区中。我们把这个过程就称之为“捕获”。反向引用在正则表达式中,我们可以使用\n(n>0,正整数,代表系统中的缓冲区编号)来获取缓冲区中的内容,我们把这个过程就称之为“反向引用”。在正则语法中,用“\1”来引用前面的捕获(使用子表达式匹配的结果)。用\2表示第二个捕获的内容….在正则语法外(如replace时),用“$1”来引用前面的捕获。 var str = '1122 3434 5566 7879 9887'; //匹配连续四个数字,第一和第二数字相同,第三和第四数字相同 var res = str.match(/(\d)\1(\d)\2/g); console.log(res); //匹配连续四个数字,第一和第三数字相同,第二和第四数字相同 var res = str.match(/(\d)(\d)\1\2/g); console.log(res); //匹配连续四个数字,第一和第三数字相同 var res = str.match(/(\d)\d\1\d/g); console.log(res); //匹配连续四个数字,第一和第二数字相同,第三和第四数字相同,并将相同的数字只保留一个 var res = str.replace(/(\d)\1(\d)\2/g, '$1$2'); console.log(res);禁止引用(?:正则) 这个小括号中的内容不能够被引用 //第一次捕获禁止引用 var str = '1122 3434 5566 7879 9887'; var res = str.match(/(?:\d)(\d)\1\d/g); console.log(res);第5章 匹配中文(utf-8编码)每个字符(中文、英文字母、数字、各种符号、拉丁文、韩文、日文等)都对应着一个Unicode编码。查看Unicode编码,找到中文的部分,然后获取中文的Unicode编码的区间,就可以用正则匹配了。前面我们用[a-z]表示小写字母,[0-9]表示数字,这就是一个范围表示,如果有一个数x能够表示第一个中文,有一个数y能够表示最后一个中文,那么[x-y]就可以表示所有的中文了。中文的Unicode编码从4E00开始,到9FA5结束。[\u4E00-\u9FA5]这个区间就能够表示中文。完整的Unicode编码表:http://blog.csdn.net/hherima/article/details/9045861 var str = "你好,世界"; var res = str.match(/[\u4E00-\u9FA5]/g); console.log(res);//["你", "好", "世", "界"]案例二解决结巴程序把“今今今天晚晚晚晚晚晚上吃吃吃吃吃吃鸡”字符串换成单字的形式,即“今天晚上吃鸡”;核心思想:匹配到重复的字符时,保留一个。 var str = "今今今天晚晚晚晚晚晚上吃吃吃吃吃吃鸡"; //今天晚上吃鸡 var res = str.replace(/([\u4E00-\u9FA5])\1+/g, '$1'); console.log(res);第6章 环视也叫 预查、断言、零宽断言。正则表达式中,用于查找某些内容之前或者之后的东西,叫做环视。环视通常也叫做预查、断言或者零宽断言。1、正向肯定预查也叫 顺序肯定环视every(?=n) 匹配任何其后紧接指定字符串 n 的字符串。 //匹配后面字符为10的win var str = "win7 win8 win10"; var res = str.match(/win(?=10)/g); console.log(res); //["win"]2、正向否定预查也叫 顺序否定环视every(?!n) 匹配任何其后没有紧接指定字符串 n 的字符串。 //匹配后面字符不为10的win var str = "win7 win8 win10"; var res = str.match(/win(?!10)/g); console.log(res); //["win", "win"](?!B)[A-Z]这种写法,其实它是[A-Z]范围里,排除B的意思,前置的(?!B)只是对后面数据的一个限定,从而达到过滤匹配的效果。 var str = "abcd1234"; var res = str.match(/(?!c)[a-z]/g); console.log(res); //["a", "b", "d"]练习:从一堆图片地址中,找出符合条件的图片地址。 var arr = [ 'img/a.jpg', 'img/20181014/b.png', 'image/20181014/a.jpg', 'image/20181013/b.png', '20181013/c.png' ];匹配img开头的图片地址/^img.*(jpg|png|gif)$/g匹配不以image开头的图片地址/^(?!image).*(jpg|png|gif)$/第7章 String 对象的正则方法1、match方法stringObj.match(regex)在字符串中检索匹配正则表达式regex的子串;如果匹配,返回包含匹配结果的一个数组;不匹配返回null。正则表达式regex中不带全局修饰符g,则只匹配一次。正则表达式regex中带全局修饰符g,则匹配所有结果。 var str = "1234@qq.com"; var res = str.match(/[@\.]/g); // .要加转义 console.log(res); //["@", "."]2、replace方法stringObj.replace(regex, replacement)在字符串中检索匹配正则表达式regex的子串,并替换为指定的字符串replacement;返回替换之后的新字符串。正则表达式regex中不带全局修饰符g,则只匹配一次并替换一次。正则表达式regex中带全局修饰符g,则匹配所有结果并替换所有结果。替换的时候,使用"$1"表示匹配的第一个子表达式:用$2表示第二个子表达式,以此类推。3、search方法stringObj.search(regex)在字符串中搜索符合正则表达式的结果。如果找到结果返回结果的起始位置,停止向后检索,也就是说忽略全局标识符g;如果没有匹配结果,返回-1. var str = "1234@qq.com"; var res = str.search(/[@\.]/); // .要加转义 console.log(res); //44、split方法stringObj.split(regex)把一个字符串分割成字符串数组, 返回一个数组 var str = "1234@qq.com"; var res = str.split(/[@\.]/);// .要加转义 console.log(res); //["1234", "qq", "com"]手机端判断const is_mobile = /windows phone|iphone|android/gi.test(window.navigator.userAgent)
2022年10月13日
84 阅读
0 评论
3 点赞
1
...
12
13
14
...
17