20191231pm

20191231

筆試題

你使用過哪些方法,來提升微信小程序的應用速度?

- 提升頁面加載速度
- 用戶行爲預測
- 減小默認 data 的大小
- 組件化方案

https://www.jianshu.com/p/3bf...javascript

1、提升頁面加載速度

在小程序這個環境下,怎樣提升頁面加載速度呢? 這個問題很大,我把問題具體一下,如何縮短從用戶點擊某個連接,到打開新頁面的這段時間? 這裏拋一個核心關鍵點:

從頁面響應用戶點擊行爲,開始跳轉,到新頁面onload事件觸發,存在一個延遲,這個延遲大概在100-300ms之間(安卓響應比ios慢些)。

這個延遲說短不短,咱們能夠利用這段時間,預先發起新頁面所須要的網絡請求。這樣一來,就節省了100-300ms(或者一個網絡請求的時間)。

知道有這個gap後,代碼如何實現呢?

說白了,就是實現一個在A頁面預加載B頁面數據的功能。但而這種跨頁面的調用,很容易把邏輯搞複雜,將不一樣頁面的邏輯耦合在一塊兒。因此,咱們但願將預加載的邏輯隱藏於無形中,不增長任何的頁面間耦合,以及開發複雜度。

下面以騰訊視頻小程序爲例,講解下技術實現。

小程序首頁:


當用戶點擊海報圖後,會執行如下代碼(就一行):


接下來程序會加載播放頁:


播放頁主要代碼:


能夠看到,無論是外部頁面的調用仍是實際邏輯的實現都很是簡潔。在第二個頁面中,咱們擴展了Page的生命週期函數,增長了onNavigate方法。該方法在頁面即將被建立但還沒開始建立的時候執行。

老司機也許會發現這裏有點蹊蹺。在首頁點擊的時候,播放頁根本就沒有建立,對象都不存在,怎麼訪問到裏面的方法呢?

這裏就要說下微信的頁面機制。

在小程序啓動時,會把全部調用Page()方法的object存在一個隊列裏(以下圖)。每次頁面訪問的時候,微信會從新建立一個新的對象實例(實際上就是深拷貝)。

也就是說,在A頁面在執行點擊響應事件的時候,B頁面的實例還沒建立,這時候調用的onNavigate方法,其實是Page對象的原型(小程序啓動時候建立的那個)。

而接下來立刻要被建立的B頁面,又是另一個object。因此,在onNavigate和onLoad方法中,this指針指的不是同一個對象,不能把臨時數據存儲在當前object身上。所以咱們封裝了一對全局的緩存方法,$put()和$take()。


爲了通用性,Page上用到的公共的方法,好比$route、$put、$take都定義在了一個Page的基類裏面。基類還同時保存了全部頁面的list,這樣就能夠作到根據頁面名調用具體頁面的onNavigate方法。 固然,並非每一個頁面都須要實現onNavigate方法,對於沒有定義onNavigate方法的,$route函數會跳過預加載環節,直接跳轉頁面。因此對於開發者來講,不須要關心別的頁面實現了什麼,對外看來徹底透明。

2、用戶行爲預測

在上面的例子中,咱們實現了用戶主動點擊頁面,提早加載下一頁面數據的方法。而在某些場景下,用戶的行爲能夠預測,咱們能夠在用戶還沒點擊的時候就預加載下個頁面的數據。讓下個頁面秒開,進一步提高體驗的流暢性。

繼續以騰訊視頻小程序爲例,主界面分爲3個頁卡(大部分小程序都會這麼設計),經過簡單的數據分析,發現進入首頁的用戶有50%會訪問第二個頁卡。因此預加載第二個頁卡的數據能夠很大程度提升用戶下個點擊頁面的打開速度。

一樣,先看看代碼實現。 首頁預加載頻道頁的姿式:


頻道頁的實現方法:


跟第一個例子相似,這裏定義了一個$preLoad()方法,同時給Page擴展了一個onPreload事件。頁面調用$preLoad()後,基類會自動找到該頁面對應的onPreload函數,通知頁面執行預加載操做。 跟第一個例子不一樣,這裏預加載的數據會保存在storage內,由於用戶不必定會立刻訪問頁面,而把數據存在全局變量會增長小程序佔用的內存。微信會絕不猶豫的把內存佔用過大的小程序給殺掉。

