disable, readonly, watch, 반복문, 유효성 검사, 전개연산자

keep_going·2023년 1월 4일
0

vue

목록 보기
10/13

// 파일명: FormPage.vue

  • vue 기능 보충
<template>
    <div>
        <button @click="state.menu=1">메뉴1</button>
        <button @click="state.menu=2">메뉴2</button>
        <button @click="state.menu=3">메뉴3</button>
        <hr />
        <menu-1 v-if="state.menu === 1"></menu-1>
        <menu-2 v-if="state.menu === 2"></menu-2>
        <menu-3 v-if="state.menu === 3"></menu-3>
    </div>
</template>

<script>
import Menu1 from '@/components/form/Menu1Page.vue';
import Menu2 from '@/components/form/Menu2Page.vue';
import Menu3 from '@/components/form/Menu3Page.vue';
import { reactive } from '@vue/reactivity';
// @는 src를 의미

export default {
    components:{
        Menu1, // 파스칼
        Menu2,
        Menu3,
    },
    setup () {
        const state = reactive({
            menu : 3,
        })

        return {
            state,
        }
    }
}
</script>

<style lang="css" scoped>

</style>

// 파일명 : form/Menu1Page.vue

<template>
    <div>
        <h3>메뉴1</h3>

        <div class="item">
            <input type="text" :readonly="state.readonly"/>
            <button @click="handleReadonly()">{{ state.label }}</button> 
        </div>

        <div class="item">
            <button :disabled="state.disabled">버튼</button>
            <button @click="handleDisabled()">{{ state.label1 }}</button> 
        </div>

        <div class="item">
            <input type="text" v-model="state.name" />
        </div>

    </div>
</template>

<script>
import { reactive } from '@vue/reactivity'
import { watch } from '@vue/runtime-core';
export default {
    setup () {
        const state = reactive({
            name        : '',

            readonly    : true, //true 글자 입력안됨.
            label       : '현재는 읽기만 가능',

            disabled    : false,
            label1      : '버튼 클릭 가능',
        });

        // state 변수 변화 감지
        watch(state, () => {
            console.log('watch state =>', state);
        },{
            immediate:true,
        });

        // state변수의 name값 변화 감지
        watch(() => state.name, () => {
            console.log('watch name state =>', state);
        },{
            immediate:true,
            deep:true,
        });


        const handleReadonly = () => {
            if(state.readonly === true){
                state.readonly = false;
                state.label = '현재는 읽기쓰기 가능'
            }
            else {
                state.readonly = true;
                state.label = '현재는 읽기만 가능'
            }
        };

        const handleDisabled = () => {
            if(state.disabled === true){
                state.disabled = false;
                state.label1 = '버튼 클릭 가능';
            }
            else {
                state.disabled = true;
                state.label1 = '버튼 클릭 불가';
            }
        };

        return {
            state,
            handleReadonly,
            handleDisabled
        };
    }
}
</script>

<style lang="css" scoped>
    .item {
        padding: 5px;
    }
</style>

// 파일명 : form/Menu2Page.vue

<template>
    <div>
        <h3>메뉴2</h3>
        {{ state }}
        <table border="1">
            <tr>
                <th>번호</th>
                <th>주문번호</th>
                <th>품명</th>
                <th>가격</th>
                <th>수량</th>
                <th>합계</th>
            </tr>

			// index붙여서 반복되는 위치 알수있음, 0부터 시작 
            // state.rows[0].cnt  [{0},{1},{2}] => {0}
			// {{ tmp.cnt }}는 {{ state.rows[idx].cnt }} 와 동일 
			<tr v-for="(tmp, idx) of state.rows" :key="tmp">
                <td>
                    <input type="checkbox" :value="idx" v-model="state.chk" />
                  // 내가 푼 방법: 체크박스의 값을 각 주문번호에 해당하는 합계로 만들기
                  // <input type="checkbox" :value="(tmp.price)*(tmp.cnt)" v-model="state.chk" /> 
                    {{ (idx+1) }}
                </td>

                <td>{{ tmp.no }}</td>
                <td>{{ tmp.name }}</td>
                <td>{{ tmp.price }}</td>
                <td>
                    <select v-model="tmp.cnt">
                        <option v-for="tmp1 of 100" :key="tmp1" :value="tmp1">{{ tmp1 }}</option>
                    </select>
                </td>
                <td>{{ tmp.price * tmp.cnt }}</td>
            </tr>

            <tr>
                <th>총합계</th>
                <td colspan="5">{{ state.total }}</td>
			 // <td colspan="5" >{{ state.chk.reduce((a,b)=>(a+b)) }}</td>
			// reduce로 체크박스(배열)의 원소값 합하기
            </tr>
        </table>

        <button @click="handleAppend()">아래쪽으로 복사</button>

        <table>
            <tr v-for="(tmp, idx) of state.rows1" :key="tmp">
                <td>{{ (idx+1) }}</td>
                <td>{{ tmp.no }}</td>
                <td>{{ tmp.name }}</td>
                <td>{{ tmp.price }}</td>
                <td>{{ tmp.cnt }}</td>
            </tr>
        </table>

        <hr />
        <table>
            <tr v-for="(tmp, idx) of state.rows2" :key="tmp">
                <td>{{ (idx+1) }}</td>
                <td>{{ tmp.no }}</td>
                <td>{{ tmp.name }}</td>
                <td>{{ tmp.price }}</td>
                <td>{{ tmp.cnt }}</td>
            </tr>
        </table>
        <button @click="handlePlus()">가격1씩증가</button>
    </div>
</template>

