(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非常容易在客戶端被改變。
推薦首頁截圖