也許對於大部分有app開發經驗的同窗來講,更廣泛的作法是先讓頁面展現上次緩存的數據,再實時拉取新數據,而後刷新頁面。這個方法在小程序上也許體驗並不太好,緣由是小程序的性能以及頁面渲染速度都不如原生app。將一個大的data傳輸給UI層,是一個很重的操做。所以不建議採用這種方法。

3、減小默認data的大小

剛剛說到,頁面打開一個新頁面時微信會深拷貝一個page對象,所以,應該儘可能減小默認data的大小,以及減小對象內的自定義屬性。有圖有真相:


以一個100個屬性的data對象爲測試用例,在iphone6上,頁面的建立時間會所以增長150ms。

4、組件化方案

微信沒有提供小程序的組件化方案(相信必定在實現中)。但開談不說組件化,寫再多代碼也枉然。這裏演示一個簡單的組件化實現。

以騰訊視頻播放頁爲例,頁面定義以下:


其中,P()函數是自定義的基類。這是一個很是有用的東西,能夠把全部通用的邏輯都寫在基類裏面,包括pv統計,來源統計,擴展生命週期函數,實現組件化等。

函數第一個參數是頁面名稱,做爲頁面的key。第二個是page對象,其中擴展了一個comps數組,裏面就是全部要加載的組件。

以播放器組件/comps/player/index.js爲例:


組件的定義跟一個普通Page對象如出一轍,有data屬性,onLoad、onShow等事件,也有頁面響應的回調方法。wxml模板裏定義的事件和js事件一一對應。

基類作的事情,就是把這些組件對象的屬性和方法複製到Page對象上(淺拷貝)。其中data屬性會merge到一塊兒。而微信預約義的生命週期函數(包括本身擴展的),則封裝成隊列按序執行。好比當系統調用onLoad方法時,其實是執行了全部組件的onLoad方法,最後再執行Page的onLoad。

以上是代碼部分,至於wxml模板和wxss部分,就要手工import過去了。

wxml:


wxss:


5、其餘

雖然小程序已經足夠小巧,但啓動速度仍是有那麼2-3秒,沒法作到秒開。樓主嘗試對小程序的啓動時間作優化,但沒有找到多少有價值的優化點。單個頁面的初始化只須要1-2ms。也許大部分時間消耗在了微信跟服務器端通訊的過程當中。

所幸,騰訊提供了一個能夠自主進行服務器性能測試的環境,用戶只須要填寫域名和簡單的幾個參數就能夠獲知本身的服務器性能狀況,目前在騰訊WeTest平臺能夠無償使用。

怎麼解決小程序的異步請求問題?

小程序支持大部分 ES6 語法
一、在返回成功的回調裏面處理邏輯
二、Promise 異步

https://blog.csdn.net/qq_1664...php

小程序通常須要用token,去識別用戶身份,每次獲取到token以後,再進行下一步操做。再獲取到token以後,將token同步緩存,

app.js:

login: function () {
        var that = this;
        return new Promise(function (resolve, reject) {
            if (wx.getStorageSync('token')) {
                resolve(wx.getStorageSync('token'))
            } else {
                wx.login({
                    success: function (res) {
                        if (res.code) {
                            wx.request({
                                url: that.baseUrl + 'tt/wx/' + res.code,
                                header: {
                                    'content-type': 'application/json',
                                    'cld.stats.page_entry': that.globalData.scene,
                                    'version': that.globalData.version
                                },
                                method: 'GET',
                                success: function (e) {
                                    if (e.statusCode == 200) {
                                        that.globalData.token = e.data.token;
                                        wx.setStorageSync('token', e.data.token);
                                        resolve(e.data.token)
                                    }
                                },
                                fail: () => {
 
                                }
                            })
                        } else {
                            console.log('登陸失敗!' + res.errMsg)
                        }
                    }
                });
            }
        })
    },
在調用login方法的時候先判斷本地有沒有緩存的token,若是有直接返回,沒有的話再從後臺經過接口獲取,獲取以後token以後同步緩存。

在首頁index.js,頁面onload的時候須要加載新聞列表,由於小程序全部請求都是異步加載,直接從緩存取token,有可能取不到,這樣能夠再index.js裏面這樣寫,具體的封裝請求方法,在個人另外一篇博客裏面有方法,這裏很少作敘述。

