react-native 爲本地js和開源庫的js編寫.d.ts聲明文件

讀書不覺已春深 !明日清明節
在使用Typescript編寫程序RN過程中遇到困擾,且不論react,不論在瀏覽器中,只論寫react-native的APP,怎麼使用 declare聲明文件namespace命名空間編寫滿意的程序。
因不能在網上找到合適的資源,以至於寫該博客準備了久久近2周。

在編寫Typescript語言下的react-native時,拋出 3 個問題

1,rn 中怎麼使用第三方Javascript開源庫 ?
2,rn 中怎麼使用 global全局變量 ?
3,rn 中怎麼使用自己本地編寫的Javascript ?

react-native 中安裝並使用Javascript開源庫 react-native-ui-lib

在這裏插入圖片描述
安裝該UI庫 react-native-ui-lib,需要安裝相應的上述依賴

npm i react-native-ui-lib

@react-native-community/blur
@react-native-community/netinfo
@react-native-community/datetimepicker
react-native-reanimated

安裝成功之後,在文檔中會看到只能使用在Javascript語言的react-native中。能使用在Typescript語言中, 有爲該開源庫編寫**.d.ts聲明文件。然後使用時會報找不到No overload matches this call.但是由於該開源庫已經具有聲明文件,所以時可以使用的。
爲換一種方式使用,以方便描述怎麼在本地編寫聲明文件。我在本地爲組件重新編寫了聲明組件,詳情解析請點擊下一篇
接下來要使用 react-native-ui-lib 就需要爲其手動編寫聲明文件了。網絡上有很多關於Jquery的聲明文件編寫。但不是應用在react-native中,且無法貼切表達rn中應如何的編寫與使用聲明文件,畢竟環境不同,畢竟本人不太專業Web端 。故此,研究了好久終有所突破並於此分享出來~

按照文檔編寫下方js文件

// */libs/components/FoundationConfig.js  (第一步)
import {Colors, Typography, Spacings} from 'react-native-ui-lib';

Colors.loadColors({
  primaryColor: '#2364AA',
  secondaryColor: '#81C3D7',
  textColor: '##221D23',
  errorColor: '#E63B2E',
  successColor: '#ADC76F',
  warnColor: '##FF963C'
});

Typography.loadTypographies({
  heading: {fontSize: 36, fontWeight: '600'},
  subheading: {fontSize: 28, fontWeight: '500'},
  body: {fontSize: 18, fontWeight: '400'},
});

Spacings.loadSpacings({
  page: 20,
  card: 12,
  gridGutter: 16
});
// */libs/components/ComponentsConfig.js  (第二步)
import {ThemeManager} from 'react-native-ui-lib';

// with plain object
ThemeManager.setComponentTheme('Card', {
  borderRadius: 8
});

// with a dynamic function
ThemeManager.setComponentTheme('Button', (props, context) => {
  // 'square' is not an original Button prop, but a custom prop that can
  // be used to create different variations of buttons in your app
  if (props.square) {
    return {
      borderRadius: 0
    };
  }
});
// */libs/components/MyScreen.js  (第三步)
import React, {Component} from 'react';
import {View, Text, Card, Button} from 'react-native-ui-lib';

class MyScreen extends Component {
  render() {
    return (
      <View flex padding-page>
        <Text heading marginB-s4>My Screen</Text>
        <Card height={100} center padding-card marginB-s4>
          <Text body>This is an example card </Text>
        </Card>
        
        <Button label="Button" body bg-primaryColor square></Button>
      </View>
    );
  }
}

export default MyScreen;

使用重點,編寫以下 聲明文件

// */libs/components/MyScreen.d.js  (第四步:創建聲明文件提供 *.tsx 使用)
import React, {Component} from 'react';

declare class MyScreen extends Component {}

export default MyScreen;

在react-native中的*.tsx文件中,使用已聲明過的Javascript文件

//第五步 *.tsx 文件中使用Javascript程序
// */screens/OnlineContact.tsx
import React from 'react';
import {
  StyleSheet,
  View,
  Text,
  Image,
} from 'react-native';
import { TouchableOpacity } from 'react-native-gesture-handler';
import DeviceConfs from '../confs/DeviceConfs';
import ImgConfs from '../../src/confs/ImgConfs';
import StringChecker from '../libs/js-module/jsmodule';
import MyScreen from '../libs/components/MyScreen';


