Svelte完全初心者覚書

#はじめに

Reactばっかり学習していたので最近話題？のSvelteを学習してみました

Reactと比較してみました
間違ってることあったらすみません...

![svelte.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669792/39878dd8-22a9-4773-90c9-399e2db9544e.png)


##環境構築

```shell
$ npx degit sveltejs/template my-project
$ cd my-project
```

```shell
$ npm install 
```

npm install して　node_modulesをインストールします

### Vscodeの拡張機能をインストール

Svelte for Vscode　ってやつ

### ローカルサーバーの立ち上げ

```shell
$ npm run dev
```

![スクリーンショット 2020-12-12 15.24.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669792/537480e7-6657-e573-757a-8f991d76a166.png)

このドシンプルな画面が出たら準備完了
Reactみたいにくるくるしてほしい

#使ってみよう

###簡単な文字の代入と表示

####React

```App.jsx
 const App = () => {
  const [name,setName] = useState("ねこ")

 const handleClick =()=>{
  setName("いぬ")
 }

return(
  <div>
    <p>{text}</P>
    <button onClick={handleClick}>text change</button>
 </div>
 )
}
```

####Svelte

```javascript:App.svelte
<script>
	let name = "ねこ";

	const handleClick = () => {
		name = "犬";
	};
</script>

<main>
	<p>{name}</p>
	<button on:click={handleClick}>update-color</button>
</main>

```

めっちゃ簡単にかけるけどonClickがon:clickになるらしい...

###入力と表示

####React

```App.jsx
 const App = () => {
  const [name,setName] = useState("")

  const inputName = useCallback(
    (event) => {
      setName(event.target.value);
    },
    [setName]
  );

return(
  <div>
    <p>{name}</P>
    <input 
      value={name}
      type={"text"}
      onChange={inputName}
    />
 </div>
 )
}
```

####Svelte

```javascript:App.svelte
<script>
	let name = "";

	const handleInput = (e) => {
		name = e.target.value;
	};
</script>

<main>
	<p>{name}</p>
	<input type="text" on:input={handleInput} value={name} />
</main>
```

そしてこれをもっと簡単にして

```javascript:App.svelte
<script>
	let name = "";
</script>

<main>
	<p>{name}</p>
       <input type="text" bind:value={name} />
</main>
```

bind:valueってのでめっちゃ簡単にかけるね
動きは全部一緒で打った文字が上に出るだけ

![スクリーンショット 2020-12-12 16.38.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669792/ad5a9339-84f5-37e7-2c8b-07c71e811e90.png)

##依存関係のState変更

###React

```App.jsx
　const fullName = useMemo(()=>{
    return firstName + lastName 
  },[firstName,lastName])
```

####Svelte

```App.svelte
 $: fullName = `${firstName}${lastName}`
```

$:になります

```
 $: {
  console.log(fullname)
 }
```
とすると

![スクリーンショット 2020-12-12 17.12.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669792/bba79a3e-dfcb-9771-31a8-760a5c2577ff.png)

書き換えるたびにconsole.log(fullName)が発火します

##配列の展開

####React

```App.jsx


 const people = [
    { name: "neko", age: 25, id: 1 },
    { name: "inu", age: 34, id: 2 },
    { name: "ushi", age: 17, id: 3 },
    ]

return(
  <div>
    {people.map((person) => (
     <div key={person.id}> 
         <h4>{person.name}</h4>
         <p>{person.age}歳</p>
     </div>
  ))}
 </div>
 )
}
```

####Svelte

```javascript:App.svelte
<script>
	let people = [
		{ name: "neko", age: 25, id: 1 },
		{ name: "inu", age: 34, id: 2 },
		{ name: "ushi",  age: 17, id: 3 },
	];
</script>

<main>
	{#each people as person (person.id)}
		<div>
			<h4>{person.name}</h4>
			<p>{person.age}歳 </p>
		</div>
	{/each}
</main>
```