app.login().then(() => {
   api.request(api.Url.newsList, 'POST', {
    type: 1,
    page:1
    }).then(res => {
        console.log('success:', res)
    }).catch(res => {
      console.log("fail:", res)
    }).finallly(()=>{
        console.log("finallly:", 結束)
    })
});
這樣的話就會避免取不到token的狀況,之因此在login方法先判斷是否存在token緩存,一是避免沒必要要的請求,二是避免重複請求

小程序和Vue寫法的區別?

https://segmentfault.com/a/11...css

1、生命週期

先貼兩張圖:

vue生命週期

clipboard.png

小程序生命週期

clipboard.png

相比之下,小程序的鉤子函數要簡單得多。

vue的鉤子函數在跳轉新頁面時,鉤子函數都會觸發,可是小程序的鉤子函數,頁面不一樣的跳轉方式,觸發的鉤子並不同。

onLoad: 頁面加載
一個頁面只會調用一次,能夠在 onLoad 中獲取打開當前頁面所調用的 query 參數。
onShow: 頁面顯示
每次打開頁面都會調用一次。
onReady: 頁面初次渲染完成
一個頁面只會調用一次,表明頁面已經準備穩當,能夠和視圖層進行交互。
對界面的設置如wx.setNavigationBarTitle請在onReady以後設置。詳見生命週期
onHide: 頁面隱藏
當navigateTo或底部tab切換時調用。
onUnload: 頁面卸載
當redirectTo或navigateBack的時候調用。
數據請求

在頁面加載請求數據時,二者鉤子的使用有些相似,vue通常會在created或者mounted中請求數據,而在小程序,會在onLoad或者onShow中請求數據。

2、數據綁定

VUE:vue動態綁定一個變量的值爲元素的某個屬性的時候,會在變量前面加上冒號:,例:

<img :src="imgSrc"/>
小程序:綁定某個變量的值爲元素屬性時,會用兩個大括號括起來,若是不加括號,爲被認爲是字符串。例:

<image src="{{imgSrc}}"></image>
3、列表渲染

直接貼代碼,二者仍是有些類似
vue:

<ul id="example-1">
  <li v-for="item in items">
    {{ item.message }}
  </li>
</ul>

var example1 = new Vue({
  el: '#example-1',
  data: {
    items: [
      { message: 'Foo' },
      { message: 'Bar' }
    ]
  }
})
小程序:


Page({
  data: {
    items: [
      { message: 'Foo' },
      { message: 'Bar' }
    ]
  }
})

<text wx:for="{{items}}">{{item}}</text>
4、顯示與隱藏元素

vue中,使用v-if 和v-show控制元素的顯示和隱藏

小程序中,使用wx-if和hidden控制元素的顯示和隱藏

5、事件處理

vue:使用v-on:event綁定事件,或者使用@event綁定事件,例如:

<button v-on:click="counter += 1">Add 1</button>
<button v-on:click.stop="counter+=1">Add1</button>  //阻止事件冒泡
小程序中,全用bindtap(bind+event),或者catchtap(catch+event)綁定事件,例如:

<button bindtap="noWork">明天不上班</button>
<button catchtap="noWork">明天不上班</button>  //阻止事件冒泡
6、數據雙向綁定

1.設置值

在vue中,只須要再表單元素上加上v-model,而後再綁定data中對應的一個值,當表單元素內容發生變化時,data中對應的值也會相應改變,這是vue很是nice的一點。

<div id="app">
    <input v-model="reason" placeholder="填寫理由" class='reason'/>
</div>

new Vue({
  el: '#app',
  data: {
   reason:''
  }
})
可是在小程序中,卻沒有這個功能。那怎麼辦呢?
當表單內容發生變化時,會觸發表單元素上綁定的方法,而後在該方法中,經過this.setData({key:value})來將表單上的值賦值給data中的對應值。
下面是代碼,能夠感覺一下:

<input bindinput="bindReason" placeholder="填寫理由" class='reason' value='{{reason}}' name="reason" />

Page({
data:{
    reason:''
},
bindReason(e) {
    this.setData({
      reason: e.detail.value
    })
  }
})
當頁面表單元素不少的時候,更改值就是一件體力活了。和小程序一比較,vue的v-model簡直爽的不要不要的。

