반응형

data.js

const main = [
    {
        num: '01',
        title: 'Section1',
        description: '내용 입력하기',
        href: '#article1'
    },
    {
        num: '02',
        title: 'Section2',
        description: '내용 입력하기',
        href: '#article2'
    },
    {
        num: '03',
        title: 'Section3',
        description: '내용 입력하기',
        href: '#article3'
    },
    {
        num: '04',
        title: 'Section4',
        description: '내용 입력하기',
        href: '#article4'
    },
    {
        num: '05',
        title: 'Section5',
        description: '내용 입력하기',
        href: '#article5'
    },
    {
        num: '06',
        title: 'Section6',
        description: '내용 입력하기',
        href: '#article6'
    },
    {
        num: '07',
        title: 'Section7',
        description: '내용 입력하기',
        href: '#article7'
    },
    {
        num: '08',
        title: 'Section8',
        description: '내용 입력하기',
        href: '#article8'
    },
    {
        num: '09',
        title: 'Section9',
        description: '내용 입력하기',
        href: '#article9'
    },
];

export default main

 

 

View.vue ( views )

<script setup>
import Header from '@components/Main/Header.vue'
import main from '@/assets/js/data.js'

</script>

<template>

    <Header />
    
    <section id="parallax_contents">
        <article :id="'article' + (index + 1)" class="content_item" v-for="(item, index) of main" :key="'a' + index">
            <span class="content_item_num">{{item.num}}</span>
            <h2 class="content_item_title">{{item.title}}</h2>
            <figure class="content_item_img_wrap">
                <div class="content_item_img"></div>
            </figure>
            <p class="content_item_description">{{item.description}}</p>
        </article>
        <!-- // article1 -->
    </section>
</template>

