如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里
最近在對《React Native移動開發實戰》一書進行部分修訂和升級。在React Native開發中,免不了會涉及到原生代碼與JS層的消息傳遞等問題,那么React Native究竟是如何實現與原生的互相操作的呢?
原生給JS傳值,主要依靠屬性,也就是通過initialProperties,這個RCTRootView的初始化函數的參數來完成。通過RCTRootView的初始化函數你可以將任意屬性傳遞給React Native應用,參數initialProperties必須是NSDictionary的一個實例。RCTRootView有一個appProperties屬性,修改這個屬性,JS端會調用相應的渲染方法。
使用RCTRootView將React Natvie視圖封裝到原生組件中。RCTRootView是一個UIView容器,承載著React Native應用。同時它也提供了一個聯通原生端和被托管端的接口。
例如有下面一段OC代碼:
下面是JS層的處理:
不管OC中關于initialProperties的名字叫什么,在JS中都是this.props開頭,然后接下來才是key名字。
RCTRootView同樣提供了一個可讀寫的屬性appProperties。在appProperties設置之后,React Native應用將會根據新的屬性重新渲染。當然,只有在新屬性和舊的屬性有更改時更新才會被觸發。
可以隨時更新屬性,但是更新必須在主線程中進行,讀取則可以在任何線程中進行。
.h的文件代碼:
.m的文件代碼:
為了實現RCTBridgeModule協議,你的類需要包含RCT_EXPORT_MODULE()宏。這個宏也可以添加一個參數用來指定在Javascript中訪問這個模塊的名字。如果你不指定,默認就會使用這個Objective-C類的名字。
并且必須明確的聲明要給Javascript導出的方法,否則React Native不會導出任何方法。OC中聲明要給Javascript導出的方法,通過RCT_EXPORT_METHOD()宏來實現。
要用到NativeModules則要引入相應的命名空間import { NativeModules } from ‘react-native’;然后再進行調用CalendarManager.doSomething(‘sdfsdf’,’sdfsdfs’);橋接到Javascript的方法返回值類型必須是void。React Native的橋接操作是異步的,所以要返回結果給Javascript,你必須通過回調或者觸發事件來進行。
說明:第一個參數代表從JavaScript傳過來的數據,第二個參數是回調方法;
RCT_EXPORT_METHOD 支持所有標準JSON類型,包括:
除此以外,任何RCTConvert類支持的的類型也都可以使用(參見RCTConvert了解更多信息)。RCTConvert還提供了一系列輔助函數,用來接收一個JSON值并轉換到原生Objective-C類型或類。例如:
如果需要從iOS原生方法發送數據到JavaScript中,那么使用eventDispatcher。例如:
在JavaScript中可以這樣訂閱事件,通常需要在componentWillUnmount函數中取消事件的訂閱。
用NativeAppEventEmitter.addListener中注冊一個通知,之后再OC中通過bridge.eventDispatcher sendAppEventWithName發送一個通知,這樣就形成了調用關系。
原生給React Native傳參
原生給React Native傳值
NSURL *jsCodeLocation;
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil]; NSArray *imageList = @[@"http://foo.com/bar1.png",
@"http://foo.com/bar2.png"]; NSDictionary *wjyprops = @{@"images" : imageList};
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"ReactNativeProject" initialProperties:wjyprops
launchOptions:launchOptions];
import React, { Component } from 'react'; import {
AppRegistry,
View,
Image,
} from 'react-native'; class ImageBrowserApp extends Component { renderImage(imgURI) { return (
<Image source={{uri: imgURI}} />
);
}
render() { return (
<View>
{this.props.images.map(this.renderImage)}
</View>
);
}
}
AppRegistry.registerComponent('ImageBrowserApp', () => ImageBrowserApp);
{"rootTag":1,"initialProps":{"images":["http://foo.com/bar1.png","http://foo.com/bar2.png"]}}.
使用appProperties進行參數傳遞
NSArray *imageList = @[@"http://foo.com/bar3.png", @"http://foo.com/bar4.png"]; rootView.appProperties = @{@"images" : imageList};
React Native執行原生方法及回調
React Native執行原生方法
#import <Foundation/Foundation.h> #import <RCTBridgeModule.h> @interface wjyTestManager : NSObject<RCTBridgeModule> @end
#import "wjyTestManager.h" @implementation wjyTestManager RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(doSomething:(NSString *)aString withA:(NSString *)a)
{ NSLog(@"%@,%@",aString,a);
} @end
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Alert,
TouchableHighlight,
} from 'react-native';
import {
NativeModules,
NativeAppEventEmitter
} from 'react-native'; var CalendarManager = NativeModules.wjyTestManager; class ReactNativeProject extends Component { render() { return (
<TouchableHighlight onPress={()=>CalendarManager.doSomething('sdfsdf','sdfsdfs')}>
<Text style={styles.text}
>點擊 </Text>
</TouchableHighlight>
);
}
} const styles = StyleSheet.create({
text: {
flex: 1,
marginTop: 55,
fontWeight: 'bold' },
});
AppRegistry.registerComponent('ReactNativeProject', () => ReactNativeProject);
傳參并回調
RCT_EXPORT_METHOD(testCallbackEvent:(NSDictionary *)dictionary callback:(RCTResponseSenderBlock)callback)
{ NSLog(@"當前名字為:%@",dictionary); NSArray *events=@[@"callback ", @"test ", @" array"];
callback(@[[NSNull null],events]);
}
JS層代碼:
import {
NativeModules,
NativeAppEventEmitter
} from 'react-native'; var CalendarManager = NativeModules.wjyTestManager; class ReactNativeProject extends Component { render() { return (
<TouchableHighlight onPress={()=>{CalendarManager.testCallbackEvent(
{'name':'good','description':'http://www.lcode.org'},
(error,events)=>{ if(error){
console.error(error);
}else{
this.setState({events:events});
}
})}}
>
<Text style={styles.text}
>點擊 </Text>
</TouchableHighlight>
);
}
}
參數類型說明
#import "RCTConvert.h" #import "RCTBridge.h" #import "RCTEventDispatcher.h" // 對外提供調用方法,為了演示事件傳入屬性字段 RCT_EXPORT_METHOD(testDictionaryEvent:(NSString *)name details:(NSDictionary *) dictionary)
{ NSString *location = [RCTConvert NSString:dictionary[@"thing"]]; NSDate *time = [RCTConvert NSDate:dictionary[@"time"]]; NSString *description=[RCTConvert NSString:dictionary[@"description"]]; NSString *info = [NSString stringWithFormat:@"Test: %@\nFor: %@\nTestTime: %@\nDescription: %@",name,location,time,description]; NSLog(@"%@", info);
}
iOS原生訪問React Native
#import "RCTBridge.h" #import "RCTEventDispatcher.h" @implementation CalendarManager @synthesize bridge = _bridge; // 進行設置發送事件通知給JavaScript端 - (void)calendarEventReminderReceived:(NSNotification *)notification
{ NSString *name = [notification userInfo][@"name"];
[self.bridge.eventDispatcher sendAppEventWithName:@"EventReminder" body:@{@"name": name}];
} @end
import { NativeAppEventEmitter } from 'react-native';
var subscription = NativeAppEventEmitter.addListener( 'EventReminder',
(reminder) => console.log(reminder.name)
); ... // 千萬不要忘記忘記取消訂閱, 通常在componentWillUnmount函數中實現。
subscription.remove();
如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里
js中構造函數的幾種繼承模式淺析
一、原型鏈模式繼承
利用原型讓一個引用類型繼承另一個引用類型的屬性和方法 。
用的最多。
缺點:不可傳參,不可多繼承。
-
function People(name, age) {//添加公有屬性
-
name = name || 'xiaolan';
-
age = age || 18;
-
this.name = name;
-
this.age = age;
-
}//創建一個名為People的類
-
People.prototype.eat = function() {//添加私有屬性
-
console.log(this.name + '賊能吃');
-
}
-
function Cat(color) {//創建一個名為Cat的類
-
this.color = color;
-
}
-
Cat.prototype = new People('小叮當', 200);//實例化一個People類,并賦值給Cat類的原型鏈
-
var cat = new Cat('藍白色')
-
console.log(cat.name)//'小叮當'
-
cat.eat();//'小叮當賊能吃'
二、混合模式繼承
用call的方法只能繼承私有屬性,所以再加一遍一遍原型鏈模式繼承,原型鏈模式繼承又把私有屬性和公有屬性都繼承了一遍。
-
function People(name, age) { //創建一個父級People類
-
name = name || 'xiaolan';
-
age = age || 18;
-
this.name = name;
-
this.age = age;
-
}
-
People.prototype.eat = function() {
-
console.log(this.name + '賊能吃');
-
}
-
-
function Cat(color, name, age) {
-
this.color = color;
-
People.call(this, name, age); //通過call的形式繼承
-
//通過call(this),將People的指向改為Cat的實例
-
}
-
var cat = new Cat('藍白色', '小叮當', 1);
-
console.log(cat.name);//'小叮當'
-
cat.eat();//報錯,
-
//繼承不了公有屬性,所以cat.eat()會報錯;
為了繼承公有屬性,用原型鏈模式在把公有屬性和方法繼承過來,
-
function People(name, age) { //創建一個父級People類
-
name = name || 'xiaolan';
-
age = age || 18;
-
this.name = name;
-
this.age = age;
-
}
-
People.prototype.eat = function() {
-
console.log(this.name + '賊能吃');
-
}
-
-
function Cat(color, name, age) {
-
this.color = color;
-
People.call(this, name, age); //通過call的形式繼承
-
//通過call(this),將People的指向改為Cat的實例
-
}
-
Cat.prototype = new People()
-
var cat = new Cat('藍白色', '小叮當', 200)
-
console.log(cat)
-
console.log(cat.name); //'小叮當',在原型鏈繼承的時候,就近原則,cat.name 先找到'小叮當',就不往下找了
-
cat.eat(); //'小叮當賊能吃'
三、拷貝繼承
優點:可以多繼承,可傳參;
缺點:浪費資源,不能判斷父級;
-
function People(name, age) { //創建一個父級People類
-
name = name || 'xiaolan';
-
age = age || 18;
-
this.name = name;
-
this.age = age;
-
}
-
People.prototype.eat = function() {
-
console.log(this.name + '賊能吃');
-
}
-
-
function Cat(color, name, age) {
-
this.color = color;
-
var people = new People(name, age) //實例化一個People類
-
for (let i in people) {
-
this[i] = people[i]; //將people中的可枚舉屬性和方法遍歷并附給Cat類,公有屬性和私有屬性都是可枚舉屬性;
-
}
-
}
-
var cat = new Cat('藍白色', '小叮當', 2);
-
console.log(cat.name); //小叮當
-
cat.eat(); //小叮當賊能吃
四、寄生組合方式繼承
優點:私有屬性和公有屬性都單獨繼承,可以傳參;
私有屬性可以多繼承,公有屬性不可多繼承;
-
function People(name, age) {
-
name = name || 'xiaolan';
-
age = age || 18;
-
this.name = name;
-
this.age = age;
-
}
-
People.prototype.eat = function() {
-
console.log(this.name + '賊能吃');
-
}
-
-
function Cat(color, name, age) {
-
this.color = color;
-
People.call(this, name, age) //用call的形式把私有屬性繼承過來
-
}
-
-
function Fn() {} //創建一個中間構造函數,用來接收People的公有屬性,為了防止創建實例Cat實例是影響原來的people構造函數
-
Fn.prototype = People.prototype;
-
Cat.prototype = new Fn(); //將中間構造函數Fn繼承people的公有屬性傳給Cat的原型鏈
-
Cat.prototype.constructor = Cat; //由于上一步重置了Cat原型鏈的constructor屬性,所以要重新給賦回來;
-
var cat = new Cat('藍白色', '小叮當', 3);
-
console.log(cat.name); //'小叮當'
-
cat.eat() //'小叮當賊能吃
注:若有不嚴謹與錯誤的地方,請多指教!
藍藍設計( www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務
如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里
問題總結 https://github.com/vuejs-templates/webpack/issues/260
首先npm install --save babel-polyfill
然后在main.js
中的最前面引入babel-polyfill
import 'babel-polyfill'
在index.html 加入以下代碼(非必須)
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
在config中的webpack.base.conf.js
中,修改編譯配置
-
entry:{
-
app:['babel-polyfill','./src/main.js']
-
}
當然,如果你只用到了 axios
對 promise
進行兼容,可以只用 es6-promise
npm install es6-promise --save
在 main.js
中的最前面 引入
import 'es6-promise/auto'
那么,就有一個問題了,build之后的dist文件只有放在服務器上才能查看,但本地如何查看呢,參考一下配置
修改config文件夾中的index.js文件,將build對象中的打包路徑,'/
‘改為'./'
,由絕對路徑改為相對路徑,建議將sourceMap
改為false
,編譯的時候會快一點
build: { assetsPublicPath: './', productionSourceMap: false, },
修改完之后,重新 npm run build ,得到新的dist文件夾
然后進入dist文件夾
cd dist
全局安裝簡易node服務器
npm install http-server -g
啟動簡易node服務器
http-server
出現如下圖所示,就代表你的服務器啟動成功了,那你也能在5000端口查看編譯打包后的項目了,可以在ie瀏覽器中直接測試了
IE在處理日期的時候,不支持-支持/的日期方式 如 2017-01-01應該
藍藍設計( www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務
如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里
Promise 是異步編程的一種解決方案,比傳統的解決方案–回調函數和事件--更合理和更強大。它由社區最早提出和實現,ES6將其寫進了語言標準,統一了語法,原生提供了Promise
所謂Promise ,簡單說就是一個容器,里面保存著某個未來才回結束的事件(通常是一個異步操作)的結果。從語法上說,Promise是一個對象,從它可以獲取異步操作的消息。
三種狀態:
狀態改變:
這兩種情況只要發生,狀態就凝固了,不會再變了,這時就稱為resolved(已定型
基本用法
ES6規定,Promise對象是一個構造函數,用來生成Promise實例
Promise的源碼分析:
曾幾何時,我們的代碼是這樣的,為了拿到回調的結果,不得不
終于,我們的
首先我們要知道自己手寫一個
我們先聲明一個類,叫做
那么接下來我會分析上面代碼的作用,原理
then方法是
這里主要做了將構造器中resolve和reject的結果傳入
之前我們只是處理了同步情況下的Promise,簡而言之所有操作都沒有異步的成分在內。那么如果是異步該怎么辦?
最早處理異步的方法就是callback,就相當于我讓你幫我掃地,我會在給你發起任務時給你一個手機,之后我做自己的事情去,不用等你,等你掃完地就會打手機給我,誒,我就知道了地掃完了。這個手機就是callback,回調函數。
首先我們需要改一下構造器里的代碼,分別添加兩個回調函數的數組,分別對應成功回調和失敗回調。他們的作用是當成功執行resolve或reject時,執行callback。
然后是then需要多加一個狀態判斷,當Promise中是異步操作時,需要在我們之前定義的回調函數數組中添加一個回調函數。
ok!大功告成,異步已經解決了
這也是
一下子多了很多方法,不用怕,我會一一解釋
那就讓我們來看看這個
它的作用是用來將onFufilled的返回值進行判斷取值處理,把最后獲得的值放入最外面那層的
我們現在已經基本完成了Promise的then方法,那么現在我們需要看看他的其他方法。
相信大家都知道catch這個方法是用來捕獲Promise中的reject的值,也就是相當于then方法中的onRejected回調函數,那么問題就解決了。我們來看代碼。
該方法是掛在Promise原型上的方法。當我們調用catch傳callback的時候,就相當于是調用了then方法。
大家一定都看到過
這兩個方法是直接可以通過class調用的,原理就是返回一個內部是resolve或reject的Promise對象。
all方法可以說是Promise中很常用的方法了,它的作用就是將一個數組的Promise對象放在其中,當全部resolve的時候就會執行then方法,當有一個reject的時候就會執行catch,并且他們的結果也是按著數組中的順序來排放的,那么我們來實現一下。
其原理就是將參數中的數組取出遍歷,每當執行成功都會執行
race方法雖然不常用,但是在Promise方法中也是一個能用得上的方法,它的作用是將一個
原理大家應該看懂了,很簡單,就是遍歷數組執行Promise,如果有一個
語法糖這三個字大家一定很熟悉,作為一個很Swag的前端工程師,對async/await這對兄弟肯定很熟悉,沒錯他們就是generator的語法糖。而我們這里要講的語法糖是Promise的。
什么作用呢?看下面代碼你就知道了
沒錯,我們可以方便的去調用他語法糖defer中的
Promise 的含義
Promise 對象的狀態不受外界影響
Promise對象的狀態改變,只有兩種可能:
resolve
函數的作用是,將Promise對象的狀態從“未完成”變為“成功”(即從 pending
變為 resolved
),在異步操作成功時調用,并將異步操作的結果,作為參數傳遞出去;
reject
函數的作用是,將Promise對象的狀態從“未完成”變為“失敗”(即從 pending
變為 rejected
),在異步操作失敗時調用,并將異步操作報出的錯誤,作為參數傳遞出去。
1.回調地獄
callback hell
,這種環環相扣的代碼可以說是相當惡心了
蓋世英雄
出現了,他身披金甲圣衣、駕著七彩祥云。好吧打岔兒了,沒錯他就是我們的Promise
,那讓我們來看看用了Promise
之后,上面的代碼會變成什么樣吧
2.重點開始,小眼睛都看過來
2.1 Promise/A+
Promise
,應該怎么去寫,誰來告訴我們怎么寫,需要遵循什么樣的規則。當然這些你都不用擔心,其實業界都是通過一個規則指標來生產Promise
的。讓我們來看看是什么東西。傳送門?Promise/A+
2.2 constructor
Promise
,里面是構造函數。如果es6還有問題的可以去阮大大的博客上學習一下(傳送門?es6)
executor:
這是實例Promise
對象時在構造器中傳入的參數,一般是一個function(resolve,reject){}
status:``Promise
的狀態,一開始是默認的pendding狀態,每當調用道resolve和reject方法時,就會改變其值,在后面的then方法中會用到
value:
resolve回調成功后,調用resolve方法里面的參數值
reason:
reject回調成功后,調用reject方法里面的參數值
resolve:
聲明resolve方法在構造器內,通過傳入的executor方法傳入其中,用以給使用者回調
reject:
聲明reject方法在構造器內,通過傳入的executor方法傳入其中,用以給使用者回調
2.3 then
Promise
中最為重要的方法,他的用法大家都應該已經知道,就是將Promise
中的resolve或者reject的結果拿到,那么我們就能知道這里的then方法需要兩個參數,成功回調和失敗回調,上代碼!
onFufilled
和onRejected
中,注意這兩個是使用者傳入的參數,是個方法。所以你以為這么簡單就完了?要想更Swag
的應對各種場景,我們必須得再完善。繼續往下走!
3.異步的Promise
3.1 callback?。。。?
3.2 resolvePromise
Promise
中的重頭戲,我來介紹一下,我們在用Promise的時候可能會發現,當then函數中return了一個值,我們可以繼續then下去,不過是什么值,都能在下一個then中獲取,還有,當我們不在then中放入參數,例:promise.then().then()
,那么其后面的then依舊可以得到之前then返回的值,可能你現在想很迷惑。讓我來解開你心中的憂愁,follow me。
Promise
?:首先我們要注意的一點是,then有返回值,then了之后還能在then,那就說明之前的then返回的必然是個Promise
。
setTimeout
?:因為Promise本身是一個異步方法,屬于微任務一列,必須得在執行棧執行完了在去取他的值,所以所有的返回值都得包一層異步setTimeout。
resolvePromise
是什么?:這其實是官方Promise/A+的需求。因為你的then可以返回任何職,當然包括Promise
對象,而如果是Promise
對象,我們就需要將他拆解,直到它不是一個Promise
對象,取其中的值。
resolvePromise
到底長啥樣。
Promise
的resolve函數中。
promise2
(then函數返回的Promise對象),x
(onFufilled函數的返回值),resolve、reject
(最外層的Promise上的resolve和reject)。
promise2
和x
?:首先在Promise/A+中寫了需要判斷這兩者如果相等,需要拋出異常,我就來解釋一下為什么,如果這兩者相等,我們可以看下下面的例子,第一次p2是p1.then出來的結果是個Promise
對象,這個Promise
對象在被創建的時候調用了resolvePromise(promise2,x,resolve,reject)函數,又因為x等于其本身,是個Promise
,就需要then方法遞歸它,直到他不是Promise
對象,但是x(p2)的結果還在等待,他卻想執行自己的then方法,就會導致等待。
resolvePromise
函數已經resolve或者reject了,那就不需要在執行下面的resolce或者reject。
resolvePromise
函數?:相信細心的人已經發現了,我這里使用了遞歸調用法,首先這是Promise/A+中要求的,其次是業務場景的需求,當我們碰到那種Promise的resolve里的Promise的resolve里又包了一個Promise的話,就需要遞歸取值,直到x不是Promise對象。
4.完善Promise
4.1 catch
4.2 resolve/reject
Promise.resolve()、Promise.reject()
這兩種用法,它們的作用其實就是返回一個Promise對象,我們來實現一下。
4.3 all
processData
方法,processData
方法就是用來記錄每個Promise的值和它對應的下標,當執行的次數等于數組長度時就會執行resolve,把arr的值給then。這里會有一個坑,如果你是通過arr數組的長度來判斷他是否應該resolve的話就會出錯,為什么呢?因為js數組的特性,導致如果先出來的是1位置上的值進arr,那么0位置上也會多一個空的值,所以不合理。
4.4 race
Promise
數組放入race中,哪個先執行完,race就直接執行完,并從then中取值。我們來實現一下吧。
Promise
執行成功就resolve。
Promise語法糖 deferred
Promise
對象。那么它還有沒有另外的方法呢?答案是有的。我們需要在全局上安裝promises-aplus-tests插件npm i promises-aplus-tests -g
,再輸入promises-aplus-tests [js文件名] 即可驗證你的Promise的規范。
藍藍設計( www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務
如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里
通常當用戶打開一個資源的
對于壓縮格式的文件(
對于瀏覽器這種行為,一般情況下是可以接受的,因為用戶可以在瀏覽器顯示文件后將文件保存到電腦中,但是一些情況下用戶可能希望文件直接被下載而不是在瀏覽器中被打開,比如有時候用戶想去下載一個歌曲,但是瀏覽器可能回去播放該音頻。那么怎么讓瀏覽器強制去下載文件要怎么做呢
瀏覽器會根據資源類型去判斷是否支持,如果支持時會嘗試去在頁面上展示該資源。瀏覽器判斷資源類型是根據返回頭
在HTTP場景中,
因此當我們希望該資源被直接下載時候,我們可以設置返回頭
這里設置名稱時候,要注意下
瀏覽器既然定義了該行為,根據瀏覽器的不同用戶可能在設置頁面去配置某些格式的文件是否希望瀏覽器去展示該文件。一些有爭議的情況下,你也可以提示用戶自己根據需求去設置這些參數。
url
,如果瀏覽器支持這個格式的文件的情況下,瀏覽器會嘗試去再頁面里展示它而不是直接下載。例如一張圖片(jpg, png, gif等
),幾乎所有瀏覽器都會去將圖片在瀏覽器里面展示。
zip, tar, gzip等
)瀏覽器總是會直接去下載它們,另外一些格式的文件,根據瀏覽器的不同也會有差異的處理方法,例如Microsoft Word
文件(doc, docx
)在ie
瀏覽器下通常會在瀏覽器中展示,但是其他瀏覽器幾乎都會直接下載它,同樣的對于PDF
文件chrome
有自己的pdf 轉換器
它會嘗試去在瀏覽器上展示該文件。
強制下載文件
a標簽的download屬性
html5
中 a
標簽新增了 download
屬性,該屬性指示瀏覽器下載url
的內容而不是導航到url
,因此如果配置了此屬性用戶會直接下載url
的內容。作為開發如果想直接觸發該事件我們可以直接用代碼模擬a標簽和點擊事件
download
屬性只在同域時候有效,當跨域請求時候該屬性將會被忽略。
改變資源格式
Content-Type
的值,因此一方面我們在服務端可以設置返回頭字段為文件流'Content-Type': 'application/octet-stream'
,或者根據一些具體資源直接壓縮后傳輸,瀏覽器不能分析zip
之類的壓縮文件所以會直接去下載它們。
配置Content-Disposition
Content-Disposition
消息頭指示回復的內容該以何種形式展示,是以內聯的形式(即網頁或者頁面的一部分),還是以附件的形式下載并保存到本地。
inline
默認參數表示消息體會以頁面的一部分或者整個頁面的形式展示。
attachment
消息體應該被下載到本地,將參數filename
的值預填為下載后的文件名
Content-Disposition
的值為attachment
。
filename
的編碼格式。
用戶自己在瀏覽器設置
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
藍藍設計( www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務
如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里
今天來看看怎么實現炫酷的打字機效果。即把一段話一個字一個字的顯示出來。
效果圖:
實現思路:
首先規定好顯示字數的速度即settimeout執行間隔用來控制每個字之間輸出速度。再把判斷段落的總字數,循環段落總字數來實現一個字一個字的輸出。
js代碼:
藍藍設計( www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務
如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里
1.什么是DOM
4.訪問元素的方法
8.更多討論
問題1:getElementsByClassName() 使用時需要注意的地方
回答:它取出來的是個數組,及時只有一個那也是數組對象,所以改變指定元素時需使用角標
問題2:innerHTML 和innerText的區別
回答:innerText替換是會將標簽替換成字符串,而innerHTML 則會保留標簽插入到節點當中
問題3:dom事件
回答:事件是文檔或者瀏覽器窗口中發生的,特定的交互瞬間。事件是用戶或瀏覽器自身執行的某種動作,如click,load和mouseover都是事件的名字。事件是javaScript和DOM之間交互的橋梁。
事件發生,調用它的處理函數執行相應的JavaScript代碼給出響應。
DOM是中立于平臺和語言的接口,它允許程序和腳本動態地訪問和更新文檔的內容、結構和樣式。
在 HTML DOM中,所有事物都是節點。DOM 是被視為節點樹的 HTML。
什么是節點
2.什么是DOM節點
HTML 文檔中的所有內容都是節點
整個文檔是一個文檔節點
每個 HTML 元素是元素節點
HTML 元素內的文本是文本節點
每個 HTML 屬性是屬性節點
注釋是注釋節點
demo
3.常見的DOM屬性
屬性是節點(HTML 元素)的值,您能夠獲取或設置。
innerHTML 屬性
nodeName 屬性
nodeName 屬性規定節點的名稱
元素節點的 nodeName 與標簽名相同
屬性節點的 nodeName 與屬性名相同
文本節點的 nodeName 始終是 #text
文檔節點的 nodeName 始終是 #document
nodeValue 屬性
nodeValue 屬性規定節點的值。
元素節點的 nodeValue 是 undefined 或 null
文本節點的 nodeValue 是文本本身
屬性節點的 nodeValue 是屬性值
通過使用 getElementById() 方法
通過使用 getElementsByTagName() 方法
通過使用 getElementsByClassName() 方法
5.修改元素的方法
改變 HTML 內容
document.getElementById("p1").innerHTML="New text!";
改變 CSS 樣式
document.getElementById("p2").style.color="blue";
改html和css
追加子元素的方法
首先必須創建該元素(元素節點),然后把它追加到已有的元素上。var para=document.createElement("p");
創建新的 HTML 元素 - appendChild() 在父元素的最后追加
創建新的 HTML 元素-element.insertBefore(para,child);在指定位置給父級追加子元素
刪除 HTML 元素,您必須清楚該元素的父元素:parent.removeChild(child);
替換 HTML 元素:parent.replaceChild(para,child); 方法
6.DOM - 事件
允許 JavaScript 對 HTML 事件作出反應
onclick 事件——當用戶點擊時
onload 事件——用戶進入
onunload 事件——用戶離開
onmouseover事件——鼠標移入
onmouseout事件——鼠標移出
onmousedown事件——鼠標按下
onmouseup 事件——鼠標抬起
7.參考文獻
藍藍設計( www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務
如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里
基本格式:
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>制作我的第一個網頁</title>
<style type="text/css">
h1{font-size;color;text-align:center}
</style>
</head>
<body>
<h1>Hello World! </h1>
</body>
</html>
注釋:<!--注釋文本-->
強調語氣:<strong>,<em>:前者實現加粗再加粗,后者實現加粗加斜 體。
<span>標簽:寫在style 里設置單獨樣式。
<q></q>標簽:引用簡短文本,使引用的詩句等自己出現雙引號。
<blockquote>: 引用長文本,增加縮進量。
<br />: 換行標簽。
:代碼之間實現空格。
<hr />: 段落之間分隔的橫線。
<address>: 定義一個地址(比如電子郵件地址) ,簽名或者文檔的作者身份。在瀏覽器上顯示的樣式為斜體。
<code>: 加入簡短代碼。
<pre>: 加入一段長代碼。
Ul-li標簽: 添加新聞信息列表, 圖片列表, 無序文字列表。
Ol-li 標簽:添加有序列表,與ul-li 標簽類似。
<div> :把一些獨立的邏輯部分劃分出來,形成欄目板塊。其中還可使用
<div id=” “>給板塊命名。
<table>: 制作表格。
用CSS 樣式為表格添加邊框:<style type=”text/css”>
黑色邊框: table tr td,th{border:1px solid #000;}</style>
<caption>:為表格添加標題和摘要。 <table summary=’’”表格簡介文本”>
<caption>標題文本</caption> </table>
<a>: 實現超鏈接。<a href=”目標網址” title=“鼠標滑過顯示的文本”>鏈接顯示的文本</a> 默認在當前瀏覽器窗口打開,添加“target—blank ”在新的瀏覽器窗口打開。
<mailto>: 在網頁中鏈接Email 地址。 <a href=”mailto: yy@qq。com ?
Cc(抄送地址)=zsq@qq。com & bcc(密件抄送地址)=zjj@qq。com &
subject=”主題” & body=“郵件內容”>發送</a> 給多個收件人發送,用分號隔開。第一個參數用?開頭,之后用 &隔開。
<img>: 添加圖片。Src=”標識圖像的位置?!?alt=”指定圖像的描述性文本,當圖像不可見時(下載不成功時),可看到該屬性指定的文本”
Title=“提供在圖像可見時對圖像的描述(鼠標滑過圖片時顯示的文本)”
<form>: 表單標簽,與用戶交互使得瀏覽器可以處理用戶的數據。
<form method=”數據傳送的方式(get/post)action=”瀏覽器輸入的數據被傳送到的地方,如一個 PHP 頁面(save。php)””
<label for="username">用戶名:</label>
<input type="text" name="username" id="username" value="" />
<label for="pass">密碼:</label>
<input type="password" name="pass" id="pass" value="" /> 瀏覽器顯示: 用戶名: 肯定存,啊 密碼:
表單文本輸入框,密碼輸入框:<form><input type=”text/password”
name=”名稱(以備后臺使用)” value=“文本(設置默認值,提示作用)”>
文本域的多行輸入:<textarearows(height)=”行數” cols(width)
=”列數”>文本</textarea>
單選框,復選框:<input type=”radio(單選框)/checkbox(復選框)”
value=” 值 ” name=” 名 稱 ” checked= “ checked ” /> 當 設 置
checked=”checked”時,該選項被默認選中。同一組按鈕,name 取值必須相同。
下拉列表框<select>:<label> XX </label>
<select>
<option value=”讀書” selected=”selected(被默認選中)”>讀書</option></select>
提交按鈕 submit:<input type=”submit” value=”提交”>重置按鈕 reset:<input type=”reset” value=”重置”>
<label>:<label for=”控件id 名稱”>慢跑 </label>
<input type=”checkbox” name=”gender” id=”jogging” />
for 屬性的值與id 屬性值一定要相同。
Placeholder:<input type=”email” id=”email” placeholder=”Enter email”>該提示會在輸入字段為空時顯示,并會在字段獲得焦點時消失。
CSS 樣式:定義文本的顯示樣式,如字體大?。?span style="box-sizing:border-box;outline:0px;word-break:break-all;color:#9BBA58;">font-size),顏色(color),加粗(font-weight:bold)等。
注釋語句:/*注釋語句*/。
內聯式 CSS 樣式:<p style=”color:red ; font-size:12px”>紅色字體</p>
嵌入式 CSS 樣式:<style type=”text/css”>span{ }</style>
外部式 CSS 樣式:在head 里寫:<link href=”XX。css” rel=”stylesheet”
type=”text/css”>,在XX。css 里寫:span{ }
三種方式的優先級:相同權值下,內聯式 >嵌入式 >外部式。但是,嵌入式 >外部式的前提為嵌入式的位置一定在外部式的后面。
選擇器:每一條CSS 樣式定義由兩部分組成:選擇器{樣式;}
標簽選擇器:如<html>,<body>,<h1>,<img>,<p font,,>。
類選擇器:。類選擇名稱(可任意起名,。XX){css 樣式代碼;} -> <span class=”XX”></span>
ID 選擇器:#類選擇名稱(可任意,#XX){css 樣式代碼;} -><span
id=”XX”></span>只能在文檔中使用一次。
“>”子選擇器:用于選擇指定標簽元素的第一代子元素。【直接后代】 first>span{border:1px solid red;} <span>我還是一個<span>膽小如鼠</span>的小女孩</span>
包含(后代)選擇器:加入空格,用于選擇指定標簽元素下的后輩元素。【所有子后代元素】
通用選擇器:由一個*指定,匹配html 中所有標簽元素。在style 里:
*{color:red;}
偽類選擇符 “ :hover”:它允許給html 不存在的標簽(標簽的某種狀態)設置樣式。 a:hover{color:red;}鼠標滑過時字體變為紅色。
分組選擇符 “ ,”:為多個標簽元素設置同一個樣式。 如h1,p{ }。
繼承:有些樣式具有繼承性如color,有些不具有如border。具有繼承性的允許樣式不僅應用于某個特定 html 標簽元素,而且應用于其后代。
權值:標簽的權值為1,類選擇符的權值為10,ID 選擇符的權值最高為 100。
p{color:red;} /*權值為1*/
p span{color:green;} /*權值為1+1=2*/
。warning{color:white;} /*權值為10*/
p span。warning{color:purple;} /*權值為1+1+10=12*/
#footer 。note p{color:yellow;} /*權值為100+10+1=111*/ 特殊性:繼承也有權值,但是只有0。1 。
層疊:當有相同權重值時,后面的樣式會覆蓋前面的樣式。
重要性 !important :p{color:red!important;}這時p 段落中的文本會顯示紅色。!important 要寫在分號前面。
藍藍設計( www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務
如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里
input框的類型到底有多少種呢?零零總總算起來有23種。
▍總述
常用的并且能為大多數瀏覽器所識別的類型大概有:text、password、number、button、reset、submit、hidden、radio、checkbox、file、image、color、range、date、month、week、time、datetime-local。
另外還有一些類型:tel、email、url、datetime、search。這些類型部分瀏覽器不支持識別或校驗。
▍text:文本
代碼:
效果:
注意:當input沒有填寫類型時,默認為文本類型。
▍password:密碼
代碼:
效果:
▍number:數字
代碼:
效果:
▍button:按鈕
代碼:
效果:
▍tel:電話
代碼:
效果:
注意:tel類型似乎沒有什么實際作用。
▍email:郵件
代碼:
效果:
注意:火狐對email類型有校驗,360瀏覽器無校驗。
▍file:文件
代碼:
效果:
▍range:滑動條
代碼:
效果:
▍date:日期
代碼:
效果:
▍month:月份
代碼:
效果:
▍week:周
代碼:
效果:
▍time:時間
代碼:
效果:
▍datetime:時間、日、月、年(UTC時間)
代碼:
效果:
注意:火狐、360瀏覽器都對datetime不支持,會按照text類型處理。
▍datetime-local:時間、日、月、年(本地時間)
代碼:
效果:
▍radio:單選框
代碼:
效果:
▍checkbox:復選框
代碼:
效果:
▍image:圖片
代碼:
效果:
▍color:顏色
代碼:
效果:
▍search:搜索框
代碼:
效果:
注意:search似乎與text的效果沒有什么區別。。。
▍reset:重置按鈕
代碼:
效果:
注意:reset按鈕一般用于form表單中。
▍submit:提交按鈕
代碼:
效果:
注意:submit按鈕一般用于form表單中。
▍hidden:隱藏
代碼:
效果:
注意:hidden類型會將input隱藏,所以什么都看不到,而且被隱藏的input框也不會占用空間。
▍url:路徑
代碼:
效果:
注意:火狐對url類型有校驗,360瀏覽器無校驗。
▍寫在結尾
總的來說,目前input框也就只有這23種類型,雖然有的類型可能用不上一兩次甚至是一次都用不上,但是了解一下還是不錯的。
藍藍設計( www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務
如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里
vue-router
對于大多數單頁面應用,都推薦使用官方支持的 vue-router 庫。
學習網址:https://router.vuejs.org/installation.html#direct-download-cdn
提示:本篇博客僅僅介紹搭建項目之后,再下載vue-router的情況,并非搭建項目是直接引入vue-router。
一、安裝方法(npm方式)
在終端運行以下指令
注意:--save 與 --save-dev 的區別
--save(可以省略) 下載的第三方依賴到package.js中的dependencies。
--save-dev 下載開發時依賴,指環境配置,下載到package.js中的devDependencies,webpack、bable等等均屬于開發
時依賴。
二、導入與使用
vue-router下載之后,需要在入口文件main.js導入,具體做法如下:
三、官網介紹使用步驟
網址:https://router.vuejs.org/zh/guide/#javascript
藍藍設計( www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務
藍藍設計的小編 http://www.syprn.cn