2.取值

vue中,經過this.reason取值

小程序中,經過this.data.reason取值

clipboard.png

7、綁定事件傳參

在vue中,綁定事件傳參挺簡單,只須要在觸發事件的方法中,把須要傳遞的數據做爲形參傳入就能夠了,例如:

<button @click="say('明天不上班')"></button>

new Vue({
  el: '#app',
  methods:{
    say(arg){
    consloe.log(arg)
    }
  }
})
在小程序中,不能直接在綁定事件的方法中傳入參數,須要將參數做爲屬性值,綁定到元素上的data-屬性上,而後在方法中,經過e.currentTarget.dataset.*的方式獲取,從而完成參數的傳遞,很麻煩有沒有...

<view class='tr' bindtap='toApprove' data-id="{{item.id}}"></view>
Page({
data:{
    reason:''
},
toApprove(e) {
    let id = e.currentTarget.dataset.id;
  }
})
clipboard.png

8、父子組件通訊

1.子組件的使用

在vue中,須要:

編寫子組件
在須要使用的父組件中經過import引入
在vue的components中註冊
在模板中使用
//子組件 bar.vue
<template>
  <div class="search-box">
    <div @click="say" :title="title" class="icon-dismiss"></div>
  </div>
</template>
<script>
export default{
props:{
    title:{
       type:String,
       default:''
      }
    }
},
methods:{
    say(){
       console.log('明天不上班');
       this.$emit('helloWorld')
    }
}
</script>

// 父組件 foo.vue
<template>
  <div class="container">
    <bar :title="title" @helloWorld="helloWorld"></bar>
  </div>
</template>

