<template>
<div>
<h3>Home.vue</h3>
<vueper-slides bullets-outside :dragging-distance="50">
<vueper-slide
v-for="(tmp, i) in state.slides"
:key="i"
:title="tmp.title"
:image="tmp.image"
:video="tmp.video"
>
</vueper-slide>
</vueper-slides>
</div>
</template>
<script>
import { VueperSlides, VueperSlide } from "vueperslides";
import "vueperslides/dist/vueperslides.css";
export default {
components: {
VueperSlides,
VueperSlide,
},
setup() {
const state = {
slides: [
{
title: "Aurora Borealis",
image: "https://i.ytimg.com/vi_webp/ehJg_OlcjpE/maxresdefault.webp",
video: {
url: "https://www.youtube.com/embed/ehJg_OlcjpE?rel=0&showinfo=0&controls=0&fs=0&modestbranding=1&color=white&iv_load_policy=3&autohide=1&enablejsapi=1",
props: {
allow:
"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture",
},
},
},
{
title: "Fjords",
image: "https://i.ytimg.com/vi/2sr9MGkkeks/maxresdefault.jpg",
video: {
url: "https://www.youtube.com/embed/2sr9MGkkeks?controls=0&fs=0&modestbranding=1&color=white&iv_load_policy=3&autohide=1&enablejsapi=1",
props: {
allow: "autoplay",
},
pointerEvents: false,
},
},
],
};
return { state };
},
};
</script>
<style lang="scss" scoped>
</style>
<template>
<div style="width: 500px; height: 300px">
<h3>src/component/Chart.vue</h3>
<vue3-chart-js
:id="state.id"
:type="state.type"
:data="state.data"
ref="chartRef"
>
</vue3-chart-js>
<button @click="updateChart">updateChart</button>
<button type="submit" @click="exportChart">ExportChart</button>
</div>
</template>
<script>
import Vue3ChartJs from "@j-t-mcc/vue3-chartjs";
import { ref } from "vue";
export default {
components: {
Vue3ChartJs,
},
setup() {
// 빈 것 만들기
const chartRef = ref(null);
// object(R) -> reactvie(RW) -> ref(RW Deep)
const state = {
//Read
id: "doughnut",
type: "doughnut",
data: {
labels: ["html", "css", "script", "vue3"],
datasets: [
{
backgroundColor: ["#41B883", "#E46651", "#00D8FF", "#DD1B16"],
data: [340, 220, 460, 320],
},
],
},
};
//function updateChart() { }
const updateChart = () => {
// 변경데이터 설정
state.data.labels = ["Cats", "Dogs", "Hamsters", "Dragons"];
state.data.datasets = [
{
backgroundColor: ["#333333", "#E46651", "#00D8FF", "#DD1B16"],
data: [100, 20, 800, 20],
},
];
console.log(chartRef.value);
// 컴포넌트에 변화되었음을 알려줌
chartRef.value.update(250);
console.log(chartRef.value);
};
const exportChart = () => {
let a = document.createElement("a");
a.href = chartRef.value.chartJSState.chart.toBase64Image();
a.download = "image-export.png";
a.click();
a = null;
};
// 리턴함.
return { state, updateChart, chartRef, exportChart };
},
};
</script>
<style lang="scss" scoped>
</style>
<template>
<div>
<h3>src/components/BoardWrite.vue</h3>
{{ state }}<br />
제목 : <input type="text" v-model="state.title" /> <br />
내용 :
<div style="width: 600px">
<ckeditor
:editor="editor.editor"
:config="editor.editorConfig"
v-model="state.content"
></ckeditor>
</div>
<br />
작성자 : <input type="text" v-model="state.writer" /> <br />
이미지 :
<img :src="state.imgurl" style="width: 100px; height: 100px" />
<input type="file" @change="handleImage" /><br />
<button @click="handleWrite">글쓰기</button>
</div>
</template>
<script>
import { reactive } from "vue";
import ClassicEditor from "@ckeditor/ckeditor5-build-classic";
export default {
setup() {
//object
const editor = {
editor: ClassicEditor,
editorData: "<p>테스트</p>",
editorConfig: {},
};
const state = reactive({
title: "",
content: "",
writer: "",
imgdata: "",
imgurl: require("../assets/3.jpg"),
});
// 첨부 or 취소
const handleImage = (e) => {
if (e.target.files[0]) {
// 첨부
state.imgdata = e.target.files[0];
// 크롬내부에 임시로 이미지를 표시하기 위한 URL생성
state.imgurl = URL.createObjectURL(e.target.files[0]);
} else {
// 취소
state.imgdata = "";
state.imgurl = require("../assets/3.jpg");
}
};
const handleWrite = async () => {
if (state.title === "") {
alert("제목을 입력해주세요");
return false;
}
if (state.content === "") {
alert("내용을 입력해주세요");
return false;
}
if (state.writer === "") {
alert("작성자를 입력해주세요");
return false;
}
};
return { state, handleWrite, handleImage, editor };
},
};
</script>
<style lang="css">
.ck-editor__editable {
min-height: 500px;
}
</style>
<template>
<div class="style1">
<h3>src/components/Join.vue</h3>
{{ state }}{{ userid }}
<input type="text" ref="userid" v-model="state.userid" />
<input type="password" ref="userpw" v-model="state.userpw" />
<input type="password" ref="userpw1" v-model="state.userpw1" />
<input type="text" ref="username" v-model="state.username" />
<button @click="handleJoin">회원가입</button>
</div>
</template>
<script>
import { reactive, ref } from "vue";
//CMD> npm i axios --save
import axios from "axios";
export default {
setup() {
// High레벨 변수 생성: 오브젝트만 변화감지
// 쉽게이해가능 깊이가 있는 컨트롤 불가능
const state = reactive({
userid: "aaa",
userpw: "",
userpw1: "",
username: "",
});
// Low레벨 변수 생성 : 오브젝트가 아님
const userid = ref("aaa"); // 위에서 연결하면 bbb값은 의미가 없어짐
const userpw = ref("aaa");
const userpw1 = ref("aaa");
const username = ref("aaa");
// function handleJoin( ){ }
const handleJoin = async () => {
if (state.userid === "") {
alert("아이디를 입력하세요!");
userid.value.focus();
return false; // 이 위치에서 메소드 종료
}
if (state.userpw === "") {
alert("비밀번호를 입력하세요!");
userpw.value.focus();
return false;
}
if (state.userpw1 === "") {
alert("비밀번호1을 입력하세요!");
userpw1.value.focus();
return false;
}
if (state.username === "") {
alert("이름을 입력하세요!");
username.value.focus();
return false;
}
//유효성 검증완료되는 시점에 벡엔드 연동
const url = "http://ihongss.com/json/exam13.json";
const headers = { "Content-Type": "application/json" };
const response = await axios.get(url, { headers });
console.log(response.data);
};
return { state, handleJoin, userid, userpw, userpw1, username };
},
};
</script>
<!--scss, less => css
// CMD> npm install -D sass-loader@^10 sass-->
<style lang="scss" scoped>
.style1 {
border: 1px solid;
padding: 20px;
}
</style>
ref와 reactive의 차이점 생각하기
high레벨 low레벨 생각하기
오타 조심하기