<script>
import { reactive } from '@vue/reactivity'
import { onMounted, watch } from '@vue/runtime-core'
export default {
    setup () {
        
        const state = reactive({
            rows1   : [],
            rows    : [],
            chk     : [],
            // chk  : [0], 체크박스의 값을 합계로 정했으므로 기본값을 빈값으로 두면 오류발생
            total   : 0,
            rows2 : [] //임의의 데이터를 3개 추가하기 버튼 누르면 가격 1씩 증가
        });

        // 코딩테스트 => 문제해결 => 속도 => 반복문횟수 줄이기 (시간복잡도)

        // [{},{},{}]  => [1, 2]
        watch(() => state.chk, () => {
            state.total = 0;
            for(let tmp1 of state.chk) { //[2, 0]
                state.total += state.rows[tmp1].price 
                            * state.rows[tmp1].cnt;
            }
          
        // 비효율적!
        // for(let tmp of state.rows) { // 전체 {111},{222},{333}
        //     for(let tmp1 of state.chk) { // [111, 333]
        //         if(tmp.no === tmp1) {
        //             state.total += tmp.price *tmp.cnt;
        //         }
        //     }
        // }
          
        },{
            immediate:true,
            deep:true,
        });
      
      	

        const handleData = () => {
            // 벡엔드에서 받은내용(받았다고 가정) => 주문번호, 물품명, 가격, 수량
            state.rows =  [
                { no : 111, name:'가', price:10, cnt:20 },
                { no : 222, name:'나', price:20, cnt:30 },
                { no : 333, name:'다', price:100, cnt:22 },
            ];

            state.rows2 =  [
                { no : 111, name:'가', price:10, cnt:20 },
                { no : 222, name:'나', price:20, cnt:30 },
                { no : 333, name:'다', price:100, cnt:22 },
            ];


            //------------------------
            // 추출 변경 ....
            //------------------------
            for(let i=0;i<3;i++)  {
                let obj = {};
                obj.no  = (444 + i);
                obj['name'] = '가나다' + i;
                obj.price = 1000;
                obj.cnt = 14;

                state.rows.push( obj ); // 배열에 원소 집어넣기
            }

            // 위치(0부터), 개수
            state.rows.splice(2, 1); // 배열에서 원소 삭제하기
        };   
      
        // 전개연산자(복사)
        // const a = [{id:1,name:'a'},{id:2,name:'b'},{id:3,name:'c'}]
        // const b = {...a[0]}   => {id:1,name:'a'}

        // 전개연산자(병합)
        // const c = [{...a[0]}, {...a[2]}]

        // 원시데이터 [{},{},{}]  => 추출 => 배열 [1,3,4] => chart에 사용
        // [1,2,3] => [{},{},{}]

        const handleAppend = () => {
            //state.rows에 있는 것중에서 체크된 항목만 state.rows1에 복사
            for(let tmp1 of state.chk) { //[2, 0]
                state.rows1.push( { ...state.rows[tmp1] } );
            }
        };

        const handlePlus = () =>{
            for(let tmp of state.rows2) {
                tmp.price++;
            }
          	// 배열에 있는 각각 원소를 반복문으로 먼저 나열! 그 후 key값에 접근 
            // 아래는 나열 안하고 배열 내에서 원소 위치를 찾고 그 후 key값에 접근한것
            // 굳이 slice 써서 배열내 원소의 값을 복사해올 필요가 없었음..
            
            // for(let i=0; i < state.rows2.length; i++) {
            //     state.rows2[i].price++;
            // }
        };

        onMounted(() => {
            handleData();
        });
      
        return {
            state,
            handleAppend,
            handlePlus
        };
    }
}
</script>

<style lang="css" scoped>

</style>

// 파일명 : form/Menu3Page.vue

<template>
    <div>
        <div>
            <input type="text" :ref="el => { arr[0] = el }" v-model="id" />
            // ref 배열화 시켰더니 사용할때 형태가 복잡해졌네...
        </div>

        <div>
            <input type="text" :ref="el => { arr[1] = el }" v-model="name" />
        </div>

        <div>
            <input type="text" v-model="age" />
        </div>

        <div>
            <button @click="handleAction()">유효성검사</button>
        </div>
    </div>
</template>

<script>
import { reactive, ref, toRefs } from '@vue/reactivity'
export default {
    setup () {
        const uid   = ref();
        const uname = ref();
		// 위와 같이 쓰다가 항목이 많아지면 아래처럼 배열화 시키자
        const arr   = ref([]);

        const state = reactive({
            id : '',
            name : '',
            age : 0,
        });

        const handleAction = () => {
            if(state.id.length <= 0){
                alert('아이디 입력');
                arr.value[0].focus();
                return false;
            }
            if(state.name.length <= 0){
                alert('이름 입력');
                arr.value[1].focus();
                return false;
            }
			if(state.age <= 0) {
                alert('나이 입력');
                return false;
            }
            alert('유효성통과');
        };

        return {
            state, 
            uid,
            uname,
            arr,
            ...toRefs(state),
            handleAction
        };
    }
}
</script>

<style lang="css" scoped>

</style>
profile
keep going

1개의 댓글

comment-user-thumbnail
2023년 1월 4일

이미지 수정하고 바껴서 보이려면 url자체가 바껴야함
아무런 처리 안하면 url주소가 사진 수정해도 동일해서 읽어오지 않음.
보통은 쿼리에 시간정보를 넣어줌(숫자 13자리).
백엔드에서 imageurl 만드는데서 &ts=${Date.now()}를 붙여줌

답글 달기