<script>
import Bar from './bar.vue'
export default{
data(){
    return{
        title:"我是標題"
    }
},
methods:{
    helloWorld(){
        console.log('我接收到子組件傳遞的事件了')
    }
},
components:{
    Bar
}
</script>
在小程序中,須要:

編寫子組件
在子組件的json文件中,將該文件聲明爲組件
{
  "component": true
}
在須要引入的父組件的json文件中,在usingComponents填寫引入組件的組件名以及路徑
"usingComponents": {
    "tab-bar": "../../components/tabBar/tabBar"
  }
在父組件中,直接引入便可
<tab-bar currentpage="index"></tab-bar>
具體代碼:
// 子組件
<!--components/tabBar/tabBar.wxml-->
<view class='tabbar-wrapper'>
  <view class='left-bar {{currentpage==="index"?"active":""}}' bindtap='jumpToIndex'>
    <text class='iconfont icon-shouye'></text>
    <view>首頁</view>
  </view>
  <view class='right-bar {{currentpage==="setting"?"active":""}}' bindtap='jumpToSetting'>
    <text class='iconfont icon-shezhi'></text>
    <view>設置</view>
  </view>
</view>
2.父子組件間通訊

在vue中

父組件向子組件傳遞數據,只須要在子組件經過v-bind傳入一個值,在子組件中,經過props接收,便可完成數據的傳遞,示例:

// 父組件 foo.vue
<template>
  <div class="container">
    <bar :title="title"></bar>
  </div>
</template>
<script>
import Bar from './bar.vue'
export default{
data(){
    return{        
        title:"我是標題"
    }
},
components:{
    Bar
}
</script>

// 子組件bar.vue
<template>
  <div class="search-box">
    <div :title="title" ></div>
  </div>
</template>
<script>
export default{
props:{
    title:{
       type:String,
       default:''
      }
    }
}
</script>
子組件和父組件通訊能夠經過this.$emit將方法和數據傳遞給父組件。

在小程序中

父組件向子組件通訊和vue相似,可是小程序沒有經過v-bind,而是直接將值賦值給一個變量,以下:

<tab-bar currentpage="index"></tab-bar>

此處, 「index」就是要向子組件傳遞的值
在子組件properties中,接收傳遞的值

properties: {
    // 彈窗標題
    currentpage: {            // 屬性名
      type: String,     // 類型(必填),目前接受的類型包括:String, Number, Boolean, Object, Array, null(表示任意類型)
      value: 'index'     // 屬性初始值(可選),若是未指定則會根據類型選擇一個
    }
  }
子組件向父組件通訊和vue也很相似,代碼以下:

//子組件中
methods: {   
    // 傳遞給父組件
    cancelBut: function (e) {
      var that = this;
      var myEventDetail = { pickerShow: false, type: 'cancel' } // detail對象,提供給事件監聽函數
      this.triggerEvent('myevent', myEventDetail) //myevent自定義名稱事件,父組件中使用
    },
}

//父組件中
<bar bind:myevent="toggleToast"></bar>

// 獲取子組件信息
toggleToast(e){
    console.log(e.detail)
}
若是父組件想要調用子組件的方法

vue會給子組件添加一個ref屬性,經過this.$refs.ref的值即可以獲取到該子組件,而後即可以調用子組件中的任意方法,例如:

//子組件
<bar ref="bar"></bar>

//父組件
this.$ref.bar.子組件的方法
小程序是給子組件添加id或者class,而後經過this.selectComponent找到子組件,而後再調用子組件的方法,示例:

//子組件
<bar id="bar"></bar>

// 父組件
this.selectComponent('#id').syaHello()
小程序父組件改變子組件樣式

1.父組件將style傳入子組件
2.父組件傳入變量控制子組件樣式
3.在父組件樣式中,在子組件類名前面加上父組件類名

<view class='share-button-container' bindtap='handleShareBtn'>
   <share-button  product="{{goodProduct}}" type="1" back-color="#fff" fore-color="#9e292f" bind:error="on_error" />
</view>

.share-button-container .button--btn-navigator__hover{
  background: #fff;
}
小程序和vue在這點上太類似了,有木有。。。

H5中viewport-fit作什麼用的?

https://www.cnblogs.com/sunsh...html

iPhone X 配備一個覆蓋整個手機的全面屏,頂部的「劉海」爲相機和其餘組件留出了空間。然而結果就是會出現一些尷尬的情景:網站被限制在一個「安全區域」,在兩側邊緣會出現白條兒。移除這個白條兒也不難,給 body 設置一個 background-color 就能夠搞定。或者,能夠添加 viewport-fit=cover meta 標籤,將整個網站擴展到整個屏幕。
`<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">`
圖0:iPhone X 的劉海和 CSS

而後就由你來決定被安全區域制約的重疊區了。有一些新的 CSS 能夠助你一臂之力。Stephen Radford 文檔:

爲了處理這些需求,iOS 11 的 Safari 引入了一些 constant 來處理 viewport-fit=cover 屬性。

safe-area-inset-top
safe-area-inset-right
safe-area-inset-left
safe-area-inset-bottom
這些值能夠應用到 margin、padding 上,也能夠應用到絕對定位的 top 或 left 上。

在網頁的 container 上添加以下代碼:

`padding: constant(safe-area-inset-top) constant(safe-area-inset-right) constant(safe-area-inset-bottom) constant(safe-area-inset-left);`

<span></span>綁定了click事件,嵌入ios app後點擊無效,如何解決?

1. 給須要綁定事件的元素添加一個css cursor: pointer ,事件依然用click事件。
.farmGoods{
    cursor:pointer;
 }

2. 第二種解決方案是將click事件替換爲touchstart事件,或者click事件與touchstart事件並存。
$(document).on("touchstart",".farmGoods",function(){
     alert('111');
 });

3. 換標籤

如下代碼輸出的結果:

  1. 答案:2
let s=new Set();
    s.add([1]);
    s.add([1]);
    console.log(s.size);
  1. 答案:undefined
let map=new Map();
    map.set([5],'測試問題');
    let con=map.get([5]);
    console.log(con);
  1. 答案:1 2 4 3
const promise=new Promise((resolve,reject)=>{
        console.log(1);
        resolve();
        console.log(2)
    });
    promise.then(()=>{
        console.log(3);
    });
    console.log(4);

原生js

媒體查詢實現響應式頁面的原理是什麼?

@media 是很是有用的。 當你重置瀏覽器大小的過程當中,頁面也會根據瀏覽器的寬度和高度從新渲染頁面,這對調試來講是一個極大的便利
媒體類型
all         用於全部設備
print       用於打印機和打印預覽
screen      用於電腦屏幕,平板電腦,智能手機等。(最經常使用)
speech      應用於屏幕閱讀器等發聲設備
媒體功能
max-width   定義輸出設備中的頁面最大可見區域寬度
min-width   定義輸出設備中的頁面最小可見區域寬度
實例
@media screen and (max-width: 300px) {//文檔寬度小於等於300px時body背景是亮藍色
    body {
        background-color:lightblue;
    }
}
@media screen and (min-width: 300px){//文檔寬度大於等於300px時body背景是亮藍色
    body {
        background-color:lightblue;
    }
}
@media screen and (min-width:300px) and (max-width:500px) {//文檔寬度大於等於300px小於等於500px時加載css代碼
    /* CSS 代碼 */
}

構建H5頁面須要考慮哪些因素?

1、內存的評估

其實內存的評估主要用於評估項目美術資源的使用程度,相比代碼和配置佔用的內存量,美術資源纔是大頭。這一步對於咱們程序來講很是重要,由於策劃不懂,設計爲了效果不會去考慮美術量是否過大。可是再咱們沒有經歷過完整項目以前,咱們怎麼知道要作一個怎樣的限制呢?很簡單,咱們只須要去看看市面上當紅H5產品,F12看看他的美術資源,地圖有多少格,每張多大,人物動畫,技能特效等等資源有多大!基本上就能夠換算出大概的內存佔用量。而後再用較爲低端的手機跑一跑,看看是否有瀏覽器崩潰的狀況。由於崩潰每每是內存爆了!一句話總結 內存的評估主要是告訴策劃和美術,咱們的地圖最大能多大,咱們的人物動做幾個合適幾幀合適,ui資源得多複用多9宮格!由於這些決定了你的遊戲能在多低端的手機上成功運行!

2、drawcall的評估

這一指標影響了渲染性能,直接影響你的遊戲卡不卡,固然前提是你的代碼邏輯沒什麼坑本身的地方!簡單的評估一樣能夠參考市面上的當紅產品,看看他們最多同屏多少個角色,多少個特效,UI面板的多少。雖然cacheAsBitmap能夠減小drawcall,可是那也是用內存來換的性能,意味着若是使用不合理又會對內存帶來壓力。因此遊戲中同屏對象的數量限制你也須要實踐來進行評測。一句話總結 drawcall的評估,主要是爲了在低端機上也能流暢的運行,告訴策劃咱們能不能多武將多美人,怪物能不能一堆一堆的出現,地圖塊多大尺寸合適!這些決定了你的遊戲能在多低端的手機上不卡頓!

3、引擎的選擇

目前市面上最流行的H5引擎就是egret和layabox了,傳說中layabox的性能要優於egret,因爲egret的工具更加完善一點,因此當初選擇了egret。可是發現開發過程當中,爲了方便項目的使用。序列幀動畫生成工具,地圖編輯器等等工具都是本身開發的。因此說雖然egret工具不少,可是發現對於本身來講使用價值不大。建議你們以引擎穩定性和性能爲主要考慮條件。最簡單的性能評估,就是使用兩個引擎跑一樣的demo看各個數據。這個demo主要用於評估引擎的渲染性能和執行性能,好比drawcall極限測試,cacheAsBitmap極限測試,資源加載效率測試等等。 畢竟引擎幫咱們作的最多的其實就是渲染和資源加載這一塊。一句話總結 性能的重要性要大於工具是否使用方便,由於方便的工具每每是本身根據項目定製開發!引擎的選擇絕對不是看幾篇別人的廣告帖子貼出來的參數就決定了,必須本身去實踐對比!

jsonp的原理是什麼?如何判斷後臺返回的是json仍是jsonp?

一、一個衆所周知的問題,Ajax直接請求普通文件存在跨域無權限訪問的問題,甭管你是靜態頁面、動態網頁、web服務、WCF,只要是跨域請求,一概不許;

二、不過咱們又發現,Web頁面上調用js文件時則不受是否跨域的影響(不只如此,咱們還發現凡是擁有"src"這個屬性的標籤都擁有跨域的能力,好比<script>、<img>、<iframe>);

三、因而能夠判斷,當前階段若是想經過純web端(ActiveX控件、服務端代理、屬於將來的HTML5之Websocket等方式不算)跨域訪問數據就只有一種可能,那就是在遠程服務器上設法把數據裝進js格式的文件裏,供客戶端調用和進一步處理;

四、恰巧咱們已經知道有一種叫作JSON的純字符數據格式能夠簡潔的描述複雜數據,更妙的是JSON還被js原生支持,因此在客戶端幾乎能夠爲所欲爲的處理這種格式的數據;

五、這樣子解決方案就呼之欲出了,web客戶端經過與調用腳本如出一轍的方式,來調用跨域服務器上動態生成的js格式文件(通常以JSON爲後綴),顯而易見,服務器之因此要動態生成JSON文件,目的就在於把客戶端須要的數據裝入進去。

六、客戶端在對JSON文件調用成功以後,也就得到了本身所需的數據,剩下的就是按照本身需求進行處理和展示了,這種獲取遠程數據的方式看起來很是像AJAX,但其實並不同。

七、爲了便於客戶端使用數據,逐漸造成了一種非正式傳輸協議,人們把它稱做JSONP,該協議的一個要點就是容許用戶傳遞一個callback參數給服務端,而後服務端返回數據時會將這個callback參數做爲函數名來包裹住JSON數據,這樣客戶端就能夠隨意定製本身的函數來自動處理返回數據了。

八、ajax 的核心是經過 XmlHttpRequest 獲取非本頁內容,而 jsonp 的核心則是動態添加 <script> 標籤來調用服務器提供的 js 腳本。

九、jsonp是一種方式或者說非強制性協議,如同ajax同樣,它也不必定非要用json格式來傳遞數據,若是你願意,字符串都行,只不過這樣不利於用jsonp提供公開服務。

https://www.jianshu.com/p/f46...vue

判斷有沒有callback參數,其實json和jsonp本質上都是字符串,只是jsonp是外層包裹了一層函數。

json

下面是jquery的ajax請求,數據類型爲json,它是以json格式在先後臺進行數據的傳輸,它與侷限性就是不能跨域請求,這是爲了網絡數據的安全所制定的規則。

$.ajax({
            type: "post", // 數據提交類型
            url: "danmu.php",// 請求地址 同源服務器/瀏覽器安全設置
            data: {word:"abc",username:"ltt"}, // 發送數據
            dataType: "json", // 返回數據的類型
            async: true, // 是否異步,true爲異步
            // success爲數據加載完成後的回調函數
            success: function(data){
                var show = document.getElementById('show');
                for(i in data){
                    show.innerHTML += data[i]+"<br>";
                }
                console.log(data);
            }       
        });
這是後臺部分,首先判斷前臺是否請求數據,若是請求了,就將前臺須要的數據返回給前臺。
注意:返回給前臺的數據必定要轉成json格式的,經過json_encode將數組轉換成json格式

<?php
    if(!empty($_POST['word'])){
        $arr = [];
        $word = htmlspecialchars($_POST['word']);
        $username = htmlspecialchars($_POST['username']);
        $arr[] = $word;
        $arr[] = $username;
        $fp = fopen("danmu.txt","a+");
        fwrite($fp,$word."\n");
        fclose($fp);
        echo json_encode(array($word));
    }
?>
因爲json不能跨域請求,因而就有了jsonp

jsonp

你們都知道script標籤是能夠跨域請求的,jsonp的原理就是經過script的src,將函數做爲src請求地址的參數來傳遞數據,因此jsonp只有get一種傳輸方式。
下面是jsonp的數據交互,首先定義一個回調函數,定義dataType類型爲jsonp,將函數做爲參數傳輸給後臺,它與json相比是多了一層函數。

<script type="text/javascript">
        // 自定義的回調函數
        function show(val){
            document.getElementById("show").src=val[0].src;
        }
        $.ajax({
            type:"get",
            url:"myphp.php",
            dataType:"jsonp", // 如今時jsonp請求,這個時候,jquery使用的是script標籤發送請求
            jsonp:"callmyphp", // 後臺用來接受函數名的變量名
            jsonpCallback:"show",// 自定義的回調函數名
            async:true,
        });
至於何時用json何時用jsonp?我就一個原則,能使用json的時候都是用json,只有必需要跨域請求時才使用jsonp

如何兼容css?

https://www.jianshu.com/p/a6f...java

一、CSS Hack

咱們爲了讓頁面造成統一的效果,要針對不一樣的瀏覽器/版本而寫css的過程就叫作CSS hack
(1)IE條件註釋法

即在正常代碼以外添加判別IE瀏覽器或對應版本的條件註釋,符合條件的瀏覽器或者版本號纔會執行裏面的代碼。

<!--格式-->
<!--lt是小於   gt是大於    lte是小於等於    gte是不小於   !是不等於-->

<!--[if IE]>
    你想要執行的代碼
<![endif]-->

<!--[if lt IE8]>
    你想要執行的代碼
<![endif]-->

<!--[if ! IE 8]>
    你想要執行的代碼
<![endif]-->
<!--示例1-->
<!--[if lte IE 8]>
<link rel="stylesheet" type="text/css" href="base.css"/>
<![endif]-->

1.png


2.png
(2)CSS屬性前綴法

即給css的屬性添加前綴,好比*能夠被IE6/IE7識別,但_只能被IE6識別,IE6-IE10均可以識別"\9",IE6不能識別!important ,Firefox不能識別 * _ \9

說明:

在標準模式中

"-" 減號是IE6專有的hack

"\9" IE6-IE10 都生效

"\0" IE8-IE10 都生效,是IE8-IE10的hack

"\9\0" 只對IE9-IE10 生效

<!--示例2-->
        <style>
            h1{
                color: #FF0000;     /* all */
                color: #222\9;   /* IE */
                *color: #333;    /* IE6/IE7 */
                _color:#444;     /* IE6 */
            }
        </style>

3.png


4.png


5.png


6.png

IEtester:http://www.ietester.cn/ 測試兼容的
(3)選擇器前綴法

IE6 可識別 *div{color:red}

IE7 可識別 *+{color:red}

@media screen \9{...} 只對IE6/IE7生效

@media \0screen {body {background:blue}} 只對IE6/7/8有效

。。。。。

<!--示例3-->
        <style>
            *h2{
                color:orange;
            }
        </style>
二、瀏覽器私有屬性

-moz 表明Firefox瀏覽器私有屬性
-ms 表明IE瀏覽器私有屬性
-webkit 表明chrome、Safari私有屬性
-o 表明Opera私有屬性
注意:對於私有屬性,要把標準寫法放到最後,兼容性寫法放到前面

咱們常常會在某個CSS的屬性前添加一些前綴,好比:-webkit-,-moz-,-ms-,這些就是瀏覽器的私有屬性。

爲何會出現私有屬性呢?這是由於制定HTML和CSS標準的組織w3c動做是很慢的。

一般,有W3C組織成員提出一個新屬性,好比說圓角border-radius,你們都以爲很好,但w3c制定標準,要走很複雜的程序、審查等,而瀏覽器市場推廣時間緊,若是一個屬性已經夠成熟了,就會在瀏覽器中加入支持。
可是爲避免往後w3c公佈標準時有所變動,會加入一個私有前綴,好比 -webkit- border-radius,經過這種方式來提早支持新屬性,等到往後w3c公佈了標準,border-radius的標準寫法確立以後,再讓新版的瀏覽器支持border-radius這種寫法。
<!--示例4-->
.box{
                width: 300px;
                height: 300px;
                -webkit-border-radius: 150px;
                -moz-border-radius: 150px;
                -ms-border-radius:150px;
                -o-border-radius: 150px;
                border-radius: 150px;
                background-color: royalblue;
            }
三、瀏覽器CSS樣式初始化

針對不一樣瀏覽器渲染效果的不一樣,能夠進行瀏覽器css樣式初始化,也就是加一個reset.css文件

/*淘寶的reset.css*/
blockquote,body,button,dd,dl,dt,fieldset,form,h1,h2,h3,h4,h5,h6,hr,input,legend,li,ol,p,pre,td,textarea,th,ul {margin:0;padding:0}
body,button,input,select,textarea { font:12px/1.5 tahoma,arial,'Hiragino Sans GB',\5b8b\4f53,sans-serif}
h1,h2,h3,h4,h5,h6 {font-size:100%}
address,cite,dfn,em,var {font-style:normal}
code,kbd,pre,samp {font-family:courier new,courier,monospace}
small {font-size:12px}
ol,ul {list-style:none}
a {text-decoration:none}
a:hover {text-decoration:underline}
sup {vertical-align:text-top}
sub {vertical-align:text-bottom}
legend {color:#000}
fieldset,img {border:0}
button,input,select,textarea {font-size:100%}
table {border-collapse:collapse;border-spacing:0}
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息