<style lang="scss" scoped>
    #parallax_contents {
        width: 100%;
        max-width: 1600px;
        margin: 0 auto;
        overflow: hidden;
        font-family: 'NEXONLv1Gothic';
        font-weight: 400;
    }
    .content_item {
        position: relative;
        width: 100%;
        max-width: 70vw;
        margin: 10vw 0;
        text-align: right;
        padding-top: 10vw;
        &:nth-child(even) {
            margin-left: auto;
            text-align: left;
            .content_item_num {
                right: auto;
                left: -5vw;
            }
            .content_item_description {
                margin-right: 0;
                margin-left: -3vw;
            }
        }
        &:nth-child(1) .content_item_img {
            background-image: url(https://images.unsplash.com/photo-1653559260394-ee10e61e0155?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=764&q=80);
        }
        &:nth-child(2) .content_item_img {
            background-image: url(https://images.unsplash.com/photo-1653559260394-ee10e61e0155?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=764&q=80);
        }
        &:nth-child(3) .content_item_img {
            background-image: url(https://images.unsplash.com/photo-1653559260394-ee10e61e0155?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=764&q=80);
        }
        &:nth-child(4) .content_item_img {
            background-image: url(https://images.unsplash.com/photo-1653559260394-ee10e61e0155?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=764&q=80);
        }
        &:nth-child(5) .content_item_img {
            background-image: url(https://images.unsplash.com/photo-1653559260394-ee10e61e0155?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=764&q=80);
        }
        &:nth-child(6) .content_item_img {
            background-image: url(https://images.unsplash.com/photo-1653559260394-ee10e61e0155?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=764&q=80);
        }
        &:nth-child(7) .content_item_img {
            background-image: url(https://images.unsplash.com/photo-1653559260394-ee10e61e0155?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=764&q=80);
        }
        &:nth-child(8) .content_item_img {
            background-image: url(https://images.unsplash.com/photo-1653559260394-ee10e61e0155?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=764&q=80);
        }
        &:nth-child(9) .content_item_img {
            background-image: url(https://images.unsplash.com/photo-1653559260394-ee10e61e0155?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=764&q=80);
        }
    }
    .content_item_num {
        position: absolute;
        font-size: 25vw;
        font-family: 'Lato';
        opacity: 0.07;
        right: -5vw;
        top: -5vw;
    }
    .content_item_title {
        padding-bottom: 1vw;
        font-size: 2vw;
    }
    .content_item_img_wrap {
        position: relative;
        width: 100%;
        padding-bottom: 56%;
        background-color: #000;
    }
    .content_item_img {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background-repeat: no-repeat;
        background-size: cover;
        filter: saturate(0%);
        transition: all 1s;
        &:hover {
            filter: saturate(100%);
        }
    }
    .content_item_description {
        position: relative;
        font-size: 4vw;
        line-height: 1.5;
        word-break: keep-all;
        margin-top: -6vw;
        margin-right: -3vw;
        z-index: 1;
    }
</style>

 

Header.vue ( component )

<script setup>
import main from '@/assets/js/data.js'

</script>
<template>
    <nav class="parallax_nav">
        <ul>
            <li v-for="(item, index) of main" :key="'a' + index" ><a :href="item.href" v-smooth-scroll>{{item.num}}</a></li>
        </ul>
    </nav>
</template>

<style lang="scss" scoped>
    a {
        text-decoration: none;
        color: #FFF;
    }
    .parallax_nav {
        position: fixed;
        top: 0;
        right: 0;
        width: 100%;
        overflow: hidden;
        transition: all 1s;
        z-index: 100;
        > ul {
            position: relative;
            top: 0px;
            transition: all 1s;
            display: flex;
            padding: 20px;
            background-color: #D2D2D2;
            > li {
                width: 40px;
                height: 40px;
                line-height: 40px;
                text-align: center;
                border-radius: 50%;
                margin-right: 10px;
                font-size: 16px;
                font-weight: 700;
            }
            .active { background-color: #FFF; a { color: #222; } }
        }
        .list_active { top: 0px; }
    }
    .hide {
        top: -100px;
    }
</style>

<script>
    export default {
        mounted() {
            window.addEventListener("scroll", scrollProgress);
        }
    }


    let nowScrollTop;
    let lastScrollTop = 0;

    function scrollProgress(){
        nowScrollTop = true;

        setTimeout(() => {
            if(nowScrollTop) {
                nowScrollTop = false;
                hasScroll();
            }
        }, 100);
    }

    function hasScroll() {
        let scrollTop = document.documentElement.scrollTop || window.scrollY || window.pageYOffset;

        if(scrollTop > lastScrollTop){
            document.querySelector(".parallax_nav").classList.add("hide");
        } else {
            document.querySelector(".parallax_nav").classList.remove("hide");
        }

        lastScrollTop = scrollTop;

    };

    
</script>

 

반응형
반응형

id값에 변수 추가하기

<div :id="'id명' + (index + 1)" v-for="(item, index) of main" :key="'a' + index"></div>

 

실제 예

<div :id="'box' + (index + 1)" v-for="(item, index) of main" :key="'a' + index"></div>
<!-- id="box1" -->

<div :id="'box' + index + 1" v-for="(item, index) of main" :key="'b' + index"></div>
<!-- id="box01" -->

<div :id="'box' + index" v-for="(item, index) of main" :key="'c' + index"></div>
<!-- id="box0 -->

1번부터 나오게 하기 위해서 첫번째처럼 괄호를 써서 표현을 했습니다.

 

:key값을 문자열을 추가하여 표기한 이유 바로가기

 

반응형
반응형

vite vue에서 js파일을 내보내는데 문제가 생겼다.

vue나 Nuxt에서 js파일을 내보낼때 module.exports로 내보낼수가 있었는데 vite에서는 module.exports로 내보내기가 작동하지 않았다.

 

:: 해결방법

Vite에서의 내보내기 ( export )

const array = [
    {
        num: 1,
        title: '내용'
    },
    {
        num: 2,
        title: '내용'
    },
    {
        num: 3,
        title: '내용'
    },
]

const array2 = [
    {
        num: 1,
        title: '내용'
    },
    {
        num: 2,
        title: '내용'
    },
    {
        num: 3,
        title: '내용'
    },
]

// 기본 내보내기
export default array

// 여러 변수를 내보내기
export { array, array2 }

 

Vite에서의 받기 ( import )

// 하나만 내보낸걸 받을 때
import array from '경로'

// 여러 변수를 내보낸걸 받을 때
import { array, array2 } from '경로'

 


 

Vue, Nuxt에서의 내보내기 ( export )

const array = [
    {
        num: 1,
        title: '내용'
    },
    {
        num: 2,
        title: '내용'
    },
    {
        num: 3,
        title: '내용'
    },
]

module.exports = {
    array: array
}

 

반응형
반응형

Props란 ?

부모 컴포넌트에서 자식 컴포넌트로 데이터를 전달할 때 사용되는 단방향 데이터 전달 방식이다.

 

 

App.vue ( 부모 컴포넌트 )

html

<template>
  <input type="text" v-model="callProps" />
  <Header :msg="callProps" />
</template>

script

import Header from '@components/Main/Header.vue'
import { ref } from 'vue'

export default {
  data() {
    const callProps = ref('Hello')

    return {
      callProps
    }
  }
}

 

Header.vue ( 자식 컴포넌트 )

html

<template>
    <h1>자식 컴포넌트 확인하기</h1>
    <div>{{msg}}</div>
</template>

script

export default {
    props: {
        msg: String
    }
}

 

부모 컴포넌트(App.vue)에 input창에 텍스트를 입력하면 :msg="callProps"를 통해서 자식 컴포넌트로 보내지고 자식 컴포넌트(Header.vue)에 props를 통해 텍스트가 전달된다.

 

반응형
반응형

v-bind 디렉티브 : 단방향 결합을 지원

v-model 디렉티브 : 양방향 결합을 지원

 

단방향 결합 => 변수의 값이 템플릿으로만 결합되어 템플릿의 HTML태그가 변경한 값이 변수에 돌아오지 않는다.

양방향 결합 => 변수의 변경이 템플릿의 DOM에 영향을 미치는 것은 물론이고, 템플릿에서의 변경이 변수의 값을 변경시키기도 한다.

 

<template>
    <div>
        <input type="text" :value="abbr" />
        <input type="text" v-model="normal" />

        <hr />

        <abbr :title="normal">{{abbr}}</abbr>
        <br />
        <abbr :title="abbr">{{normal}}</abbr>
    </div>
</template>
import { ref } from 'vue'

export default {
    setup() {
        const abbr = ref('Project1')
        const normal = ref('Project2')
        return {
            abbr,
            normal
        }
    }
}

vue에서 먼저 ref 컴포지션 API함수를 불러왔다. setup함수는 Options API와는 다르게 반응형 변수를 선언하기 위해서는 ref함수로 값을 한번 감싸줘야 한다.

반응형
반응형

v-text디렉티브나 수염표기법(Mustache syntax)으로 나타내는 값은 모두 일반 텍스트로 출력이 된다.

이는 HTML엘리먼트의 textContent를 업데이트하기 때문이다. 이는 결국 HTML을 작성한 문자열을 변수의 값으로 대입하더라도 HTML태그를 가지고 있는 문자열 그대로 렌더링이 된다.

반면 v-html디렉티브는 HTML엘리먼트의 innerHTML값에 변수값을 전달하기 때문에 문자열이 HTML마크업 언어로 표현되도록 한다. innerHTML에 바로 값을 집어 넣기 때문에 변수는 반드시 HTML평문이어야 하며, Vue의 문법을 사용해도 컴파일이 되지 않는다.

 

수염표기법 / v-text디렉티브

<div v-text="msg"></div> <!-- 안녕하세요 -->
<div v-pre>{{msg}}</div> <!-- 안녕하세요 -->
setup() {
    const msg = "안녕하세요"
    return {
        msg
    }
},

 

v-pre디렉티브를 이용한 컴파일 무시

<div v-pre>{{msg}}</div> <!-- {{msg}} -->

 

반응형
반응형

변수는 선언하고 값을 넣으면 자동으로 DOM에 업데이트가 된다. Options API를 사용하기 위해서는 단순히 data옵션에 변수를 선언하면 되며, 컴포지션 API와 함께 이용하기 위해서는 setup함수를 생성하고 그 안에 일반적인 자바스크립트 변수를 선언하듯이 선언하면 된다. 선언된 변수는 템플릿의 변수와 결합될 수 있도록 반드시 객체 형식으로 반환돼야 한다.

 

template

<template>
    <div>
        <div id="date">
            {{date}}
        </div>
        <div id="date2">
            {{date2}}
        </div>
    </div>
</template>

 

script

export default {
    setup() {
        const date = Date().toString()
        return {
            date
        }
    },
    data() {
        return {
            date2: Date().toString()
        }
    }
}

setup함수 내에서 변수를 선언하고 반환하는 방법과 기존과 동일한 방식의 Options API를 이용해 변수를 선언하고 반환하는 방법을 보여준다.

setup함수에서는 date라는 함수를 선언하고 자바스크립트의 Date클래스의 toString메서드를 이용해 현재 날짜와 시간을 얻어온다.

같은 값을 얻어오지만 Options API는 data라는 별도의 옵션 함수를 이용해 date2에 날짜와 시간을 대입하는 것을 알 수 있다.

Date().toString()

 

 

반응형
반응형

Vue2까지는 Option API만 제공을 했으며, 컴포넌트를 생성할 때 옵션 속성이라 불리는 data, methods, computed등과 같은 것들을 정의해야 했다. 이는 코드가 길어지면 가독성을 낮추는 문제점이 있었기에 다른 컴포지션 프레임워크들과 같이 컴포지션 API를 지원하고자 setup함수를 제공하게 됐다.

 

setup함수의 구조

setup() {
    const data = 1
    return { data }
}

이전 Options API에서 사용하던 computed, watch옵션은 모두 setup함수에서도 구현이 가능하다.

기존 methods옵션으로 제공하던 함수의 경우 다음과 같이 변수로 할당하여 반환하면 된다.

const foo = () => { data = 2 }
return { foo }

 

반응형
반응형

Alias

초창기 Vite는 Alias를 지원하지 않아 서드파티 라이브러리를 사용하곤 했다. 하지만 2020년 5월 Vite는 공식적으로 Alias를 지원하게 되었다. Alias를 이용하면 대규모 프로젝트를 진행할 때 각 파일의 경로를 모두 적어줘야 하는 불편함을 해소해준다.

Alias를 구성하기 전에 경로를 생성할 때 도움을 줄 수 있는 path라이브러리를 설치해준다.

 

NPM [ path 설치 ]

$ npm install path

Alias를 설치하면 컴포넌트를 불러올때 /src/components/component.vue와 같이 할 필요없이 @components/component.vue라고 할 수 있다.

 

vite.config.js

import path from 'path'

export default defineConfig({
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src'),
      '@components': path.resolve(__dirname, './src/components'),
      '@app_modules': path.resolve(__dirname, './src/modules'),
      '@store': path.resolve(__dirname, './src/store')
    }
  },
  plugins: [vue()]
})

이제 import를 할 때 '../../assets/style ...'을 할 필요없이 '@/assets/style ...'로 사용할 수 있게 되었다.

컴포넌트로 진입할 때는 '../../components/component.vue'를 할 필요없이 @components/component.vue로 깔끔하게 입력할 수 있게 되었다.

반응형

'VueJS > Vue3 Vite' 카테고리의 다른 글

[ Vue ] [ Vue3 Vite ] 선언적 렌더링  (0) 2022.05.13
[ Vue ] [ Vue3 Vite ] 컴포지션 함수 setup  (1) 2022.05.13
[ Vue ] [ Vue3 Vite ] SASS, SCSS 사용하기  (0) 2022.05.12
[ Vue ] Vue3 Vite dist  (0) 2022.05.12
[ Vue ] Vue3 Vite  (0) 2022.05.12
반응형

Vite 바로가기

 

SASS ADD

$ npm add -D sass

 

.scss 파일 생성하기

 

main.js [ 전역 설정 ]

import './assets/styles/reset.scss'

전역으로 설정하려면 main.js에 내가 생성한 .scss파일을 한줄 추가해준다.

 

.vue [ 직접 추가하기 ]

<style lang="scss" scoped>
@import "../../assets/styles/main/header.scss";
    
</style>

scoped로 처리해주지 않으면 전역에 적용되기 때문에 적용시켜주어야 한다.

 

반응형

'VueJS > Vue3 Vite' 카테고리의 다른 글

[ Vue ] [ Vue3 Vite ] 선언적 렌더링  (0) 2022.05.13
[ Vue ] [ Vue3 Vite ] 컴포지션 함수 setup  (1) 2022.05.13
[ Vue ] [ Vue3 Vite ] Vite Alias 생성하기  (0) 2022.05.12
[ Vue ] Vue3 Vite dist  (0) 2022.05.12
[ Vue ] Vue3 Vite  (0) 2022.05.12

+ Recent posts