Vue 3์์ ์๋ก ๋ฑ์ฅํ The composition API์ ๋ํด ์์๋ณด์.
import getPosts from './getPosts' export default{ setup(){ // data //methods //computed //lifecycle hooks const data=getPosts() } }
1.Group logic together in a setup function
2.Easily create reusable logic(Functions)
์์ ์ฝ๋๋ฅผ ์ดํด๋ณด์.
<template>
<div class="home">
home
<p ref='p'>My name is {{name}} and my age is {{age}}</p>
<button @click="handleClick">click me </button>
<input type='text' v-model='name'> //์ธํ์ ์์ฑํ๋๋๋ก name์ด ๋ณ๊ฒฝ๋๋ค
</div>
</template>
<script>
import {ref} from'vue'
export default{
name:'Home',
//setup() is always runs first before created and mounted..
setup(){
console.log('setup')
const p = ref(null)
console.log(p,p.value)
//These are not reactive by default
let name='mario'
let age=30
//we can use refs to create reactive values!
const name=ref('mario')
const age=ref(30)
const handleClick=()=>{
console.log(p,p.value);
p.value.classList.add('test')
p.value.textContent='hello,ninjas';// ๋ฒํผ ๋๋ฅด๋ฉด p ๋ด์ฉ์ ๊ฐ์ด ๋ฐ๋๋ค.
//name๊ณผ age์ ๊ฐ์ด ๋ณ๊ฒฝ๋๋ค(๋ฒํผ ๋๋ฅด๋ฉด)
name.value='loco'
age.value=29
}
return {name,age,handleClick,p}
}
}
</script>
<template>
<div class='home'>
<h1>Home</h1>
<h2>Refs</h2>
<p> {{ninjaOne.name}}-{{ninjaOne.age}}</p>
<button @click='updateNinjaOne'>Update ninja one</button>
<h2>Reactive</h2>
<p>{{ninjaTwo.name}}-{{ninjaTwo.age}}</p>
<button @click="updateNinjaTwo">Update ninja two</button>
</div>
</template>
<script>
import {ref,reactive} from 'vue'
export default {
name:'Home',
setup() {
const ninJaOne=ref({name:'mario',age:30})
const ninjaTwo=reactive({name:'luigi',age:34})
const nameOne=ref('mario')
const nameTwo=reactive('luigi');
//luigi๊ฐ์ primitive value์ด๊ธฐ์ ์
๋ฐ์ดํธ ๋์ง ๋ชปํ๋ค.
const updateNinjaOne=()=>{
๐ ninjaOne.value.age=40
}
const updateNinjaTwo=()=>{
๐ ninjaTwo.age=45
nameTwo='mario' // ์ ํ ์
๋ฐ์ดํธ ๋์ง ์๋๋ค.
return{ninjaOne,updateNinjaOne,ninjaTwo,updateNinjaTwo}
}
}
ref
๋ฅผ ์ฌ์ฉํ ๋๋, ๊ฐ์ ์ ๊ทผํ๊ธฐ ์ํด value๋ฅผ ํญ์ ์ ์ด์ค์ผํ๋ค.
๊ทธ๋ฌ๋reactive
๋ฅผ ์ฌ์ฉํ ๋๋ value๋ฅผ ์ฌ์ฉํ ํ์์๋ค.
๋ ์ค์ ๋ฌด์ผ ์ฐ๋ ๊ฒ์ด ์ข์๊ฐ?reactive๋ ๊ฐ์ ์ ๋ฐ์ดํธํ๊ธฐ ์ด๋ ต๋ค. ์ฌ๋ฌ์ด์ ๋ก ref๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ์ข๋ค
<template>
<div class='home'>
<h1>Home</h1>
<input type='text' v-model='search'>
<p>search term - {{search}}</p>
<div v-for="name in matchingNames" :key="name">{{name}}</div>
</div>
</template>
<script>
import {computed,ref} from'vue'
export default {
name:'Home',
setup(){
const search=ref('')
const names=ref(['mario','yoru','luigi','tod','peach'])
const matchingNames = computed(()=>{
return names.value.filter((name) => name.includes(search.value))
})
return {names,search}
}
}
</script>
<template>
<div class="home">
<h1>Home</h1>
๐ <PostList v-if='showPosts' :posts='posts' />
//๋ง์ฝ showPosts๊ฐ false์ด๋ฉด ์ด ์ปดํฌ๋ํธ๋ ์ธ๋ง์ดํธ๋์ด์ ์๋ณด์ด๊ฒ ๋ ๊ฒ์ด๋ค.
<button @click='showPosts =!showPosts'>toggle posts</button>
<button @click="posts.pop()"> delete a post </button>
</div>
</template>
<script>
๐ import PostList from '../';
import {ref} from 'vue'
export default {
name:'Home',
๐ components:{PostList},
setup(){
const posts = ref([
{title:'welcome',body:'lorem',id:1},
{title:'top 5 tips', body:'Lorem',id:2}
])
const showPosts = ref(true)
return {posts,showPosts}
}
}
</script>
==PostList.vue===
<template>
<div class='post-list'>
<div v-for='post in posts :key='post.id'>
<h3>{{post.title}}</h3>
</div>
</div>
</template>
<script>
export default {
props:['posts'],
setup(props) {
console.log(props.posts)
}
}
</script>
<template>
<div class='post-list'>
<div v-for='post in posts :key='post.id'>
<SinglePost :post='post'/>
</div>
</div>
</template>
<script>
import { onMounted , onUnmounted,onUpdated} from 'vue'
import SinglePost from './SinglePost.vue'
export default {
props:['posts'],
components:{SinglePost},
๐ setup(props) {
onMounted(()=>console.log('component mounted')
onUnmounted (()=>console.log('component unmounted')
onUpdated(()=>console.log('component updated'))
}
}
</script>
<template>
<div class='home'>
<h1> Home</h1>
<div v-if='error'>{{error}} </div>
<div v-if="posts.length'>
<PostList :posts='posts' />
</div>
<div v-else > Loading...</div>
</div>
</template>
<script>
import PostList from '../'
import {ref} from 'vue'
export default {
name:'Home',
components:{PostList},
setup(){
const posts=ref([])
const error=ref(null)
๐น const load=async()=>{
try{
let data= await fetch('http://localhost:3000/posts'
)
if(!data.ok){
throw Error('no data available')
}
posts.value = await data.json()
catch(err){
error.value=err.message
console.log(error.value)
}
}
load();
return {posts,error}
<template>
<div class='app'>
<p> {{ jobs[0]/location</p>
</div>
</template>
<script lang='ts'>
import {defineComponent,reactive,toRefs,ref} from 'vue';
im
import Job from './types/Job';
export default defineComponent ({
name:'App',
components:{},
setup(){
//const state = reactive ({
//name:'Link',
//age:25 as string | number <Type Assertion>
// })
//state.name =99999 //cannot change type
//If I change the name as a number,this is not gonna work.
//state.age='26'
//return {...toRefs(state)}
const name = ref('Link')
const age = ref<number|string>(25); //we can use generic arguments instead of using type assertion
age.value=26 ๊ฐ๋ฅ
age.value='26'๊ฐ๋ฅํด์ง
return {name,age}
const jobs=ref<Job[]>([
{title:'farm worker',location:'London' salary:30000,id:'1'}
{title:'lawyer',location:'Newyork' salary:40000,id:'2'}
{title:'engineer',location:'Paris' salary:30000,id:'3'}
])
return {jobs}
},
methods:{
changeName(name:string){
this.name =name
return name
},
changeAge(age:string|number){
this.age = age
return age
}
}
});
</script>
====Job.ts==============
interface Job {
title:string,
location:string,
salary:number,
id:string
}
export default Job
์ฐธ๊ณ :Youtube_The Net Ninja