interface OnlineContactProps {
  id: string;
  schecker: StringChecker;
}
interface OnlineContactState {
  tabIndex: number;
}
export default class OnlineContact extends React.Component<OnlineContactProps, OnlineContactState>{

  schecker = new StringChecker();
  constructor(props: OnlineContactProps){
    super(props);
    this.state = {
      tabIndex: 0
    }
  }
  
  render(){
    
    return <View style={{flex:1, alignItems:'center', backgroundColor: 'white'}}>
      {/* 標題欄 */}
        <View style={{width: DeviceConfs.sWidth, height: 42, 
            flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between'}}>
            <TouchableOpacity onPress={()=>{this.props.navigation.pop()}} activeOpacity = {0.8}
              style={{flexDirection:'row', alignItems: 'center', width:DeviceConfs.sWidth * 0.3}}>
              <Image source={ImgConfs.ic_goback} resizeMode={'contain'} 
              style={{width: 38, height: 38}}/>
              <Text style={{color: '#444', fontWeight: 'bold', fontSize: 14, alignSelf: 'center', marginLeft: -6}}>{'返回'}</Text>
            </TouchableOpacity>
          <View style={{width:DeviceConfs.sWidth * 0.3, alignItems: 'center', justifyContent:'center'}}>
            <Text style={{color: '#333', fontWeight: 'bold', fontSize: 18}}>{'TS功能測試'}</Text>
          </View>
          <View style={{width:DeviceConfs.sWidth * 0.3}}/>
        </View>
        <View style={{height:4, width: DeviceConfs.sWidth, backgroundColor: '#f4f4f4'}}/>

        {/* 寫入測試的代碼 */}
        
        {/* 自定義聲明文件使用第三方庫的js */}
        <View style= {{width:DeviceConfs.sWidth, height: DeviceConfs.sHeight ,
            padding: 30 ,justifyContent: 'center'}}>
            <MyScreen />
        </View>

      </View>
  }
}

效果展示
在這裏插入圖片描述

react-native 中使用 global全局變量

Javascript中的RN有使用 global全局變量的方式,當然Typescript的RN也有自己使用global全局變量的方式 。

Javascript語言中的全局變量配置方式
Typescript語言下的全局配置,則需要通過編寫聲明文件*.d.ts使用到全局變量的擴展方式。比如一下擴展全局變量手機尺寸,寬和高。

// */types/index.d.ts
// Prop Types
export {};

declare global {

    var gHeight: string | number;
    var gWidth: string | number;
}

export {}; 此行代碼必不可少,使當前全局聲明成爲module聲明。
聲明文件書寫完畢之後,聲明文件中是不允許具體實現的。所以需要對在新聲明的全局變量在APP起始頁進行賦值。

// */AppContainer.tsx   (APP起始頁.tsx的組件容器)
const sWidth = Dimensions.get('window').width;
const sHeight = Dimensions.get('window').height;
class AppContainer extends React.Component<AppProps> {
  constructor(props: AppProps){
    super(props);
    //配置全局變量-初始化
    gHeight = sHeight;
    gWidth = sWidth;
  }
  ... ...

應用到頁面中,比如 .tsx 測試頁面

// */screens/OnlineContact.tsx
import React from 'react';
import {
  View,
  Text,
  Image,
} from 'react-native';
import { TouchableOpacity } from 'react-native-gesture-handler';
import DeviceConfs from '../confs/DeviceConfs';
import ImgConfs from '../../src/confs/ImgConfs';
import StringChecker from '../libs/js-module/jsmodule';


interface OnlineContactProps {
  id: string;
  schecker: StringChecker;
}
interface OnlineContactState {
  tabIndex: number;
}
export default class OnlineContact extends React.Component<OnlineContactProps, OnlineContactState>{

  schecker = new StringChecker();
  constructor(props: OnlineContactProps){
    super(props);
    this.state = {
      tabIndex: 0
    }
  }
  
  render(){
    
    return <View style={{flex:1, alignItems:'center', backgroundColor: 'white'}}>
      {/* 標題欄 */}
        <View style={{width: DeviceConfs.sWidth, height: 42, 
            flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between'}}>
            <TouchableOpacity onPress={()=>{this.props.navigation.pop()}} activeOpacity = {0.8}
              style={{flexDirection:'row', alignItems: 'center', width:DeviceConfs.sWidth * 0.3}}>
              <Image source={ImgConfs.ic_goback} resizeMode={'contain'} 
              style={{width: 38, height: 38}}/>
              <Text style={{color: '#444', fontWeight: 'bold', fontSize: 14, alignSelf: 'center', marginLeft: -6}}>{'返回'}</Text>
            </TouchableOpacity>
          <View style={{width:DeviceConfs.sWidth * 0.3, alignItems: 'center', justifyContent:'center'}}>
            <Text style={{color: '#333', fontWeight: 'bold', fontSize: 18}}>{'TS功能測試'}</Text>
          </View>
          <View style={{width:DeviceConfs.sWidth * 0.3}}/>
        </View>
        <View style={{height:4, width: DeviceConfs.sWidth, backgroundColor: '#f4f4f4'}}/>

        {/* 寫入測試的代碼 */}
        
        {/* 自定義聲明文件擴展全局變量 */}
        <View style= {{width:DeviceConfs.sWidth, height: DeviceConfs.sHeight ,
            padding: 30 ,alignItems: 'center'}}>
              <Text style={{fontSize: 16, color: 'red', alignSelf: 'flex-start'}}>
              {'自寫聲明文件 擴展全局變量:'}{'\n'}{'手機高度:'}{gHeight}{'\n手機寬度:'}{gWidth}
              </Text>
        </View>

      </View>
  }
}

效果展示
在這裏插入圖片描述

react-native使用自編寫的Javascript文件

舉例兩種 —— class類的文件、variable和function的文件
編寫本地的Javascript文件 —— 類class

// */namesp/ZipCodeValidator.js
// const numberRegexp = /^[0-9]+$/;
export default class ZipCodeValidator {
    isAcceptable(s) {
        
        return "ZipCodeValidator - 使用export namespace 聲明文件";
    }
}
// */namesp/ZipCodeValidator.js
import ZipCodeValidator from "./ZipCodeValidator";

// const lettersRegexp = /^[A-Za-z]+$/;
class LettersOnlyValidator {
    isAcceptable(s) {
        return "LettersOnlyValidator - 使用export namespace 聲明文件";
    }
}
LettersOnlyValidator.ZipCodeValidator = ZipCodeValidator;
export default LettersOnlyValidator;

編寫聲明文件,爲提供給 Ts 使用


// */namesp/LettersOnlyValidator.d.ts
declare class LettersOnlyValidator{
    isAcceptable(s?: string): string;
}
 
declare namespace LettersOnlyValidator {
    export class ZipCodeValidator{
        isAcceptable(s?: string): string|boolean;
    }
}
export default LettersOnlyValidator;

*.tsx文件中使用Javascript文件

// */screens/OnlineContact.tsx
import React from 'react';
import {
  View,
  Text,
  Image,
} from 'react-native';
import { TouchableOpacity } from 'react-native-gesture-handler';
import DeviceConfs from '../confs/DeviceConfs';
import ImgConfs from '../../src/confs/ImgConfs';
import StringChecker from '../libs/js-module/jsmodule';
import LettersOnlyValidator from '../libs/namesp/LettersOnlyValidator';

interface OnlineContactProps {
  id: string;
  schecker: StringChecker;
}
interface OnlineContactState {
  tabIndex: number;
}
export default class OnlineContact extends React.Component<OnlineContactProps, OnlineContactState>{

  schecker = new StringChecker();
  constructor(props: OnlineContactProps){
    super(props);
    this.state = {
      tabIndex: 0
    }
  }
  
  render(){
    
    return <View style={{flex:1, alignItems:'center', backgroundColor: 'white'}}>
      {/* 標題欄 */}
        <View style={{width: DeviceConfs.sWidth, height: 42, 
            flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between'}}>
            <TouchableOpacity onPress={()=>{this.props.navigation.pop()}} activeOpacity = {0.8}
              style={{flexDirection:'row', alignItems: 'center', width:DeviceConfs.sWidth * 0.3}}>
              <Image source={ImgConfs.ic_goback} resizeMode={'contain'} 
              style={{width: 38, height: 38}}/>
              <Text style={{color: '#444', fontWeight: 'bold', fontSize: 14, alignSelf: 'center', marginLeft: -6}}>{'返回'}</Text>
            </TouchableOpacity>
          <View style={{width:DeviceConfs.sWidth * 0.3, alignItems: 'center', justifyContent:'center'}}>
            <Text style={{color: '#333', fontWeight: 'bold', fontSize: 18}}>{'TS功能測試'}</Text>
          </View>
          <View style={{width:DeviceConfs.sWidth * 0.3}}/>
        </View>
        <View style={{height:4, width: DeviceConfs.sWidth, backgroundColor: '#f4f4f4'}}/>

        {/* 寫入測試的代碼 */}
        
        {/* 自定義聲明文件使用本地js */}
        <View style= {{width:DeviceConfs.sWidth, height: DeviceConfs.sHeight ,
            padding: 30 ,alignItems: 'center'}}>
              <Text style={{fontSize: 16, color: 'red', alignSelf: 'flex-start'}}>
              {'自寫聲明文件 使用本地編寫的Javascript:'}{'\n'}{new LettersOnlyValidator.ZipCodeValidator().isAcceptable()}
              </Text>
        </View>

      </View>
  }
}

效果展示
在這裏插入圖片描述

編寫本地的Javascript文件 —— variable和function

// */js-module/jsvariable.js
export const httpurl = 'https://www.baidu.com/';

export function watchTV(){
  console.log('我在看電視 呢?!');
  let status = '給我把電視 打開 ~';
  return status;
}

編寫聲明文件,爲提供給 Ts 使用

// */js-module/jsvariable.d.ts
declare const httpurl: string;
declare function watchTV(): string;

export {httpurl, watchTV}

*.tsx文件中使用Javascript文件

// */screens/OnlineContact.tsx
import React from 'react';
import {
  View,
  Text,
  Image,
} from 'react-native';
import { TouchableOpacity } from 'react-native-gesture-handler';
import DeviceConfs from '../confs/DeviceConfs';
import ImgConfs from '../../src/confs/ImgConfs';
import StringChecker from '../libs/js-module/jsmodule';
import LettersOnlyValidator from '../libs/namesp/LettersOnlyValidator';
import {httpurl, watchTV} from '../libs/js-module/jsvariable';

interface OnlineContactProps {
  id: string;
  schecker: StringChecker;
}
interface OnlineContactState {
  tabIndex: number;
}
export default class OnlineContact extends React.Component<OnlineContactProps, OnlineContactState>{

  schecker = new StringChecker();
  constructor(props: OnlineContactProps){
    super(props);
    this.state = {
      tabIndex: 0
    }
  }
  
  render(){
    
    return <View style={{flex:1, alignItems:'center', backgroundColor: 'white'}}>
      {/* 標題欄 */}
        <View style={{width: DeviceConfs.sWidth, height: 42, 
            flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between'}}>
            <TouchableOpacity onPress={()=>{this.props.navigation.pop()}} activeOpacity = {0.8}
              style={{flexDirection:'row', alignItems: 'center', width:DeviceConfs.sWidth * 0.3}}>
              <Image source={ImgConfs.ic_goback} resizeMode={'contain'} 
              style={{width: 38, height: 38}}/>
              <Text style={{color: '#444', fontWeight: 'bold', fontSize: 14, alignSelf: 'center', marginLeft: -6}}>{'返回'}</Text>
            </TouchableOpacity>
          <View style={{width:DeviceConfs.sWidth * 0.3, alignItems: 'center', justifyContent:'center'}}>
            <Text style={{color: '#333', fontWeight: 'bold', fontSize: 18}}>{'TS功能測試'}</Text>
          </View>
          <View style={{width:DeviceConfs.sWidth * 0.3}}/>
        </View>
        <View style={{height:4, width: DeviceConfs.sWidth, backgroundColor: '#f4f4f4'}}/>

        {/* 寫入測試的代碼 */}
        
        {/* 自定義聲明文件使用本地js */}
        <View style= {{width:DeviceConfs.sWidth, height: DeviceConfs.sHeight ,
            padding: 30 ,alignItems: 'center'}}>
              <Text style={{fontSize: 16, color: 'red', alignSelf: 'flex-start'}}>
              {'自寫聲明文件 使用本地編寫的Javascript:'}{'\n'}{httpurl}{'\n'}{watchTV()}
              </Text>
        </View>

      </View>
  }
}

效果展示
在這裏插入圖片描述
後續有關聲明文件的如何編寫,請點擊下一篇 ~

文章參考:
https://ts.xcatliu.com/basics/declaration-files
https://zhongsp.gitbooks.io/typescript

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章