mirror of
https://github.com/lainbo/component-party.git
synced 2026-04-05 13:09:03 +08:00
0d86a8aa35a37c22633c82a4d17650f769286a04
Component Party
Reactivity
Variable assignment
React
import { useState } from 'react';
export default function Name() {
const [name, setName] = useState(0);
setName('Jane');
console.log(name);
}
Svelte
<script>
let name = 'John';
name = 'Jane';
console.log(name);
</script>
Vue 3
<script setup>
import { ref } from 'vue';
const name = ref('John');
name.value = 'Jane';
console.log(name.value);
</script>
Computed
React
import { useState, useMemo } from 'react';
export default function DoubleCount() {
const [count] = useState(0);
const doubleCount = useMemo(() => count * 2, [count]);
console.log(doubleCount);
return <div />;
}
Svelte
<script>
let count = 10;
$: doubleCount = count * 2;
console.log(doubleCount);
</script>
Vue 3
<script setup>
import { ref, computed } from 'vue';
const count = ref(10);
const doubleCount = computed(() => count.value * 2);
console.log(doubleCount.value);
</script>
<div />
Templating
Minimal
React
export default function HelloWorld() {
return <h1>Hello world</h1>;
}
Svelte
<h1>Hello world</h1>
Vue 3
<template>
<h1>Hello world</h1>
</template>
Styling
React
export default function HelloWorld() {
// how do you declare title class ??
return (
<>
<h1 className="title">Hello world</h1>
<button style={{ 'font-size': '10rem' }}>I am a button</button>
</>
);
}
Svelte
<template>
<h1 class="title">Hello world</h1>
<button style="font-size: 10rem;">I am a button</button>
</template>
<style>
.title {
color: red;
}
</style>
Vue 3
<template>
<h1 class="title">
Hello world
</h1>
<button style="font-size: 10rem">
I am a button
</button>
</template>
<style scoped>
.title {
color: red;
}
</style>
Loop
React
export default function Countries() {
const countries = ['France', 'United States', 'Spain'];
return (
<ul>
{countries.map((country) => (
<li key={country}>{country}</li>
))}
</ul>
);
}
Svelte
<script>
const countries = ['France', 'United States', 'Spain'];
</script>
<ul>
{#each countries as country}
<li>{country}</li>
{/each}
</ul>
Vue 3
<script setup>
const countries = ['France', 'United States', 'Spain'];
</script>
<template>
<ul>
<li
v-for="country in countries"
:key="country"
>
{{ country }}
</li>
</ul>
</template>
Event click
React
import { useState } from 'react';
export default function Name() {
const [count, setCount] = useState(0);
function incrementCount() {
setCount(count + 1);
}
return (
<>
<p>Counter: {count}</p>
<button onClick={incrementCount}>+1</button>
</>
);
}
Svelte
<script>
let count = 0;
function incrementCount() {
count += 1;
}
</script>
<p>Counter: {count}</p>
<button on:click={incrementCount}>+1</button>
Vue 3
<script setup>
import { ref } from 'vue';
const count = ref(0);
function incrementCount() {
count.value = count.value + 1;
}
</script>
<template>
<p>Counter: {{ count }}</p>
<button @click="incrementCount">
+1
</button>
</template>
Dom ref
React
import { useState, useEffect } from 'react';
export default function PageTitle() {
const [pageTitle, setPageTitle] = useState('');
useEffect(() => {
setPageTitle(document.title);
});
return <p>Page title is {pageTitle}</p>;
}
Svelte
<script>
import { onMount } from 'svelte';
let inputElement;
onMount(() => {
inputElement.focus();
});
</script>
<input bind:this={inputElement} />
Vue 3
<script setup>
import { ref, onMounted } from 'vue';
const inputElement = ref();
onMounted(() => {
inputElement.value.focus();
});
</script>
<input ref="inputElement" />
Conditional
React
import { useState, useMemo } from 'react';
const TRAFFIC_LIGHTS = ['red', 'orange', 'green'];
export default function TrafficLight() {
const [lightIndex, setLightIndex] = useState(0);
const light = useMemo(() => TRAFFIC_LIGHTS[lightIndex], [lightIndex]);
function nextLight() {
if (lightIndex + 1 > TRAFFIC_LIGHTS.length - 1) {
setLightIndex(0);
} else {
setLightIndex(lightIndex + 1);
}
}
return (
<>
<button onClick={nextLight}>Next light</button>
<p>Light is: {light}</p>
<p>
You must
{light === 'red' && <span>STOP</span>}
{light === 'orange' && <span>SLOW DOWN</span>}
{light === 'green' && <span>GO</span>}
</p>
</>
);
}
Svelte
<script>
const TRAFFIC_LIGHTS = ['red', 'orange', 'green'];
let lightIndex = 0;
$: light = TRAFFIC_LIGHTS[lightIndex];
function nextLight() {
if (lightIndex + 1 > TRAFFIC_LIGHTS.length - 1) {
lightIndex = 0;
} else {
lightIndex++;
}
}
</script>
<button on:click={nextLight}>Next light</button>
<p>Light is: {light}</p>
<p>
You must
{#if light === 'red'}
STOP
{:else if light === 'orange'}
SLOW DOWN
{:else if light === 'green'}
GO
{/if}
</p>
Vue 3
<script setup>
import { ref, computed } from 'vue';
const TRAFFIC_LIGHTS = ['red', 'orange', 'green'];
const lightIndex = ref(0);
const light = computed(() => TRAFFIC_LIGHTS[lightIndex]);
function nextLight() {
if (lightIndex.value + 1 > TRAFFIC_LIGHTS.length - 1) {
lightIndex.value = 0;
} else {
lightIndex.value++;
}
}
</script>
<template>
<button @click="nextLight">
Next light
</button>
<p>Light is: {{ light }}</p>
<p>
You must
<span v-if="light === 'red'">STOP</span>
<span v-else-if="light === 'orange'">SLOW DOWN</span>
<span v-else-if="light === 'green'">GO</span>
</p>
</template>
Input binding
React
import { useState } from 'react';
export default function InputHello() {
const [text, setText] = useState('Hello world');
function handleChange(event) {
setText(event.target.value);
}
return (
<>
<p>{text}</p>
<input value={text} onChange={handleChange} />
</>
);
}
Svelte
<script>
let text = 'Hello World';
</script>
<p>{text}</p>
<input bind:value={text} />
Vue 3
<script setup>
import { ref } from 'vue';
const text = ref('Hello World');
</script>
<template>
<p>{{ text }}</p>
<input v-model="text">
</template>
Event modifier
Lifecycle
OnMount
React
import { useState, useEffect } from 'react';
export default function PageTitle() {
const [pageTitle, setPageTitle] = useState('');
useEffect(() => {
setPageTitle(document.title);
});
return <p>Page title: {pageTitle}</p>;
}
Svelte
<script>
import { onMount } from 'svelte';
let pageTitle = '';
onMount(() => {
pageTitle = document.title;
});
</script>
<p>Page title is: {pageTitle}</p>
Vue 3
<script setup>
import { ref, onMounted } from 'vue';
const pageTitle = ref('');
onMounted(() => {
pageTitle.value = document.title;
});
</script>
<template>
<p>Page title: {{ pageTitle }}</p>
</template>
OnUnmount
React
import { useState, useEffect } from 'react';
export default function Time() {
const [time, setTime] = useState(new Date().toLocaleTimeString());
const timer = setInterval(() => {
setTime(new Date().toLocaleTimeString());
}, 1000);
useEffect(() => {
return () => {
clearInterval(timer);
};
});
return <p>Current time: {time}</p>;
}
Svelte
<script>
import { onDestroy } from 'svelte';
let time = new Date().toLocaleTimeString();
const timer = setInterval(() => {
time = new Date().toLocaleTimeString();
}, 1000);
onDestroy(() => {
clearInterval(timer);
});
</script>
<p>Current time: {time}</p>
Vue 3
<script setup>
import { ref, onUnmounted } from 'svelte';
const time = ref(new Date().toLocaleTimeString());
const timer = setInterval(() => {
time.value = new Date().toLocaleTimeString();
}, 1000);
onUnmounted(() => {
clearInterval(timer);
});
</script>
<p>Current time: {time}</p>
Watcher
Component composition
Props
React
import { useState } from 'react';
import Hello from './Hello.jsx';
export default function App() {
const [username, setUsername] = useState('John');
function handleChange(event) {
setUsername(event.target.value);
}
return (
<>
<input value={username} onChange={handleChange} />
<Hello name={username} />
</>
);
}
import PropTypes from 'prop-types';
export default function Hello({ name }) {
return <p>Hello {name} !</p>;
}
Hello.propTypes = {
name: PropTypes.string.isRequired
};
Svelte
<script>
import Hello from './Hello.svelte';
let username = 'John';
</script>
<input bind:value={username} />
<Hello name={username} />
<script>
export let name;
</script>
<p>Hello {name} !</p>
Vue 3
<script setup>
import { ref } from 'vue';
import Hello from './Hello.vue';
const username = ref('John');
</script>
<template>
<input v-model="username">
<Hello :name="username" />
</template>
<script setup>
const props = defineProps({
name: {
type: String,
required: true
}
});
</script>
<template>
<p>Hello {{ props.name }} !</p>
</template>
Event
Slot
Slot named
Slot props
Event dom forwarding
Store context
Form inputs
Real usecase
Todolist
Fetch
Languages
TypeScript
50.7%
JavaScript
18.6%
Svelte
14%
HTML
7.5%
Vue
5%
Other
4.2%