<address id="ttjl9"></address>

      <noframes id="ttjl9"><address id="ttjl9"><nobr id="ttjl9"></nobr></address>
      <form id="ttjl9"></form>
        <em id="ttjl9"><span id="ttjl9"></span></em>
        <address id="ttjl9"></address>

          <noframes id="ttjl9"><form id="ttjl9"></form>

          首頁

          React Native原生與JS層交互

          seo達人

          如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里

          最近在對《React Native移動開發實戰》一書進行部分修訂和升級。在React Native開發中,免不了會涉及到原生代碼與JS層的消息傳遞等問題,那么React Native究竟是如何實現與原生的互相操作的呢?

          原生給React Native傳參

          原生給React Native傳值

          原生給JS傳值,主要依靠屬性,也就是通過initialProperties,這個RCTRootView的初始化函數的參數來完成。通過RCTRootView的初始化函數你可以將任意屬性傳遞給React Native應用,參數initialProperties必須是NSDictionary的一個實例。RCTRootView有一個appProperties屬性,修改這個屬性,JS端會調用相應的渲染方法。

          使用RCTRootView將React Natvie視圖封裝到原生組件中。RCTRootView是一個UIView容器,承載著React Native應用。同時它也提供了一個聯通原生端和被托管端的接口。

          例如有下面一段OC代碼:

          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];
              
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14

          下面是JS層的處理:

          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);
              
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23

          不管OC中關于initialProperties的名字叫什么,在JS中都是this.props開頭,然后接下來才是key名字。

          {"rootTag":1,"initialProps":{"images":["http://foo.com/bar1.png","http://foo.com/bar2.png"]}}. 
              
          • 1

          使用appProperties進行參數傳遞

          RCTRootView同樣提供了一個可讀寫的屬性appProperties。在appProperties設置之后,React Native應用將會根據新的屬性重新渲染。當然,只有在新屬性和舊的屬性有更改時更新才會被觸發。

          NSArray *imageList = @[@"http://foo.com/bar3.png", @"http://foo.com/bar4.png"]; rootView.appProperties = @{@"images" : imageList};
              
          • 1
          • 2
          • 3

          可以隨時更新屬性,但是更新必須在主線程中進行,讀取則可以在任何線程中進行。

          React Native執行原生方法及回調

          React Native執行原生方法

          .h的文件代碼:

          #import <Foundation/Foundation.h> #import <RCTBridgeModule.h> @interface wjyTestManager : NSObject<RCTBridgeModule> @end
              
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7

          .m的文件代碼:

          #import "wjyTestManager.h" @implementation wjyTestManager RCT_EXPORT_MODULE();
          
          RCT_EXPORT_METHOD(doSomething:(NSString *)aString withA:(NSString *)a)
          { NSLog(@"%@,%@",aString,a);
          } @end
              
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12

          為了實現RCTBridgeModule協議,你的類需要包含RCT_EXPORT_MODULE()宏。這個宏也可以添加一個參數用來指定在Javascript中訪問這個模塊的名字。如果你不指定,默認就會使用這個Objective-C類的名字。

          并且必須明確的聲明要給Javascript導出的方法,否則React Native不會導出任何方法。OC中聲明要給Javascript導出的方法,通過RCT_EXPORT_METHOD()宏來實現。

          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);
              
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27
          • 28
          • 29
          • 30
          • 31
          • 32
          • 33
          • 34
          • 35
          • 36
          • 37
          • 38

          要用到NativeModules則要引入相應的命名空間import { NativeModules } from ‘react-native’;然后再進行調用CalendarManager.doSomething(‘sdfsdf’,’sdfsdfs’);橋接到Javascript的方法返回值類型必須是void。React Native的橋接操作是異步的,所以要返回結果給Javascript,你必須通過回調或者觸發事件來進行。

          傳參并回調

          RCT_EXPORT_METHOD(testCallbackEvent:(NSDictionary *)dictionary callback:(RCTResponseSenderBlock)callback)
          { NSLog(@"當前名字為:%@",dictionary); NSArray *events=@[@"callback ", @"test ", @" array"];
            callback(@[[NSNull null],events]);
          }
              
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6

          說明:第一個參數代表從JavaScript傳過來的數據,第二個參數是回調方法; 
          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>
          
                  );
                }
          }
              
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27

          參數類型說明

          RCT_EXPORT_METHOD 支持所有標準JSON類型,包括:

          • string (NSString)
          • number (NSInteger, float, double, CGFloat, NSNumber)
          • boolean (BOOL, NSNumber)
          • array (NSArray) 包含本列表中任意類型
          • object (NSDictionary) 包含string類型的鍵和本列表中任意類型的值
          • function (RCTResponseSenderBlock)

          除此以外,任何RCTConvert類支持的的類型也都可以使用(參見RCTConvert了解更多信息)。RCTConvert還提供了一系列輔助函數,用來接收一個JSON值并轉換到原生Objective-C類型或類。例如:

          #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);
          }
              
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14

          iOS原生訪問React Native

          如果需要從iOS原生方法發送數據到JavaScript中,那么使用eventDispatcher。例如:

          #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
              
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16

          在JavaScript中可以這樣訂閱事件,通常需要在componentWillUnmount函數中取消事件的訂閱。

          import { NativeAppEventEmitter } from 'react-native';
          
          var subscription = NativeAppEventEmitter.addListener( 'EventReminder',
            (reminder) => console.log(reminder.name)
          ); ... // 千萬不要忘記忘記取消訂閱, 通常在componentWillUnmount函數中實現。
          subscription.remove();
              
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9

          用NativeAppEventEmitter.addListener中注冊一個通知,之后再OC中通過bridge.eventDispatcher sendAppEventWithName發送一個通知,這樣就形成了調用關系。

          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 平面設計服務

          js學習中的總結——幾種繼承模式

          seo達人

          如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里

               js中構造函數的幾種繼承模式淺析

          一、原型鏈模式繼承

              利用原型讓一個引用類型繼承另一個引用類型的屬性和方法 。

              用的最多。

              缺點:不可傳參,不可多繼承。

          
                  
          1. function People(name, age) {//添加公有屬性
          2. name = name || 'xiaolan';
          3. age = age || 18;
          4. this.name = name;
          5. this.age = age;
          6. }//創建一個名為People的類
          7. People.prototype.eat = function() {//添加私有屬性
          8. console.log(this.name + '賊能吃');
          9. }
          10. function Cat(color) {//創建一個名為Cat的類
          11. this.color = color;
          12. }
          13. Cat.prototype = new People('小叮當', 200);//實例化一個People類,并賦值給Cat類的原型鏈
          14. var cat = new Cat('藍白色')
          15. console.log(cat.name)//'小叮當'
          16. cat.eat();//'小叮當賊能吃'

          二、混合模式繼承

              用call的方法只能繼承私有屬性,所以再加一遍一遍原型鏈模式繼承,原型鏈模式繼承又把私有屬性和公有屬性都繼承了一遍。

          
                  
          1. function People(name, age) { //創建一個父級People類
          2. name = name || 'xiaolan';
          3. age = age || 18;
          4. this.name = name;
          5. this.age = age;
          6. }
          7. People.prototype.eat = function() {
          8. console.log(this.name + '賊能吃');
          9. }
          10. function Cat(color, name, age) {
          11. this.color = color;
          12. People.call(this, name, age); //通過call的形式繼承
          13. //通過call(this),將People的指向改為Cat的實例
          14. }
          15. var cat = new Cat('藍白色', '小叮當', 1);
          16. console.log(cat.name);//'小叮當'
          17. cat.eat();//報錯,
          18. //繼承不了公有屬性,所以cat.eat()會報錯;

          為了繼承公有屬性,用原型鏈模式在把公有屬性和方法繼承過來,

          
                  
          1. function People(name, age) { //創建一個父級People類
          2. name = name || 'xiaolan';
          3. age = age || 18;
          4. this.name = name;
          5. this.age = age;
          6. }
          7. People.prototype.eat = function() {
          8. console.log(this.name + '賊能吃');
          9. }
          10. function Cat(color, name, age) {
          11. this.color = color;
          12. People.call(this, name, age); //通過call的形式繼承
          13. //通過call(this),將People的指向改為Cat的實例
          14. }
          15. Cat.prototype = new People()
          16. var cat = new Cat('藍白色', '小叮當', 200)
          17. console.log(cat)
          18. console.log(cat.name); //'小叮當',在原型鏈繼承的時候,就近原則,cat.name 先找到'小叮當',就不往下找了
          19. cat.eat(); //'小叮當賊能吃'

          三、拷貝繼承

              優點:可以多繼承,可傳參;

              缺點:浪費資源,不能判斷父級;

          
                  
          1. function People(name, age) { //創建一個父級People類
          2. name = name || 'xiaolan';
          3. age = age || 18;
          4. this.name = name;
          5. this.age = age;
          6. }
          7. People.prototype.eat = function() {
          8. console.log(this.name + '賊能吃');
          9. }
          10. function Cat(color, name, age) {
          11. this.color = color;
          12. var people = new People(name, age) //實例化一個People類
          13. for (let i in people) {
          14. this[i] = people[i]; //將people中的可枚舉屬性和方法遍歷并附給Cat類,公有屬性和私有屬性都是可枚舉屬性;
          15. }
          16. }
          17. var cat = new Cat('藍白色', '小叮當', 2);
          18. console.log(cat.name); //小叮當
          19. cat.eat(); //小叮當賊能吃

          四、寄生組合方式繼承

              優點:私有屬性和公有屬性都單獨繼承,可以傳參;

              私有屬性可以多繼承,公有屬性不可多繼承;

          
                  
          1. function People(name, age) {
          2. name = name || 'xiaolan';
          3. age = age || 18;
          4. this.name = name;
          5. this.age = age;
          6. }
          7. People.prototype.eat = function() {
          8. console.log(this.name + '賊能吃');
          9. }
          10. function Cat(color, name, age) {
          11. this.color = color;
          12. People.call(this, name, age) //用call的形式把私有屬性繼承過來
          13. }
          14. function Fn() {} //創建一個中間構造函數,用來接收People的公有屬性,為了防止創建實例Cat實例是影響原來的people構造函數
          15. Fn.prototype = People.prototype;
          16. Cat.prototype = new Fn(); //將中間構造函數Fn繼承people的公有屬性傳給Cat的原型鏈
          17. Cat.prototype.constructor = Cat; //由于上一步重置了Cat原型鏈的constructor屬性,所以要重新給賦回來;
          18. var cat = new Cat('藍白色', '小叮當', 3);
          19. console.log(cat.name); //'小叮當'
          20. cat.eat() //'小叮當賊能吃


          注:若有不嚴謹與錯誤的地方,請多指教!






          1. 這里寫圖片描述



          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 平面設計服務


          vue在ie9中的兼容問題

          seo達人

          如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里

          問題總結  https://github.com/vuejs-templates/webpack/issues/260

          1. 首先npm install --save babel-polyfill

          2. 然后在main.js中的最前面引入babel-polyfill

            import 'babel-polyfill'

          3. 在index.html 加入以下代碼(非必須)

            <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">

          4. 在config中的webpack.base.conf.js中,修改編譯配置

          
              
          1. entry:{
          2. app:['babel-polyfill','./src/main.js']
          3. }

          當然,如果你只用到了 axios 對 promise進行兼容,可以只用 es6-promise

          npm install es6-promise --save

          在 main.js 中的最前面 引入

          import 'es6-promise/auto' 
          • 以上配置,ie9兼容就完成了

          那么,就有一個問題了,build之后的dist文件只有放在服務器上才能查看,但本地如何查看呢,參考一下配置

          1. 修改config文件夾中的index.js文件,將build對象中的打包路徑,'/‘改為'./',由絕對路徑改為相對路徑,建議將sourceMap改為false,編譯的時候會快一點

            build: { assetsPublicPath: './', productionSourceMap: false, },

          2. 修改完之后,重新 npm run build ,得到新的dist文件夾

          3. 然后進入dist文件夾

            cd dist

          4. 全局安裝簡易node服務器

            npm install http-server -g

          5. 啟動簡易node服務器

            http-server

          6. 出現如下圖所示,就代表你的服務器啟動成功了,那你也能在5000端口查看編譯打包后的項目了,可以在ie瀏覽器中直接測試了

            這里寫圖片描述

          7. IE在處理日期的時候,不支持-支持/的日期方式 如 2017-01-01應該 


          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務


          ES6新特性Promise異步調用

          seo達人

          如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里

          Promise 的含義

          Promise 是異步編程的一種解決方案,比傳統的解決方案–回調函數和事件--更合理和更強大。它由社區最早提出和實現,ES6將其寫進了語言標準,統一了語法,原生提供了Promise

          所謂Promise ,簡單說就是一個容器,里面保存著某個未來才回結束的事件(通常是一個異步操作)的結果。從語法上說,Promise是一個對象,從它可以獲取異步操作的消息。 
          Promise 對象的狀態不受外界影響

          三種狀態:

          • pending:進行中
          • fulfilled :已經成功
          • rejected 已經失敗

          狀態改變: 
          Promise對象的狀態改變,只有兩種可能:

          • 從pending變為fulfilled
          • 從pending變為rejected。

          這兩種情況只要發生,狀態就凝固了,不會再變了,這時就稱為resolved(已定型

          基本用法

          ES6規定,Promise對象是一個構造函數,用來生成Promise實例

          
              
          1. const promist = new Promise(function(resolve,reject){
          2. if(/*異步操作成功*/){
          3. resolve(value);
          4. }else{
          5. reject(error);
          6. }
          7. })
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7

          resolve函數的作用是,將Promise對象的狀態從“未完成”變為“成功”(即從 pending 變為 resolved),在異步操作成功時調用,并將異步操作的結果,作為參數傳遞出去; 
          reject函數的作用是,將Promise對象的狀態從“未完成”變為“失敗”(即從 pending 變為 rejected),在異步操作失敗時調用,并將異步操作報出的錯誤,作為參數傳遞出去。

          Promise的源碼分析:

          1.回調地獄

          曾幾何時,我們的代碼是這樣的,為了拿到回調的結果,不得不callback hell,這種環環相扣的代碼可以說是相當惡心了

          
                      
          1. let fs = require('fs')
          2. fs.readFile('./a.txt','utf8',function(err,data){
          3. fs.readFile(data,'utf8',function(err,data){
          4. fs.readFile(data,'utf8',function(err,data){
          5. console.log(data)
          6. })
          7. })
          8. })

          終于,我們的蓋世英雄出現了,他身披金甲圣衣、駕著七彩祥云。好吧打岔兒了,沒錯他就是我們的Promise,那讓我們來看看用了Promise之后,上面的代碼會變成什么樣吧

          
                      
          1. let fs = require('fs')
          2. function read(url){
          3. return new Promise((resolve,reject)=>{
          4. fs.readFile(url,'utf8',function(error,data){
          5. error && reject(error)
          6. resolve(data)
          7. })
          8. })
          9. }
          10. read('./a.txt').then(data=>{
          11. return read(data)
          12. }).then(data=>{
          13. return read(data)
          14. }).then(data=>{
          15. console.log(data)
          16. })

          2.重點開始,小眼睛都看過來

          2.1 Promise/A+

          首先我們要知道自己手寫一個Promise,應該怎么去寫,誰來告訴我們怎么寫,需要遵循什么樣的規則。當然這些你都不用擔心,其實業界都是通過一個規則指標來生產Promise的。讓我們來看看是什么東西。傳送門?Promise/A+

          2.2 constructor

          我們先聲明一個類,叫做Promise,里面是構造函數。如果es6還有問題的可以去阮大大的博客上學習一下(傳送門?es6

          
                      
          1. class Promise{
          2. constructor(executor){
          3. //控制狀態,使用了一次之后,接下來的都不被使用
          4. this.status = 'pendding'
          5. this.value = undefined
          6. this.reason = undefined
          7. //定義resolve函數
          8. let resolve = (data)=>{
          9. //這里pendding,主要是為了防止executor中調用了兩次resovle或reject方法,而我們只調用一次
          10. if(this.status==='pendding'){
          11. this.status = 'resolve'
          12. this.value = data
          13. }
          14. }
          15. //定義reject函數
          16. let reject = (data)=>{
          17. if(this.status==='pendding'){
          18. this.status = 'reject'
          19. this.reason = data
          20. }
          21. }
          22. //executor方法可能會拋出異常,需要捕獲
          23. try{
          24. //將resolve和reject函數給使用者
          25. executor(resolve,reject)
          26. }catch(e){
          27. //如果在函數中拋出異常則將它注入reject中
          28. reject(e)
          29. }
          30. }
          31. }

          那么接下來我會分析上面代碼的作用,原理

          • 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

          then方法是Promise中最為重要的方法,他的用法大家都應該已經知道,就是將Promise中的resolve或者reject的結果拿到,那么我們就能知道這里的then方法需要兩個參數,成功回調和失敗回調,上代碼!

          
                      
          1. then(onFufilled,onRejected){
          2. if(this.status === 'resolve'){
          3. onFufilled(this.value)
          4. }
          5. if(this.status === 'reject'){
          6. onRejected(this.reason)
          7. }
          8. }

          這里主要做了將構造器中resolve和reject的結果傳入onFufilledonRejected中,注意這兩個是使用者傳入的參數,是個方法。所以你以為這么簡單就完了?要想更Swag的應對各種場景,我們必須得再完善。繼續往下走!

          3.異步的Promise

          之前我們只是處理了同步情況下的Promise,簡而言之所有操作都沒有異步的成分在內。那么如果是異步該怎么辦?

          3.1 callback?。。。?

          最早處理異步的方法就是callback,就相當于我讓你幫我掃地,我會在給你發起任務時給你一個手機,之后我做自己的事情去,不用等你,等你掃完地就會打手機給我,誒,我就知道了地掃完了。這個手機就是callback,回調函數。

          首先我們需要改一下構造器里的代碼,分別添加兩個回調函數的數組,分別對應成功回調和失敗回調。他們的作用是當成功執行resolve或reject時,執行callback。

          
                      
          1. //存放成功回調的函數
          2. this.onResolvedCallbacks = []
          3. //存放失敗回調的函數
          4. this.onRejectedCallbacks = []
          5. let resolve = (data)=>{
          6. if(this.status==='pendding'){
          7. this.status = 'resolve'
          8. this.value = data
          9. //監聽回調函數
          10. this.onResolvedCallbacks.forEach(fn=>fn())
          11. }
          12. }
          13. let reject = (data)=>{
          14. if(this.status==='pendding'){
          15. this.status = 'reject'
          16. this.reason = data
          17. this.onRejectedCallbacks.forEach(fn=>fn())
          18. }
          19. }

          然后是then需要多加一個狀態判斷,當Promise中是異步操作時,需要在我們之前定義的回調函數數組中添加一個回調函數。

          
                      
          1. if(this.status === 'pendding'){
          2. this.onResolvedCallbacks.push(()=>{
          3. // to do....
          4. let x = onFufilled(this.value)
          5. resolvePromise(promise2,x,resolve,reject)
          6. })
          7. this.onRejectedCallbacks.push(()=>{
          8. let x = onRejected(this.reason)
          9. resolvePromise(promise2,x,resolve,reject)
          10. })
          11. }

          ok!大功告成,異步已經解決了

          3.2 resolvePromise

          這也是Promise中的重頭戲,我來介紹一下,我們在用Promise的時候可能會發現,當then函數中return了一個值,我們可以繼續then下去,不過是什么值,都能在下一個then中獲取,還有,當我們不在then中放入參數,例:promise.then().then(),那么其后面的then依舊可以得到之前then返回的值,可能你現在想很迷惑。讓我來解開你心中的憂愁,follow me

          
                      
          1. then(onFufilled,onRejected){
          2. //解決onFufilled,onRejected沒有傳值的問題
          3. onFufilled = typeof onFufilled === 'function'?onFufilled:y=>y
          4. //因為錯誤的值要讓后面訪問到,所以這里也要跑出個錯誤,不然會在之后then的resolve中捕獲
          5. onRejected = typeof onRejected === 'function'?onRejected:err=>{ throw err ;}
          6. //聲明一個promise對象
          7. let promise2
          8. if(this.status === 'resolve'){
          9. //因為在.then之后又是一個promise對象,所以這里肯定要返回一個promise對象
          10. promise2 = new Promise((resolve,reject)=>{
          11. setTimeout(()=>{
          12. //因為穿透值的緣故,在默認的跑出一個error后,不能再用下一個的reject來接受,只能通過try,catch
          13. try{
          14. //因為有的時候需要判斷then中的方法是否返回一個promise對象,所以需要判斷
          15. //如果返回值為promise對象,則需要取出結果當作promise2的resolve結果
          16. //如果不是,直接作為promise2的resolve結果
          17. let x = onFufilled(this.value)
          18. //抽離出一個公共方法來判斷他們是否為promise對象
          19. resolvePromise(promise2,x,resolve,reject)
          20. }catch(e){
          21. reject(e)
          22. }
          23. },0)
          24. })
          25. }
          26. if(this.status === 'reject'){
          27. promise2 = new Promise((resolve,reject)=>{
          28. setTimeout(()=>{
          29. try{
          30. let x = onRejected(this.reason)
          31. resolvePromise(promise2,x,resolve,reject)
          32. }catch(e){
          33. reject(e)
          34. }
          35. },0)
          36. })
          37. }
          38. if(this.status === 'pendding'){
          39. promise2 = new Promise((resolve,reject)=>{
          40. this.onResolvedCallbacks.push(()=>{
          41. // to do....
          42. setTimeout(()=>{
          43. try{
          44. let x = onFufilled(this.value)
          45. resolvePromise(promise2,x,resolve,reject)
          46. }catch(e){
          47. reject(e)
          48. }
          49. },0)
          50. })
          51. this.onRejectedCallbacks.push(()=>{
          52. setTimeout(()=>{
          53. try{
          54. let x = onRejected(this.reason)
          55. resolvePromise(promise2,x,resolve,reject)
          56. }catch(e){
          57. reject(e)
          58. }
          59. })
          60. })
          61. })
          62. }
          63. return promise2
          64. }

          一下子多了很多方法,不用怕,我會一一解釋

          1. 返回Promise?:首先我們要注意的一點是,then有返回值,then了之后還能在then,那就說明之前的then返回的必然是個Promise
          2. 為什么外面要包一層setTimeout?:因為Promise本身是一個異步方法,屬于微任務一列,必須得在執行棧執行完了在去取他的值,所以所有的返回值都得包一層異步setTimeout。
          3. 為什么開頭有兩個判斷?:這就是之前想要解決的如果then函數中的參數不是函數,那么我們需要做處理。如果onFufilled不是函數,就需要自定義個函數用來返回之前resolve的值,如果onRejected不是函數,自定義個函數拋出異常。這里會有個小坑,如果這里不拋出異常,會在下一個then的onFufilled中拿到值。又因為這里拋出了異常所以所有的onFufilled或者onRejected都需要try/catch,這也是Promise/A+的規范。當然本人覺得成功的回調不需要拋出異常也可以,大家可以仔細想想。
          4. resolvePromise是什么?:這其實是官方Promise/A+的需求。因為你的then可以返回任何職,當然包括Promise對象,而如果是Promise對象,我們就需要將他拆解,直到它不是一個Promise對象,取其中的值。

          那就讓我們來看看這個resolvePromise到底長啥樣。

          
                      
          1. function resolvePromise(promise2,x,resolve,reject){
          2. //判斷x和promise2之間的關系
          3. //因為promise2是上一個promise.then后的返回結果,所以如果相同,會導致下面的.then會是同一個promise2,一直都是,沒有盡頭
          4. if(x === promise2){//相當于promise.then之后return了自己,因為then會等待return后的promise,導致自己等待自己,一直處于等待
          5. return reject(new TypeError('循環引用'))
          6. }
          7. //如果x不是null,是對象或者方法
          8. if(x !== null && (typeof x === 'object' || typeof x === 'function')){
          9. //為了判斷resolve過的就不用再reject了,(比如有reject和resolve的時候)
          10. let called
          11. try{//防止then出現異常,Object.defineProperty
          12. let then = x.then//取x的then方法可能會取到{then:{}},并沒有執行
          13. if(typeof then === 'function'){
          14. //我們就認為他是promise,call他,因為then方法中的this來自自己的promise對象
          15. then.call(x,y=>{//第一個參數是將x這個promise方法作為this指向,后兩個參數分別為成功失敗回調
          16. if(called) return;
          17. called = true
          18. //因為可能promise中還有promise,所以需要遞歸
          19. resolvePromise(promise2,y,resolve,reject)
          20. },err=>{
          21. if(called) return;
          22. called = true
          23. //一次錯誤就直接返回
          24. reject(err)
          25. })
          26. }else{
          27. //如果是個普通對象就直接返回resolve作為結果
          28. resolve(x)
          29. }
          30. }catch(e){
          31. if(called) return;
          32. called = true
          33. reject(e)
          34. }
          35. }else{
          36. //這里返回的是非函數,非對象的值,就直接放在promise2的resolve中作為結果
          37. resolve(x)
          38. }
          39. }

          它的作用是用來將onFufilled的返回值進行判斷取值處理,把最后獲得的值放入最外面那層的Promise的resolve函數中。

          1. 參數promise2(then函數返回的Promise對象),x(onFufilled函數的返回值),resolve、reject(最外層的Promise上的resolve和reject)。
          2. 為什么要在一開始判斷promise2x?:首先在Promise/A+中寫了需要判斷這兩者如果相等,需要拋出異常,我就來解釋一下為什么,如果這兩者相等,我們可以看下下面的例子,第一次p2是p1.then出來的結果是個Promise對象,這個Promise對象在被創建的時候調用了resolvePromise(promise2,x,resolve,reject)函數,又因為x等于其本身,是個Promise,就需要then方法遞歸它,直到他不是Promise對象,但是x(p2)的結果還在等待,他卻想執行自己的then方法,就會導致等待。
          
                      
          1. let p1 = new Promise((resolve,reject)=>{
          2. resolve()
          3. })
          4. let p2 = p1.then(d=>{
          5. return p2
          6. })
          1. called是用來干嘛的?:called變量主要是用來判斷如果resolvePromise函數已經resolve或者reject了,那就不需要在執行下面的resolce或者reject。
          2. 為什么取then這個屬性?:因為我們需要去判斷x是否為Promise,then屬性如果為普通值,就直接resolve掉,如果是個function,就是Promise對象,之后我們就需要將這個x的then方法進行執行,用call的原因是因為then方法里面this指向的問題。
          3. 為什么要遞歸去調用resolvePromise函數?:相信細心的人已經發現了,我這里使用了遞歸調用法,首先這是Promise/A+中要求的,其次是業務場景的需求,當我們碰到那種Promise的resolve里的Promise的resolve里又包了一個Promise的話,就需要遞歸取值,直到x不是Promise對象。

          4.完善Promise

          我們現在已經基本完成了Promise的then方法,那么現在我們需要看看他的其他方法。

          4.1 catch

          相信大家都知道catch這個方法是用來捕獲Promise中的reject的值,也就是相當于then方法中的onRejected回調函數,那么問題就解決了。我們來看代碼。

          
                      
          1. //catch方法
          2. catch(onRejected){
          3. return this.then(null,onRejected)
          4. }

          該方法是掛在Promise原型上的方法。當我們調用catch傳callback的時候,就相當于是調用了then方法。

          4.2 resolve/reject

          大家一定都看到過Promise.resolve()、Promise.reject()這兩種用法,它們的作用其實就是返回一個Promise對象,我們來實現一下。

          
                      
          1. //resolve方法
          2. Promise.resolve = function(val){
          3. return new Promise((resolve,reject)=>{
          4. resolve(val)
          5. })
          6. }
          7. //reject方法
          8. Promise.reject = function(val){
          9. return new Promise((resolve,reject)=>{
          10. reject(val)
          11. })
          12. }

          這兩個方法是直接可以通過class調用的,原理就是返回一個內部是resolve或reject的Promise對象。

          4.3 all

          all方法可以說是Promise中很常用的方法了,它的作用就是將一個數組的Promise對象放在其中,當全部resolve的時候就會執行then方法,當有一個reject的時候就會執行catch,并且他們的結果也是按著數組中的順序來排放的,那么我們來實現一下。

          
                      
          1. //all方法(獲取所有的promise,都執行then,把結果放到數組,一起返回)
          2. Promise.all = function(promises){
          3. let arr = []
          4. let i = 0
          5. function processData(index,data){
          6. arr[index] = data
          7. i++
          8. if(i == promises.length){
          9. resolve(arr)
          10. }
          11. }
          12. return new Promise((resolve,reject)=>{
          13. for(let i=0;i<promises.length;i++){
          14. promises[i].then(data=>{
          15. processData(i,data)
          16. },reject)
          17. }
          18. })
          19. }

          其原理就是將參數中的數組取出遍歷,每當執行成功都會執行processData方法,processData方法就是用來記錄每個Promise的值和它對應的下標,當執行的次數等于數組長度時就會執行resolve,把arr的值給then。這里會有一個坑,如果你是通過arr數組的長度來判斷他是否應該resolve的話就會出錯,為什么呢?因為js數組的特性,導致如果先出來的是1位置上的值進arr,那么0位置上也會多一個空的值,所以不合理。

          4.4 race

          race方法雖然不常用,但是在Promise方法中也是一個能用得上的方法,它的作用是將一個Promise數組放入race中,哪個先執行完,race就直接執行完,并從then中取值。我們來實現一下吧。

          
                      
          1. //race方法
          2. Promise.race = function(promises){
          3. return new Promise((resolve,reject)=>{
          4. for(let i=0;i<promises.length;i++){
          5. promises[i].then(resolve,reject)
          6. }
          7. })
          8. }

          原理大家應該看懂了,很簡單,就是遍歷數組執行Promise,如果有一個Promise執行成功就resolve。

          Promise語法糖 deferred

          語法糖這三個字大家一定很熟悉,作為一個很Swag的前端工程師,對async/await這對兄弟肯定很熟悉,沒錯他們就是generator的語法糖。而我們這里要講的語法糖是Promise的。

          
                      
          1. //promise語法糖 也用來測試
          2. Promise.deferred = Promise.defer = function(){
          3. let dfd = {}
          4. dfd.promise = new Promise((resolve,reject)=>{
          5. dfd.resolve = resolve
          6. dfd.reject = reject
          7. })
          8. return dfd
          9. }

          什么作用呢?看下面代碼你就知道了

          
                      
          1. let fs = require('fs')
          2. let Promise = require('./promises')
          3. //Promise上的語法糖,為了防止嵌套,方便調用
          4. //壞處 錯誤處理不方便
          5. function read(){
          6. let defer = Promise.defer()
          7. fs.readFile('./1.txt','utf8',(err,data)=>{
          8. if(err)defer.reject(err)
          9. defer.resolve(data)
          10. })
          11. return defer.Promise
          12. }

          沒錯,我們可以方便的去調用他語法糖defer中的Promise對象。那么它還有沒有另外的方法呢?答案是有的。我們需要在全局上安裝promises-aplus-tests插件npm i promises-aplus-tests -g,再輸入promises-aplus-tests [js文件名] 即可驗證你的Promise的規范。


          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務


          么去控制瀏覽器對資源文件的處理行為

          seo達人

          如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里

          通常當用戶打開一個資源的url,如果瀏覽器支持這個格式的文件的情況下,瀏覽器會嘗試去再頁面里展示它而不是直接下載。例如一張圖片(jpg, png, gif等),幾乎所有瀏覽器都會去將圖片在瀏覽器里面展示。


          對于壓縮格式的文件(zip, tar, gzip等)瀏覽器總是會直接去下載它們,另外一些格式的文件,根據瀏覽器的不同也會有差異的處理方法,例如Microsoft Word文件(doc, docx)在ie瀏覽器下通常會在瀏覽器中展示,但是其他瀏覽器幾乎都會直接下載它,同樣的對于PDF文件chrome有自己的pdf 轉換器它會嘗試去在瀏覽器上展示該文件。

          強制下載文件

          對于瀏覽器這種行為,一般情況下是可以接受的,因為用戶可以在瀏覽器顯示文件后將文件保存到電腦中,但是一些情況下用戶可能希望文件直接被下載而不是在瀏覽器中被打開,比如有時候用戶想去下載一個歌曲,但是瀏覽器可能回去播放該音頻。那么怎么讓瀏覽器強制去下載文件要怎么做呢

          a標簽的download屬性

          html5中 a 標簽新增了 download 屬性,該屬性指示瀏覽器下載url的內容而不是導航到url,因此如果配置了此屬性用戶會直接下載url的內容。作為開發如果想直接觸發該事件我們可以直接用代碼模擬a標簽和點擊事件

          
              
          1. const link = document.createElement('a');
          2. link.addEventListener('click', function() {
          3. link.download = xxx;
          4. link.href = xxx;
          5. });
          6. const e = document.createEvent('MouseEvents');
          7. e.initEvent('click', false, false);
          8. link.dispatchEvent(e);
          • download屬性只在同域時候有效,當跨域請求時候該屬性將會被忽略。
          • 當前并非所以瀏覽器都支持該屬性,需要瀏覽器考慮兼容性。

          改變資源格式

          瀏覽器會根據資源類型去判斷是否支持,如果支持時會嘗試去在頁面上展示該資源。瀏覽器判斷資源類型是根據返回頭Content-Type的值,因此一方面我們在服務端可以設置返回頭字段為文件流'Content-Type': 'application/octet-stream',或者根據一些具體資源直接壓縮后傳輸,瀏覽器不能分析zip之類的壓縮文件所以會直接去下載它們。

          配置Content-Disposition

          在HTTP場景中,Content-Disposition 消息頭指示回復的內容該以何種形式展示,是以內聯的形式(即網頁或者頁面的一部分),還是以附件的形式下載并保存到本地。

          • inline 默認參數表示消息體會以頁面的一部分或者整個頁面的形式展示。
          • attachment 消息體應該被下載到本地,將參數filename的值預填為下載后的文件名

          因此當我們希望該資源被直接下載時候,我們可以設置返回頭Content-Disposition的值為attachment。

          
              
          1. //example
          2. Content-Disposition: attachment; filename="fname.ext"

          這里設置名稱時候,要注意下filename的編碼格式。

          用戶自己在瀏覽器設置

          瀏覽器既然定義了該行為,根據瀏覽器的不同用戶可能在設置頁面去配置某些格式的文件是否希望瀏覽器去展示該文件。一些有爭議的情況下,你也可以提示用戶自己根據需求去設置這些參數。

          
          
          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 平面設計服務


          Javascrpit之打字機效果

          seo達人

          如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里

          今天來看看怎么實現炫酷的打字機效果。即把一段話一個字一個字的顯示出來。

          效果圖:

          實現思路:

          首先規定好顯示字數的速度即settimeout執行間隔用來控制每個字之間輸出速度。再把判斷段落的總字數,循環段落總字數來實現一個字一個字的輸出。

          js代碼:

          
              
          1. var theNewsNum;
          2. var theAddNum;
          3. var totalNum;
          4. var CurrentPosion=0;
          5. var theCurrentNews;
          6. var theCurrentLength;
          7. var theNewsText;
          8. var theTargetLink;
          9. var theCharacterTimeout;
          10. var theNewsTimeout;
          11. var theBrowserVersion;
          12. var theWidgetOne;
          13. var theWidgetTwo;
          14. var theSpaceFiller;
          15. var theLeadString;
          16. var theNewsState;
          17. function startTicker(){
          18. // ------ 設置初始數值
          19. theCharacterTimeout = 50;//字符間隔時間
          20. theNewsTimeout = 2000;//新聞間隔時間
          21. theWidgetOne = "_";//新聞前面下標符1
          22. theWidgetTwo = "-";//新聞前面下標符
          23. theNewsState = 1;
          24. theNewsNum = document.getElementById("incoming").children.AllNews.children.length;//新聞總條數
          25. theAddNum = document.getElementById("incoming").children.AddNews.children.length;//補充條數
          26. totalNum =theNewsNum+theAddNum;
          27. theCurrentNews = 0;
          28. theCurrentLength = 0;
          29. theLeadString = " ";
          30. theSpaceFiller = " ";
          31. runTheTicker();
          32. }
          33. // --- 基礎函數
          34. function runTheTicker(){
          35. if(theNewsState == 1){
          36. if(CurrentPosion<theNewsNum){
          37. setupNextNews();
          38. }
          39. else{
          40. setupAddNews();
          41. }
          42. CurrentPosion++;
          43. if(CurrentPosion>=totalNum||CurrentPosion>=1){
          44. CurrentPosion=0;//最多條數不超過num_gun條
          45. }
          46. }
          47. if(theCurrentLength != theNewsText.length){
          48. drawNews();
          49. }
          50. else{
          51. closeOutNews();
          52. }
          53. }
          54. // --- 跳轉下一條新聞
          55. function setupNextNews(){
          56. theNewsState = 0;
          57. theCurrentNews = theCurrentNews % theNewsNum;
          58. theNewsText = document.getElementById("AllNews").children[theCurrentNews].children.Summary.innerText;
          59. theTargetLink = document.getElementById("AllNews").children[theCurrentNews].children.Summary.children[0].href;
          60. theCurrentLength = 0;
          61. document.all.hottext.href = theTargetLink;
          62. theCurrentNews++;
          63. }
          64. function setupAddNews() {
          65. theNewsState = 0;
          66. theCurrentNews = theCurrentNews % theAddNum;
          67. theNewsText = document.getElementById("AllNews").children[theCurrentNews].children.Summary.innerText;
          68. theTargetLink = document.getElementById("AllNews").children[theCurrentNews].children.Summary.children[0].href;
          69. theCurrentLength = 0;
          70. document.all.hottext.href = theTargetLink;
          71. theCurrentNews++;
          72. }
          73. // --- 滾動新聞
          74. function drawNews(){
          75. var myWidget;
          76. if((theCurrentLength % 2) == 1){
          77. myWidget = theWidgetOne;
          78. }
          79. else{
          80. myWidget = theWidgetTwo;
          81. }
          82. document.all.hottext.innerHTML = theLeadString + theNewsText.substring(0,theCurrentLength) + myWidget + theSpaceFiller;
          83. theCurrentLength++;
          84. setTimeout("runTheTicker()", theCharacterTimeout);
          85. }
          86. // --- 結束新聞循環
          87. function closeOutNews(){
          88. document.all.hottext.innerHTML = theLeadString + theNewsText + theSpaceFiller;
          89. theNewsState = 1;
          90. setTimeout("runTheTicker()", theNewsTimeout);
          91. }
          92. window.onload=startTicker;
          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務

          DOM常見的操作方式有哪些

          seo達人

          如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里

          1.什么是DOM

          DOM 是 Document Object Model(文檔對象模型)的縮寫。


          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 是屬性值


          4.訪問元素的方法



          通過使用 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.參考文獻



          8.更多討論

          問題1:getElementsByClassName() 使用時需要注意的地方

          回答:它取出來的是個數組,及時只有一個那也是數組對象,所以改變指定元素時需使用角標

          問題2:innerHTML 和innerText的區別

          回答:innerText替換是會將標簽替換成字符串,而innerHTML 則會保留標簽插入到節點當中

          問題3:dom事件

          回答:事件是文檔或者瀏覽器窗口中發生的,特定的交互瞬間。事件是用戶或瀏覽器自身執行的某種動作,如click,load和mouseover都是事件的名字。事件是javaScript和DOM之間交互的橋梁。

          事件發生,調用它的處理函數執行相應的JavaScript代碼給出響應。


          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務




          HTML簡單知識的總結

          seo達人

          如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里

          基本格式:

          <!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>    默認在當前瀏覽器窗口打開,添加targetblank  在新的瀏覽器窗口打開。

          <mailto>  在網頁中鏈接Email 地址。  <a href=”mailto:  yy@qq。com ?

          Cc抄送地址=zsq@qq。com  &  bcc密件抄送地址=zjj@qqcom  &

          subject=”主題”  &  body=“郵件內容”>發送</a> 給多個收件人發送,用分號隔開。第一個參數用?開頭,之后用 &隔開。 

          <img> 添加圖片。Src=”標識圖像的位置?!?alt=”指定圖像的描述性文本,當圖像不可見時(下載不成功時),可看到該屬性指定的文本”

          Title=“提供在圖像可見時對圖像的描述(鼠標滑過圖片時顯示的文本)”

          <form>  表單標簽,與用戶交互使得瀏覽器可以處理用戶的數據。

          <form  method=”數據傳送的方式get/postaction=”瀏覽器輸入的數據被傳送到的地方,如一個 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 spanwarning{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界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務




          vue-router的使用方法介紹input框的23種類型

          seo達人

          如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里

          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:文本

          代碼:

          [html] view plain copy
          1. <input type="text" />  

          效果:

          注意:當input沒有填寫類型時,默認為文本類型。

          [html] view plain copy
          1. <input />  


          ▍password:密碼

          代碼:

          [html] view plain copy
          1. <input type="password" />  

          效果:


          ▍number:數字

          代碼:

          [html] view plain copy
          1. <input type="number" />  

          效果:


          ▍button:按鈕

          代碼:

          [html] view plain copy
          1. <input type="button" value="我是按鈕" />  

          效果:


          ▍tel:電話

          代碼:

          [html] view plain copy
          1. <input type="tel" />  

          效果:

          注意:tel類型似乎沒有什么實際作用。


          ▍email:郵件

          代碼:

          [html] view plain copy
          1. <input type="email" />  

          效果:

          注意:火狐對email類型有校驗,360瀏覽器無校驗。


          ▍file:文件

          代碼:

          [html] view plain copy
          1. <input type="file" />  

          效果:


          ▍range:滑動條

          代碼:

          [html] view plain copy
          1. <input type="range" />  

          效果:


          ▍date:日期

          代碼:

          [html] view plain copy
          1. <input type="date" />  

          效果:


          ▍month:月份

          代碼:

          [html] view plain copy
          1. <input type="month" />  

          效果:


          ▍week:周

          代碼:

          [html] view plain copy
          1. <input type="week" />  

          效果:


          ▍time:時間

          代碼:

          [html] view plain copy
          1. <input type="time" />  

          效果:


          ▍datetime:時間、日、月、年(UTC時間)

          代碼:

          [html] view plain copy
          1. <input type="datetime" />  

          效果:

          注意:火狐、360瀏覽器都對datetime不支持,會按照text類型處理。


          datetime-local:時間、日、月、年(本地時間)

          代碼:

          [html] view plain copy
          1. <input type="datetime-local" />  

          效果:


          ▍radio:單選框

          代碼:

          [html] view plain copy
          1. <input type="radio" name="man" id="man" value="man"/><label for="man"></label>  
          2. <input type="radio" name="man" id="women" value="woman"/><label for="woman"></label>  

          效果:


          ▍checkbox:復選框

          代碼:

          [html] view plain copy
          1. <input type="checkbox" name="interest" value="run" id="run" /><label for="run">跑步</label>  
          2. <input type="checkbox" name="interest" value="guitar" id="guitar" /><label for="guitar">吉他</label>  
          3. <input type="checkbox" name="interest" value="yoga" id="yoga" /><label for="yoga">瑜伽</label>  
          4. <input type="checkbox" name="interest" value="read" id="read" /><label for="read">閱讀</label>  

          效果:


          ▍image:圖片

          代碼:

          [html] view plain copy
          1. <input type="image" src="http://p0.so.qhimgs1.com/bdr/_240_/t01cbdeda95800117ac.jpg" />  

          效果:


          ▍color:顏色

          代碼:

          [html] view plain copy
          1. <input type="color" />  

          效果:


          ▍search:搜索框

          代碼:

          [html] view plain copy
          1. <input type="search" />  

          效果:

          注意:search似乎與text的效果沒有什么區別。。。


          ▍reset:重置按鈕

          代碼:

          [html] view plain copy
          1. <input type="reset" />  

          效果:

          注意:reset按鈕一般用于form表單中。


          ▍submit:提交按鈕

          代碼:

          [html] view plain copy
          1. <input type="submit" />  

          效果:

          注意:submit按鈕一般用于form表單中


          ▍hidden:隱藏

          代碼:

          [html] view plain copy
          1. <input type="hidden" />  

          效果:


          注意:hidden類型會將input隱藏,所以什么都看不到,而且被隱藏的input框也不會占用空間。


          ▍url:路徑

          代碼:

          [html] view plain copy
          1. <input type="tel" />  

          效果:

          注意:火狐對url類型有校驗,360瀏覽器無校驗。


          ▍寫在結尾

          總的來說,目前input框也就只有這23種類型,雖然有的類型可能用不上一兩次甚至是一次都用不上,但是了解一下還是不錯的。



          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 平面設計服務




          vue-router的使用方法介紹

          seo達人

          如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里

          vue-router

          對于大多數單頁面應用,都推薦使用官方支持的 vue-router 庫。

          學習網址:https://router.vuejs.org/installation.html#direct-download-cdn

          提示:本篇博客僅僅介紹搭建項目之后,再下載vue-router的情況,并非搭建項目是直接引入vue-router。

          一、安裝方法(npm方式)

          在終端運行以下指令

          [html] view plain copy
          1. npm install vue-router  

          注意:--save 與 --save-dev 的區別

          --save(可以省略) 下載的第三方依賴到package.js中的dependencies。

          --save-dev 下載開發時依賴,指環境配置,下載到package.js中的devDependencies,webpack、bable等等均屬于開發

          時依賴。

          二、導入與使用

          vue-router下載之后,需要在入口文件main.js導入,具體做法如下:

          [javascript] view plain copy
          1. Vue.use(VueRouter);  
          2. Vue.use(VueAxios, axios);  
          3.   
          4. // routes:數組,在該數組中配置所有的路由;  
          5. const routes = [  
          6.   {path:'/',component:myHome,name:'home'},  
          7.   {path:'/product/:productName/:price',component:myProduct,name:'product'}  
          8. ];  
          9. // 創建router實例  
          10. const router = new VueRouter({  
          11.   routes  
          12. });  
          13. /* eslint-disable no-new */  
          14. new Vue({  
          15.   el: '#app',  
          16.   // 引入到根實例中才可以使用導航功能  
          17.   router,  
          18.   components: {App},  
          19.   template: '<App/>',  
          20.   data(){  
          21.     return {  
          22.   
          23.     }  
          24.   }  
          25. })  

          三、官網介紹使用步驟

          網址:https://router.vuejs.org/zh/guide/#javascript

          [javascript] view plain copy
          1. // 0. 如果使用模塊化機制編程,導入Vue和VueRouter,要調用 Vue.use(VueRouter)  
          2.   
          3. // 1. 定義 (路由) 組件。  
          4. // 可以從其他文件 import 進來  
          5. const Foo = { template: '<div>foo</div>' }  
          6. const Bar = { template: '<div>bar</div>' }  
          7.   
          8. // 2. 定義路由  
          9. // 每個路由應該映射一個組件。 其中"component" 可以是  
          10. // 通過 Vue.extend() 創建的組件構造器,  
          11. // 或者,只是一個組件配置對象。  
          12. // 我們晚點再討論嵌套路由。  
          13. const routes = [  
          14.   { path: '/foo', component: Foo },  
          15.   { path: '/bar', component: Bar }  
          16. ]  
          17.   
          18. // 3. 創建 router 實例,然后傳 `routes` 配置  
          19. // 你還可以傳別的配置參數, 不過先這么簡單著吧。  
          20. const router = new VueRouter({  
          21.   routes // (縮寫) 相當于 routes: routes  
          22. })  
          23.   
          24. // 4. 創建和掛載根實例。  
          25. // 記得要通過 router 配置參數注入路由,  
          26. // 從而讓整個應用都有路由功能  
          27. const app = new Vue({  
          28.   router  
          29. }).$mount('#app')  
          30.   
          31. // 現在,應用已經啟動了!  

          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務




          日歷

          鏈接

          個人資料

          藍藍設計的小編 http://www.syprn.cn

          存檔

          亚洲va欧美va天堂v国产综合