+4

[Frontend] Tìm hiểu căn bản svelte - 1 framework phổ biến ngoài Angular, React, Vue

Hôm nay mình xin giới thiệu 1 framework(mình viết gọn: fw) của frontend là svelte (trang chủ: https://svelte.dev/tutorial/) - nó là 1 fw cũng nổi tiếng không kém cạnh gì React hay Angular, Vue.

Bài viết này mình chỉ xin giới thiệu 1 số nét căn bản của svelte (dưới góc nhìn của 1 người mới tìm hiểu), sau đó mình sẽ thử áp dụng viết 1 component căn bản

I > Bắt đầu tìm hiểu nào:

1> Cách khởi tạo 1 dự án đơn giản:

Cũng như các fw khác, cách khởi tạo qua npx rất đơn giản

npx degit sveltejs/template my-svelte-project
# or download and extract 
cd my-svelte-project
# to use  run:
# node scripts/setupTypeScript.js

npm install
npm run dev

2> Cách tạo 1 component:

Bạn tạo 1 file component có đuôi .svelte , ví dụ Button.svelte Cấu trúc của 1 component:

<script>

</script>

// Phần hmtl

<style>
</style>

Ví dụ mình muốn button hiển thị số lần click

<script>
	let count = 0;

	function handleClick() {
		count += 1;
	}
</script>

<button on:click={handleClick}>
	Clicked {count} {count === 1 ? 'time' : 'times'}
</button>

<style>
  button {
  background: gray;
  padding: 20px;
}
</style>

==> Khi gọi trong component khác:

<script>
	import Button from './Button.svelte';
</script>

<div>
  <Button></Button>
</div>

3> Props và state:

Sử dụng lại ví dụ trên, mình thêm 1 props name để hiển thị xem ai đã bấm

<script>
   // Props name
  export let name = "" // default props = ""
  
  // count là state
	let count = 0;

	function handleClick() {
		count += 1;
	}
</script>

<button on:click={handleClick}>
  {name}has	Clicked {count} {count === 1 ? 'time' : 'times'}
</button>

<style>
  button {
  background: gray;
  padding: 20px;
}
</style>

==> Khi gọi trong component khác:

<script>
	import Button from './Button.svelte';
</script>

<div>
  <Button name={"petter join"}></Button>
</div>

4> Template:

Tương tự như các fw khác như react định nghĩa ra jsx, svelte cũng định nghĩa ra bộ template của riêng nó

a> if - else:

{#if user.loggedIn}
<button on:click={toggle}>
  Log out
</button>
{/if}

hoặc if else

{#if user.loggedIn}
	<button on:click={toggle}>
		Log out
	</button>
{:else}
	<button on:click={toggle}>
		Log in
	</button>
{/if}

b> Loop with Each:

<ul>
	{#each cats as cat}
		<li><a target="_blank" href="https://www.youtube.com/watch?v={cat.id}">
			{cat.name}
		</a></li>
	{/each}
</ul>

hoặc

{#each things as thing (thing.id)}
	<Thing current={thing.color}/>
{/each}

d> async await:

{#await promise}
	<p>...waiting</p>
{:then number}
	<p>The number is {number}</p>
{:catch error}
	<p style="color: red">{error.message}</p>
{/await}

5> Event

  • Event dom: các bạn chỉ cần thêm tiền tố on: Ví dụ như ở ví dụ trước:
<button on:click={handleClick}>
  {name}has	Clicked {count} {count === 1 ? 'time' : 'times'}
</button>

hoặc với sự kiện mousemove

<div on:mousemove={handleMousemove}>
	The mouse position is {m.x} x {m.y}
</div>
  • Inline event:
<div on:mousemove="{e => m = { x: e.clientX, y: e.clientY }}">
	The mouse position is {m.x} x {m.y}
</div>

6> Other: Ngoài ra svelte còn có nhiều nội dung khác như lifecycle, data, router,animation,.. trong bài viết này mình chỉ giới thiệu 1 số nét căn bản. Các bạn tìm hiểu thêm tại trang chủ: https://svelte.dev/ và trang turiol : https://svelte.dev/tutorial/

II> Ví dụ: tạo 1 component đơn giản

Mình sẽ viết 1 component audio để custom lại thẻ audio mặc định.

Demo:

Đầu tiên mình sẽ tạo 1 file tên là Audio.svelte

<script>
export let src
let myAudio
let isLoading = true
let isPlay = false
let currentTime = 0

const endLoading = () => {
  // alert("done")
  isLoading = false
}

const onClickPlay = () => {
  console.log("play")
  isPlay = !isPlay
  if (isPlay) {
    myAudio.play()
  } else {
    myAudio.pause()
  }
}

const onEnd = () => {
  isPlay = falsesvelte
}

const startLoading = () => {
  isLoading = true
}

const onTimeUpdate = () => {
  currentTime = myAudio.currentTime
}

const formatData = () => {
  const timeInt = Math.floor(currentTime)
  const minute = Math.floor(timeInt / 60)
  const second = (timeInt - 60 * minute)

  return `${minute}:${second}`
}
</script>


<div class="player">
<!-- svelte-ignore a11y-media-has-caption -->
<audio controls={false}  on:loadstart={startLoading} on:loadedmetadata={endLoading} on:timeupdate={onTimeUpdate} on:ended={onEnd} bind:this={myAudio}>
  <source src={src}>
  Your browser does not support the audio element.
</audio>

<div class="avatar">
<img alt="" src="https://vcdn1-giaitri.vnecdn.net/2019/04/17/westlifet-1555487554-2581-1555487641.jpg?w=900&h=540&q=100&dpr=1&fit=crop&s=648KLjWO8NyX-qKtELFksg" />
</div>
<p class="time">{formatData(currentTime)}</p>
<div class="control">
<i class="fas fa-backward"></i>
<i class={isPlay ? "fas fa-pause play-icon" : "fas fa-play play-icon"} on:click={onClickPlay}></i>
<i class="fas fa-forward"></i>
</div>

{#if isLoading}
<p>isLoading....</p>
{/if}
</div>

<style>
.player {
  width: 100%;
}

.play-icon {
  margin: 5px 10px;
}

.time {
  width: 100%;
  text-align: center;
  margin: 5px 0 10px;
}

.avatar {
  width: 200px;
  height: 200px;
  border: solid 1px gray;
  border-radius: 50%;
  overflow: hidden;
  display: flex;
  justify-content: center;
  margin: auto;
  animation-name: spin;
  animation-duration: 5000ms;
  animation-iteration-count: infinite;
  animation-timing-function: linear;
}

@keyframes spin {
  from {
    transform:rotate(0deg);
  }
  to {
    transform:rotate(360deg);
  }
}


</style>

==> Khi sử dụng, truyền props vào tương ứng

<script>
	import Audio from './Audio.svelte'
</script>

<body>
	<Audio src="https://stitch-statichosting-prod.s3.amazonaws.com/5f646df5e75a6deba2991e77/5f1ec11789cec85775ae470b/audio1.mp3"/>
</body>

<style>

	body {
		width: 100%;
		height: 100vh;
		display: flex;
		align-items: center;
		justify-self: center;
		text-align: center;
		padding: 1em;
		margin: 0 auto;
		background-color: antiquewhite;
	}
</style>

Cảm ơn mọi người đã đọc bài viết của mình

III> Tham khảo:

Trang chủ:https://svelte.de

Turiol: ![] https://svelte.dev/tutorial/


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.