自從我在部落格上寫一篇技術文章以來已經有一段時間了,這是一篇關於使用 @shopify/restyle 和 expo 在 React Native 中建立類型強制 UI 元件的新文章。
@shopify/restyle 是一個強大的 React Native 樣式庫,可為您的 UI 元件帶來類型安全性和一致性。與傳統的樣式方法不同,Restyle 可讓您建立集中式主題配置,在整個應用程式中強制執行設計系統原則。
入門
項目設定
- 使用 expo 設定您的 React Native 項目
npx create-expo-app@latest
- 前往您的專案目錄並使用 expo 安裝 @shopify/restyle 套件
cd /path/to/project npx expo install @shopify/restyle
創建你的主題
建立 theme.tsx 檔案來定義您的設計系統:
touch theme.tsx
- 複製並貼上預設主題配置
import {createTheme} from '@shopify/restyle'; const palette = { purpleLight: '#8C6FF7', purplePrimary: '#5A31F4', purpleDark: '#3F22AB', greenLight: '#56DCBA', greenPrimary: '#0ECD9D', greenDark: '#0A906E', black: '#0B0B0B', white: '#F0F2F3', }; const theme = createTheme({ colors: { mainBackground: palette.white, cardPrimaryBackground: palette.purplePrimary, }, spacing: { s: 8, m: 16, l: 24, xl: 40, }, textVariants: { header: { fontWeight: 'bold', fontSize: 34, }, body: { fontSize: 16, lineHeight: 24, }, defaults: { // We can define a default text variant here. }, }, }); export type Theme = typeof theme; export default theme;
實施主題提供者
更新您的 app/_layout.tsx:
import { DarkTheme, DefaultTheme } from "@react-navigation/native"; import { useFonts } from "expo-font"; import { Stack } from "expo-router"; import * as SplashScreen from "expo-splash-screen"; import { StatusBar } from "expo-status-bar"; import { useEffect } from "react"; import "react-native-reanimated"; import { ThemeProvider } from "@shopify/restyle"; import theme from "@/theme"; // Prevent the splash screen from auto-hiding before asset loading is complete. SplashScreen.preventAutoHideAsync(); export default function RootLayout() { const [loaded] = useFonts({ SpaceMono: require("../assets/fonts/SpaceMono-Regular.ttf"), }); useEffect(() => { if (loaded) { SplashScreen.hideAsync(); } }, [loaded]); if (!loaded) { return null; } return ( <themeprovider theme="{theme}"> <stack> <stack.screen name="(tabs)" options="{{" headershown: false></stack.screen> <stack.screen name="+not-found"></stack.screen> </stack> <statusbar> <h2> Creating Reusable Components </h2> <h3> Text Component </h3> <pre class="brush:php;toolbar:false">touch components/Text.tsx
// In components/Text.tsx import {createText} from '@shopify/restyle'; import {Theme} from '../theme'; export const Text = createText<theme>(); </theme>
讓我們在主螢幕上使用它
import { Text } from "@/components/Text"; import { SafeAreaView } from "react-native-safe-area-context"; export default function HomeScreen() { return ( <safeareaview> <text margin="m" variant="header"> This is the Home screen. Built using @shopify/restyle. </text> </safeareaview> ); }
正如您在上面的程式碼中看到的,我們將邊距作為“m”而不是數字傳遞。我們從 theme.tsxfile 中取得值。
// ./theme.tsx const theme = createTheme({ spacing: { s: 8, m: 16, // margin="m" l: 24, xl: 40, }, textVariants: { header: { // our text header variant fontWeight: 'bold', fontSize: 34, }, body: { fontSize: 16, lineHeight: 24, }, }, // ...rest of code }, });
這就是我們的主頁視圖的外觀
骨架裝載機組件
讓我們建造一張骨架裝載機卡
touch components/SkeletonLoader.tsx
// components/SkeletonLoader.tsx import { BackgroundColorProps, createBox, createRestyleComponent, createVariant, spacing, SpacingProps, VariantProps, } from "@shopify/restyle"; import { Theme } from "@/theme"; import { View } from "react-native"; const Box = createBox<theme>(); type Props = SpacingProps<theme> & VariantProps<theme> & BackgroundColorProps<theme> & React.ComponentProps<typeof view>; const CardSkeleton = createRestyleComponent<props theme>([ spacing, createVariant({ themeKey: "cardVariants" }), ]); const SkeletonLoader = () => { return ( <cardskeleton variant="elevated"> <box backgroundcolor="cardPrimaryBackground" height="{20}" marginbottom="s" width="70%" overflow="hidden" borderradius='{"m"}'> </box> <box backgroundcolor="cardPrimaryBackground" height="{100}" marginbottom="s" width="90%" overflow="hidden" borderradius='{"m"}'> </box> <box backgroundcolor="cardPrimaryBackground" height="{50}" marginbottom="s" width="70%" overflow="hidden" borderradius='{"m"}'> </box> </cardskeleton> ); }; export default SkeletonLoader; </props></typeof></theme></theme></theme></theme>
- 我們從 @shopify/restyle 套件中建立一個新框作為預定義元件,這將是我們創建骨架框的方式
const Box = createBox<theme>(); </theme>
- 使用createStyleComponent建立一個新的CardSkeleton元件來建立自訂元件,我們傳遞了必須在theme.tsx檔案中定義的間距和cardVariants的道具
type Props = SpacingProps<theme> & VariantProps<theme> & BackgroundColorProps<theme> & React.ComponentProps<typeof view>; const CardSkeleton = createRestyleComponent<props theme>([ spacing, createVariant({ themeKey: "cardVariants" }), ]); </props></typeof></theme></theme></theme>
- 建立一個 SkeletonLoader 元件來渲染我們的 Skelton Card 元件
// components/SkeletonLoader.tsx export const SkeletonLoader = () => { return ( <cardskeleton variant="elevated"> <box backgroundcolor="cardPrimaryBackground" height="{20}" marginbottom="s" width="70%" overflow="hidden" borderradius='{"m"}'></box> <box backgroundcolor="cardPrimaryBackground" height="{100}" marginbottom="s" width="90%" overflow="hidden" borderradius='{"m"}'></box> <box backgroundcolor="cardPrimaryBackground" height="{50}" marginbottom="s" width="70%" overflow="hidden" borderradius='{"m"}'></box> </cardskeleton> ); };
我們還剩下一件事要使其正常工作,更新 theme.tsx 檔案以擁有 cardVariants
const theme = createTheme({ colors: { // Add Black Color to use it later on black: palette.black, }, // Add Border Radius Variants borderRadii: { s: 4, m: 10, l: 25, xl: 75, }, // Add Card Variants cardVariants: { elevated: { shadowColor: "black", shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.1, shadowRadius: 4, elevation: 3, borderRadius: "m", }, defaults: { padding: "m", borderRadius: "m", }, }, });
太棒了,但是讓我們為我們的組件添加動畫
// components/SkeletonLoader.tsx const ShimmerAnimation = () => { const shimmerTranslate = useRef(new Animated.Value(0)).current; useEffect(() => { Animated.loop( Animated.timing(shimmerTranslate, { toValue: 1, duration: 1500, useNativeDriver: true, }) ).start(); }, [shimmerTranslate]); const translateX = shimmerTranslate.interpolate({ inputRange: [0, 1], outputRange: [-300, 300], }); return ( <animated.view> <p>and let’s use it in our Skeleton Loader Component<br> </p> <pre class="brush:php;toolbar:false">// components/SkeletonLoader.tsx export const SkeletonLoader = () => { return ( <cardskeleton variant="elevated"> <box backgroundcolor="cardPrimaryBackground" height="{20}" marginbottom="s" width="70%" overflow="hidden" borderradius='{"m"}'> <shimmeranimation></shimmeranimation> </box> <box backgroundcolor="cardPrimaryBackground" height="{100}" marginbottom="s" width="90%" overflow="hidden" borderradius='{"m"}'> <shimmeranimation></shimmeranimation> </box> <box backgroundcolor="cardPrimaryBackground" height="{50}" marginbottom="s" width="70%" overflow="hidden" borderradius='{"m"}'> <shimmeranimation></shimmeranimation> </box> </cardskeleton> ); };
這是完整的組件程式碼:
// components/SkeletonLoader.tsx import { useEffect, useRef } from "react"; import { Animated } from "react-native"; import { BackgroundColorProps, createBox, createRestyleComponent, createVariant, spacing, SpacingProps, VariantProps, } from "@shopify/restyle"; import { Theme } from "@/theme"; import { View } from "react-native"; const Box = createBox<theme>(); const ShimmerAnimation = () => { const shimmerTranslate = useRef(new Animated.Value(0)).current; useEffect(() => { Animated.loop( Animated.timing(shimmerTranslate, { toValue: 1, duration: 1500, useNativeDriver: true, }) ).start(); }, [shimmerTranslate]); const translateX = shimmerTranslate.interpolate({ inputRange: [0, 1], outputRange: [-300, 300], }); return ( <animated.view> <p>Et voila, we made a skeleton loader card using @shopify/restyle using </p> <p><img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/173310152233378.jpg?x-oss-process=image/resize,p_40" class="lazy" alt="How to build type-enforced UI components in React Native using @shopify/restyle"></p> <h2> Support for dark mode </h2> <p>Let’s start with adding dark theme configuration, in your theme.tsxfile<br> </p> <pre class="brush:php;toolbar:false">// theme.tsx export const darkTheme: Theme = { ...theme, colors: { ...theme.colors, mainBackground: palette.white, cardPrimaryBackground: palette.purpleDark, greenPrimary: palette.purpleLight, }, textVariants: { ...theme.textVariants, defaults: { ...theme.textVariants.header, color: palette.purpleDark, }, },
透過將深色主題配置新增至我們的layout.tsx 檔案中來將其新增至我們的應用程式佈局
npx create-expo-app@latest
- 基於顏色模式,使用預設的淺色主題或在深色模式下使用 theme.tsx 檔案中定義的 darkTheme 配置
// app/_layout.tsx 從“@/theme”導入主題,{ darkTheme }; //...其餘程式碼 <themeprovider> <stack.screen name="(tabs)" options="{{" headershown: false></stack.screen> > <stack.screen name="未找到"></stack.screen> 堆疊> <p>這是深色和淺色模式。 </p> <p><img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/173310152340178.jpg?x-oss-process=image/resize,p_40" class="lazy" alt="How to build type-enforced UI components in React Native using @shopify/restyle"></p> <p><img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/173310152557660.jpg?x-oss-process=image/resize,p_40" class="lazy" alt="How to build type-enforced UI components in React Native using @shopify/restyle"></p> <p>瞧,我們成功地使用 @shopify/restyle 套件創建了類型強制的 UI 元件</p> <p>謝謝你:)</p> </themeprovider>
以上是如何使用 @shopify/restyle 在 React Native 中建立類型強制的 UI 元件的詳細內容。更多資訊請關注PHP中文網其他相關文章!

JavaScript字符串替換方法詳解及常見問題解答 本文將探討兩種在JavaScript中替換字符串字符的方法:在JavaScript代碼內部替換和在網頁HTML內部替換。 在JavaScript代碼內部替換字符串 最直接的方法是使用replace()方法: str = str.replace("find","replace"); 該方法僅替換第一個匹配項。要替換所有匹配項,需使用正則表達式並添加全局標誌g: str = str.replace(/fi

簡單JavaScript函數用於檢查日期是否有效。 function isValidDate(s) { var bits = s.split('/'); var d = new Date(bits[2] '/' bits[1] '/' bits[0]); return !!(d && (d.getMonth() 1) == bits[1] && d.getDate() == Number(bits[0])); } //測試 var

本文探討如何使用 jQuery 獲取和設置 DOM 元素的內邊距和外邊距值,特別是元素外邊距和內邊距的具體位置。雖然可以使用 CSS 設置元素的內邊距和外邊距,但獲取準確的值可能會比較棘手。 // 設定 $("div.header").css("margin","10px"); $("div.header").css("padding","10px"); 你可能會認為這段代碼很

本文探討了十個特殊的jQuery選項卡和手風琴。 選項卡和手風琴之間的關鍵區別在於其內容面板的顯示和隱藏方式。讓我們深入研究這十個示例。 相關文章:10個jQuery選項卡插件

發現十個傑出的jQuery插件,以提升您的網站的活力和視覺吸引力!這個精選的收藏品提供了不同的功能,從圖像動畫到交互式畫廊。讓我們探索這些強大的工具:相關文章:1

HTTP-Console是一個節點模塊,可為您提供用於執行HTTP命令的命令行接口。不管您是否針對Web服務器,Web Serv

本教程向您展示瞭如何將自定義的Google搜索API集成到您的博客或網站中,提供了比標準WordPress主題搜索功能更精緻的搜索體驗。 令人驚訝的是簡單!您將能夠將搜索限制為Y

當div內容超出容器元素區域時,以下jQuery代碼片段可用於添加滾動條。 (無演示,請直接複製到Firebug中) //D = document //W = window //$ = jQuery var contentArea = $(this), wintop = contentArea.scrollTop(), docheight = $(D).height(), winheight = $(W).height(), divheight = $('#c


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

SublimeText3漢化版
中文版,非常好用

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

Dreamweaver CS6
視覺化網頁開發工具

DVWA
Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中