{#each as　配列名　単数　(一意のkey)}
 中に内容
{/each}

mapの代わりに#eachっての使えるみたい


###三項演算子

####React

```App.jsx
return(
  <div>
    {people.length > 0 ? (
    people.map((person) => (
     <div key={person.id}> 
         <h4>{person.name}</h4>
         <p>{person.age}歳</p>
     </div>
  ))):(<p>peopleないよーー</p>)}
 </div>
 )
```
 ?　以降の（）でどっちか表示するみたいな感じ
これだとpeopleが配列が0個だったらpeopleないよーーになるね

####Svelte

```javascript:App.svelte
<main>
	{#each people as person}
		<div>
			<h4>{person.name}</h4>
			<p>{person.age}歳 , {person.beltColor}</p>
		</div>
	{:else}
		<p>peopleないよーーー</p>
	{/each}
</main>
```

{#else}でpeopleないならpeopleないよー表示みたいな感じかな？

###if

条件と合えば表示させる(namが猫だったら猫ちゃんだーと表示)
####React

```App.jsx
return(
  <div>
   {people.map((person) => (
     <div key={person.id}> 
       <h4>{person.name}</h4>
       {person.name === "neko" && (
         <p>猫ちゃんだー</p>
       )}  
         <p>{person.age}歳</p>
     </div>
  ))}
 </div>
 )
```
####Svelte

```javascript:App.svelte
<main>
	{#each people as person (person.id)}
		<div>
			<h4>{person.name}</h4>
			{#if person.name === 'neko'}
				<p>こいつは猫ちゃんだーーー</p>
			{/if}
			<p>{person.age}歳</p>
		</div>
	{/each}
</main>
```

{#if　条件}　
　内容
{/if}　

みたいな感じで書くみたい

##Components

![スクリーンショット 2020-12-14 11.28.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669792/062607ef-d167-1d7e-fb2d-5849c6a24448.png)


Reactと同じようにSvelteもAppをRootComponentとしてツリー構造にComponentを作成することで
再利用性を高めることができる



###import 

Modalの表示をAppコンポーネントでimportして表示してみる
src/Modal.svelteを作成

```javascript:Modal.svelte
<script>
  let showModal = true;
</script>

<style>
.backdrop{
 css書く
..../////
}

.modal{
 ...///
 }

</style>

{#if showModal}
  <div class="backdrop" >
    <div class="modal">
      <p>ダミーダミー</p>
    </div>
  </div>
{/if}
```

showModalがtrueだったらModalが表示されるようなcomponentを作成

App.svelteでimport

```javascript:App.svelte
<script>
	import Modal from "./Modal.svelte";
</script>

<Modal/>
```
ここはscriptタフ内にReactと同じ書き方でimportを書くだけ
scriptやstyleタグの外でimportしたModalを書く
※このときModal.svelteのexportを書く必要がない（ここはReactと違うかな）

###Propsを渡して表示を切り替えよう

####React
Propsにmassageを受け取ったとする

```App.jsx
 return (
   <Modal massage="props渡すぜ" />
)
```

```Modal.jsx
const Modal = (props) =>{
  return (
　　<div>
　　  //props渡すぜ
     <p>{props.masssage}</P>
   </div>
}
```

####Svelte

```javascript:Modal.svelte
<script>
  export let message ;
  let showModal = true;
</script>

{#if showModal}
  <div class="backdrop" class:promo={isPromo}>
    <div class="modal">
      <p>{message}</p> //ここに文字入る
    </div>
  </div>
{/if}
```
scriptタグ内でmassageをexportする

``` javascript:App.svelte
<script>
    import Modal from "./Modal.svelte";
</script>

<Modal message="props渡すよー"/>
```

これでmessageを渡せます

ということで

showmodalもexportさせることで

``` javascript:Modal.svelte
<script>
  export let message ;
  export let showModal //export 
</script>

{#if showModal}
  <div class="backdrop" class:promo={isPromo}>
    <div class="modal">
      <p>{message}</p> //ここに文字入る
    </div>
  </div>
{/if}
```
``` javascript:Modal.svelte
<script>
    import Modal from "./Modal.svelte";
</script>

<Modal message="props渡すよー" showModal={true}/>
```

App.svelte内でModalComponentの表示を切り替えることができる

###実際に切り替えてみよう

``` javascript:App.svelte
<script>
    import Modal from "./Modal.svelte";
    let showModal = true;
</script>

<Modal message="props渡すよー"  {showModal} />
```
</script>

<Modal message="props渡すよー" {true}/>

App.svelteのscriptタグ内にshowModalのStateを書く
Modalに渡してあげる　showModal={showModal}と同じ意味になります


``` javascript:App.svelte
<script>
	import Modal from "./Modal.svelte";
	let showModal = false;

	const toggleModal = () => {
		showModal = !showModal;
	};
</script>

<Modal message="props渡すよー" showModal={true} on:click={toggleModal}/> 
<button on:click={toggleModal}>Open Modal</button>
//on:click | onceと書くと１回だけ発火します
```
```javascript:Modal.svelte
<script>
  export let message = "default value";  //この＝〇〇はdefaultの値
  export let showModal = false;  //defauletstate
</script>

<style>
//省略
</style>

{#if showModal}
  <div class="backdrop"  on:click|self>
    <div class="modal">
      <p>{message}</p>
    </div>
  </div>
{/if}
```

on:click を渡して|selfを書くことででModalはクリックしてもtoggleModalは発火しない

#まとめ
ちょっと長くなってしまうのでその②に続きます
Reactより楽ちんにかけそうなきがするけどReactのほうがかっこいいので推し面はReactです

続く