(1) babel-polyfill
- 在低版本的浏览器中不能支持es6语法,所以用babel-polyfill来解决
- 作用和babel-runtime类似,能够使用es6的api
- 安装
cnpm install babel-polyfill --save-dev
- 使用
在入口文件main.js中
1.require("babel-polyfill"); // es5
2.import "babel-polyfill"; // es6,写在main.js的最开始位置
3.module.exports = {
entry: ["babel-polyfill", "./app/js"]
};
注:第三种方法适用于使用webpack构建的同学,加入到webpack配置文件(webpack.config.js)entry项中
ps: ( polyfill是补丁的意思 )
(2) babel-runtime 作用和babel-polyfill类似,能够使用es6的api
cnpm install babel-runtime --save // 这里是--save,用在线上环境
(3) fastclick 解决移动端点击 300ms 延迟
- 安装
cnpm install fastclick --save // 这里是--save,用在线上环境
- 引入
在入口文件main.js中
import fastclick from ' fastclick '
- 使用
fastclick.attach(document.body)
(4) 两种方法实现,默认跳转到指定的路由页面
- router.push('/xxx')
- redirect
- 区别:有痕和无痕的区别
router.push('/') 只要刷新页面就会跳转到指定的路由页面
而 redirect 会记住当前选中的路由页面
(1) router.push('/路由地址')使用方法
在main.js中:
router.push('/recommend')
-------------------------------------------------------------------
(2) redirect ( 跟路由重定向 ) 使用方法
在router/index.js路由入口页面中:
export default new Router({
routes: [
{ path: '/', name: 'home', redirect: '/recommend' }, // 根路由重定向,会记住路由路径
{ path: '/recommend', name: 'recommend', component: Recommend },
{ path: '/singer', name: 'singer', component: Singer }
{ path: '/rank', name: 'rank', component: Rank },
{ path: '/search', name: 'search', component: Search },
]
})
(5) jsonp
(1) ( webmodules/jsonp )
- 安装
cnpm install jsonp --save
- 使用 ( api )
jsonp(url, options, fn) // 现在基本用promise结构了
jsonp(url, options, (err, data) => { })
url : ( String ) 请求地址
opts : ( Object ) 有如下选项:
param ( String ) 参数,默认是一个回调函数。和 后端约定的字段参数名 **
timeout ( Number ) 超时时间,默认1分钟后。 **
prefix ( String ) callback等于什么,在前面加个前缀。默认 __jp
name ( String )
fn callback回调函数,很少用回调,es6中基本用封装promise方法
- jsonp的封装
(2) promise
- (1) promise实例化:使用new来调用Promise的构造器来进行实例化
var promise = new Promise(function(resolve, reject) {
// 异步处理
// 处理结束后、调用resolve 或 reject
// resolve 成功时候的回调
// reject 失败时候的回调
});
- (2) 用Promise() 封装 jsonp
_getData() {
return new Promise((resolve, reject) => {
Jsonp('https://c.y.qq.com/musichall/fcgi-bin/fcg_yqqhomepagerecommend.fcg?g_tk=5381&uin=0&format=json&inCharset=utf-8&outCharset=utf-8¬ice=0&platform=h5&needNewCode=1&_=1505661043507', {param: 'jsonpCallback'}, (err, data) => {
if (!err) {
resolve(data)
console.log(data)
} else {
reject(err)
}
})
})
}
(3) for in循环
for...in 语句用于对数组或者对象的属性进行循环操作。
与for循环的区别:
for循环是对数组的元素进行循环,而不能用于非数组对象。
for (变量 in 对象)
{
在此执行代码
}
---------------------------------------------------
遇到数组时key为数据下标 ,遇到对象时 key为对象(名称:值)项的名称。
for (var k in data) {
let value = data[k] !== undefined ? data[k] : ''
url += '&' + k + '=' + encodeURIComponent(value) // 这里的k不是下标(数字),而是key:value中的key
}
(4) encodeURIComponent( URIstring )
encodeURIComponent(URIstring) 函数可把字符串作为 URI 组件进行编码。
- 返回值 :
URIstring 的副本,其中的某些字符将被十六进制的转义序列进行替换。
<script type="text/javascript">
document.write(encodeURIComponent("http://www.w3school.com.cn"))
document.write("<br />")
document.write(encodeURIComponent("http://www.w3school.com.cn/p 1/"))
document.write("<br />")
document.write(encodeURIComponent(",/?:@&=+$#"))
</script>
---------------------------------------
输出:
http%3A%2F%2Fwww.w3school.com.cn
http%3A%2F%2Fwww.w3school.com.cn%2Fp%201%2F
%2C%2F%3F%3A%40%26%3D%2B%24%23
http://www.w3school.com.cn/jsref/jsref_encodeURIComponent.asp
(5) stringObject.substring( start, stop )
- stringObject.substring(start,stop)方法用于提取字符串中介于两个指定下标之间的字符。
- start : 必须,提取的开始位置
- stop : 可选,提取的结束位置
- 返回值 :
一个新的字符串,该字符串值包含 stringObject 的一个子字符串,其内容是从 start 处到 stop-1 处的所有字符,其长度为 stop 减 start。 - ( substring是子链的意思 )
<html>
<body>
<script type="text/javascript">
var str="Helloworld!"
document.write(str.substring(3,7))
</script>
</body>
</html>
---------------------------------------------
输出结果:
lowo
(6) stringObject.indexOf(searchvalue,fromindex)
- indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。
- searchvalue : 必需。规定需检索的字符串值
- fromindex : 可选。规定在字符串中开始检索的位置。
- 位置是从0开始计算的
- 大小写敏感
- 如果要检索的字符串值没有出现,则该方法返回 -1。
<script type="text/javascript">
var str="Hello world!"
document.write(str.indexOf("Hello") + "<br />")
document.write(str.indexOf("World") + "<br />") // 这个W是大写的
document.write(str.indexOf("world"))
</script>
----------------------------------------------
输出结果:
0
-1
6
(7) Object.assign( target, ...sources )
- Object.assign() 方法用于将所有可枚举的属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
- target : 目标对象。
- sources : (多个)源对象
- 返回值 :
目标对象 - assign : 是转让,受托的意思
复制一个 object
var obj = { a: 1 };
var copy = Object.assign({}, obj);
console.log(copy); // { a: 1 }
--------------------------------
合并 objects
var o1 = { a: 1 };
var o2 = { b: 2 };
var o3 = { c: 3 };
var obj = Object.assign(o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
console.log(o1); // { a: 1, b: 2, c: 3 }, 注意目标对象自身也会改变。
const data = Object.assign({}, commonParams, { // 把commonParams和{}一起复制给data
platform: 'yqq',
hostUin: 0,
sin: 0,
ein: 29,
sortId: 5,
needNewCode: 0,
categoryId: 10000000,
rnd: Math.random(),
format: 'json'
})
export default {
data() {
return {
aa: {爱好: '代码'}
}
},
created() {
this.getArray()
},
methods: {
getArray() {
const bb = Object.assign({}, {姓名: '张三', 年龄: '20', 性别: '男'}, this.aa)
console.log(bb)
}
}
}
输出结果:Object {姓名: "张三", 年龄: "20", 性别: "男", 爱好: "代码"}
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
(6) 插槽 < slot > 与 内容分发
插槽作用: 为了让组件自由组合,分发内容。比如抽象scroll组件的时候,slot里面可以是任何内容,也不关心是什么内容。只要实现其滚动就好。
什么是内容分发:
为了让组件可以组合,我们需要一种方式来 混合父组件的内容与子组件自己的模板。这个过程被称为内容分发 (或“transclusion”如果你熟悉 Angular)。单个插槽:除非子组件模板包含至少一个 <slot> 插口,否则父组件的内容将会被丢弃。当子组件模板只有一个没有属性的插槽时,父组件整个内容片段将插入到插槽所在的 DOM 位置,并替换掉插槽标签本身。
父组件
<div>
<h1>我是父组件的标题</h1>
<my-component> // 子组件
<p>这是一些初始内容</p>
<p>这是更多的初始内容</p>
</my-component>
</div>
-----------------------------------------------------------
子组件 my-component
<div>
<h2>我是子组件的标题</h2>
<slot>
只有在没有要分发的内容时才会显示。 // 备用内容,只有在没有要分发的内容时才会显示
</slot> // 备用内容在子组件的作用域内编译
</div>
------------------------------------------------------------
渲染结果:
<div>
<h1>我是父组件的标题</h1> // 父组件自己的内容
<div>
<h2>我是子组件的标题</h2> // 子组件自己的内容
<p>这是一些初始内容</p> // 以下是插槽分发的内容
<p>这是更多的初始内容</p>
</div>
</div>
父组件模板的内容在父组件作用域内编译;子组件模板的内容在子组件作用域内编译。
(6) 具名插槽 < slot name="xxx" >
- < slot > 在子组件中用 name 来配置如何分发内容,多个插槽可以有不同的名字。
- 具名插槽将匹配内容片段中有对应 slot 特性的元素。
- ps:仍然可以有一个匿名插槽,它是默认插槽,作为找不到匹配的内容片段的备用插槽。如果没有默认插槽,这些找不到匹配的内容片段将被抛弃。
父组件
<app-layout>
<h1 slot="header">这里可能是一个页面标题</h1>
<p>主要内容的一个段落。</p>
<p>另一个主要段落。</p>
<p slot="footer">这里有一些联系信息</p>
</app-layout>
-----------------------------------------------------
子组件
<div class="container">
<header>
<slot name="header"></slot> // 该具名插槽,将匹配父组件中slot="header"中的内容
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot> // 该具名插槽,将匹配父组件中slot="footer"中的内容
</footer>
</div>
(7) Access control allow origin 访问控制允许同源
- 用axios访问线上地址 get请求 ( 跨域 ),出现 Access-Control-Allow-Origin 报错
- 解决方案:下载 allow control allow origin插件
- 以上方法只能开发中解决,实际开发要用cors。(浏览器和服务端同时支持即可)
- 报错如下图:
- axios请求
安装其他插件的时候,可以直接在 main.js 中引入并使用 Vue.use()来注册,但是 axios并不是vue插件,所以不能 使用Vue.use(),所以只能在每个需要发送请求的组件中即时引入。
为了解决这个问题,我们在引入 axios 之后,通过修改原型链,来更方便的使用。
//main.js
import axios from 'axios'
Vue.prototype.$http = axios
main.js
import axios from 'axios'
Vue.prototype.$http = axios
// prototype属性 : 使您有能力向对象添加属性和方法。
// prototype是原型的意思
---------------------------------------------------------------------------------
recommend.vue
dataImage() { // 百度图片线上接口
this.$http.get('http://image.baidu.com/channel/listjson?pn=15&rn=30&tag1=%E7%BE%8E%E5%A5%B3&tag2=%E5%85%A8%E9%83%A8&ie=utf8')
.then((response) => {
console.log(response)
})
}
(8) 轮播图
(1) 滚动的图片
- clientWidth: 获取对象可见内容的宽度,不包括滚动条,不包括边框;(client:客户端的意思)
- RegExp 对象表示正则表达式,它是对字符串执行模式匹配的强大工具。
- new RegExp(pattern, attributes);
(1)参数 pattern 是一个字符串,指定了正则表达式的模式或其他正则表达式。
(2)参数 attributes 是一个可选的字符串,包含属性 "g"、"i" 和 "m",分别用于指定全局匹配、区分大小写的匹配和多行匹配。ECMAScript 标准化之前,不支持 m 属性。如果 pattern 是正则表达式,而不是字符串,则必须省略该参数。 - test() 方法用于检测一个字符串是否匹配某个模式.
- split() 方法用于把一个字符串分割成字符串数组。
- join() 方法用于把数组中的所有元素放入一个字符串。
<template>
<div class="slider" ref="slider">
<div class="slider-group" ref="sliderGroup">
<slot name="slider">
</slot>
</div>
<div class="dots">
</div>
</div>
</template>
--------------------------------------------------------------------------
methods: {
_setSliderWidth() {
this.children = this.$refs.sliderGroup.children // 拿到sliderGroup的子元素
let width = 0
let sliderWidth = this.$refs.slider.clientWidth // 拿到slider的宽度
for (let i = 0; i < this.children.length; i++) {
let child = this.children[i] // 每一个子元素
addClass(child, 'slider-item') // 给每一个子元素添加名为'slider-item'的class
child.style.width = sliderWidth + 'px' // 每一个子元素的宽度和计算得到的父元素的宽度相同
width += sliderWidth // sliderGroup的总宽度
}
if (this.loop) {
width += sliderWidth * 2
}
this.$refs.sliderGroup.style.width = width + 'px' // sliderGroup的总宽度
},
_initSlider() {
this.slider = new BScroll(this.$refs.slider, { // 获取释口dom
scrollX: true,
scrollY: false,
momentum: true, // 惯性
snap: true, // 用户slider的属性
snpaLoop: this.loop,
snapThreshold: 0.3,
snpaSpeed: 400,
click: true
})
}
}
(2) 滚动图片的dots
1. scrollEnd() 事件
- better-scroll中的 scrollEnd() 事件
scrollEnd()
参数:{Object} {x, y} 滚动结束的位置坐标
触发时机:滚动结束。
2. getCurrentPage() 方法
- better-scroll中的 getCurrentPage() 事件
getCurrentPage()
参数:无
返回值:{Object} { x: posX, y: posY,pageX: x, pageY: y} 其中,x 和 y 表示偏移的坐标值,pageX 和 pageY 表示横轴方向和纵轴方向的页面数。 ( pageIndex )
作用:获取当前页面的信息。
3.goToPage(x, y, time, easing)
参数
{Number} x 横轴的页数
{Number} y 纵轴的页数
{Number} time 动画执行的时间
{Object} easing 缓动函数,一般不建议修改,如果想修改,参考源码中的 ease.js 里的写法
返回值:无
作用:当我们做 slide 组件的时候,slide 通常会分成多个页面。调用此方法可以滚动到指定的页面。
_initSlider() {
this.slider = new BScroll(this.$refs.slider, {
scrollX: true,
scrollY: false,
momentum: false, // 惯性,物理学的动量
snap: true, // 用于slider
snpaLoop: this.loop,
snapThreshold: 0.3,
snpaSpeed: 400,
click: true
})
this.slider.on('scrollEnd', () => { // 在滑动结束时触发事件
let pageIndex = this.slider.getCurrentPage().pageX // 得到当前的index
if (this.loop) {
pageIndex -= 1
}
this.currentPageIndex = pageIndex
})
}
_initDots() { // dots的数量
this.dots = new Array(this.$refs.sliderGroup.children.length) // 长度为5的空数组
}
-------------------------------------------------------------------
<div class="dots">
<span v-for="(item,index) in dots" // 循环dots
class="dot" // 每个dot的class
v-bind:class="{'active': currentPageIndex === index }"> // 当前的dot的class
</span>
</div>
(9) keep-alive
<keep-alive></keep-alive>
如果把切换出去的组件保留在内存中,可以保留它的状态或避免重新渲染。也不会重新请求数据,为此可以添加一个 keep-alive 指令参数:
include 和 exclude 属性允许组件有条件地缓存。二者都可以用逗号分隔字符串、正则表达式或一个数组来表示:
include - 字符串或正则表达式。只有匹配的组件会被缓存。
exclude - 字符串或正则表达式。任何匹配的组件都不会被缓存。
<keep-alive>
<component :is="currentView">
<!-- 非活动组件将被缓存! -->
</component>
</keep-alive>
--------------------------------------------------------------
实例:
<keep-alive>
<router-view></router-view>
</keep-alive>
---------------------------------------------------------------
新增:
<!-- 逗号分隔字符串 -->
<keep-alive include="a,b">
<component :is="view"></component>
</keep-alive>
<!-- 正则表达式 (使用 `v-bind`) -->
<keep-alive :include="/a|b/">
<component :is="view"></component>
</keep-alive>
<!-- 数组 (使用 `v-bind`) -->
<keep-alive :include="['a', 'b']">
<component :is="view"></component>
</keep-alive>
(10) destroyed生命周期钩子
Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
(11) axios之服务器端的请求
(11) express Router的使用
(11) 前端不能直接修改request headers,所以需要使用后端代理:原理是,前端请求的url地址,不是直接请求别的网站地址,而是自己的server端 ( 后端路由给的地址),然后由后端再去请求别的网站地址。
1. referer 请求的来源
Http协议头中的Referer主要用来让服务器判断来源页面, 即用户是从哪个页面来的,通常被网站用来统计用户来源,是从搜索页面来的,还是从其他网站链接过来,或是从书签等访问,以便网站合理定位.
Referer有时也被用作防盗链, 即下载时判断来源地址是不是在网站域名之内, 否则就不能下载或显示,很多网站,如天涯就是通过Referer页面来判断用户是否能够下载图片.
当然,对于某些恶意用户,也可能伪造Referer来获得某些权限,在设计网站时要考虑到这个问题.-
还可用做电子商务网站的安全,在提交信用卡等重要信息的页面用referer来判断上一页是不是自己的网站,如果不是,可能是黑客用自己写的一个表单,来提交,为了能跳过你上一页里的javascript的验证等目的。
但是注意不要把Rerferer用在身份验证或者其他非常重要的检查上,因为Rerferer非常容易在客户端被改变。