문제가 된다면 삭제 하도록 할게요.

 

개인정보 교육 꼭 들어야 합니다!

하지만 이런 방법으로 패스도 가능하다는걸 알고 있다면 좋겠죠?

 

 

function goLast(){
	setTimeout(() => {  
    	window.document.getElementById('contentsFrame').contentWindow.document.getElementById('frame').contentWindow.document.getElementById('MPlayer').currentTime=999999
		setTimeout(() => {
			window.document.getElementById('contentsFrame').contentWindow.document.getElementById('frame').contentWindow.document.getElementsByClassName('next')[0].click();
		}, 1000)
	}, 2000)
}

window.document.getElementById('contentsFrame')
.contentWindow.document
.getElementById('frame')
.addEventListener('load', goLast, false);

goLast();

 

goLast 함수는 비디오 플레이어의 시간 컨트롤러의 값을 매우 크게 변경하고(종료지점으로), 넥스트 페이지 버튼을 클릭하게 해줌.

그리고 이 함수를 최초 실행하게하고, frame(iframe) load이벤트에 걸어둠.

다음페이지가 호출되고 frame의 내용이 변경되고 로드가 완료되면 다시 goLast를 실행하는 구조.

 

돔 구조만 파악하면 재미삼아 간단하게 짤 수 있는 코드,

 

실행은 개발자 도구의 콘솔에서...

 

현재 위 사이트는 body > iframe > iframe > video 와 같은 형태로 되어 있어요.

화면 기록 2022-11-29 오후 3.58.01.mp4
17.10MB

https://docs.google.com/spreadsheets/d/1BYsqJlHgP2DQnUZMnTLkU3jrnmUsiLd2BifTcdpECDU/copy

 

Google Sheets - 스프레드시트를 작성하고 수정할 수 있으며 무료입니다.

하나의 계정으로 모든 Google 서비스를 스프레드시트로 이동하려면 로그인하세요.

accounts.google.com

 

위 시트를 복사하고, 확장 프로그램 > App Script 로 가서 필요한 스크립트를 수정(수정안해도 상관없음)

스크립에서는 구글의 메일앱을 사용한다.

https://developers.google.com/apps-script/reference/mail/mail-app

 

Class MailApp  |  Apps Script  |  Google Developers

Send feedback Class MailApp MailApp Sends email. This service allows users to send emails with complete control over the content of the email. Unlike GmailApp, MailApp's sole purpose is sending email. MailApp cannot access a user's Gmail inbox. Changes to

developers.google.com

 

해당 스크립트는 꼭 저장 후 파일 > 버전관리 에서 새로운 버전을 발행 후 게시 > 웹앱게시를 통해 게시를 해줘야 한다.

그럼 해당 링크를 html의 form에서 action으로 지정해주면 된다.

 

 

위 화면에서 버전에 대한걸 저장하고,

위 화면에서 최신 버전을 가져와서 배포 준비를 한다.

최초에는 메일앱을 사용하기 위한 권한 부여를 진행한다.

 

위 주소를 복사해서 form의 action에 입력한다.

form의 각 필드의 name property는 시트에서 지정된 컬럼명을 사용한다.

 

이렇게 해서 submit을 하면 해당 내용은 스프레드 시트에 쌓임과 동시에 메일로 전송이 된다.

script 에서 TO_ADDRESS 변수를 지정한 경우 지정된 메일로 메일이 가며, 주석처리로 냅둔 경우 data-email에 적힌 메일로 전송하게 된다.

 

추가적으로 

https://github.com/dwyl/learn-to-send-email-via-google-script-html-no-server/blob/master/google-apps-script.js

 

위 스크립트 처럼 xhr을 통해 폼데이터 전송으로 사용할 경우 깔끔하게 적용 가능하다.

 

위 깃 주소에 샘플페이지 또한 포함되어 있다.

 

본 글은 아래 글을 참고해 작성하였으며, 아래 글은 더욱 자세히 써있다.

 

 

https://kutar37.tistory.com/entry/%EC%A0%95%EC%A0%81-HTML-form%ED%83%9C%EA%B7%B8%EC%97%90%EC%84%9C-%EB%A9%94%EC%9D%BC%EB%B3%B4%EB%82%B4%EA%B8%B0-Google-Apps-Mail

 

정적 HTML form태그에서 메일보내기 : Google Apps Mail

html에서 mailto를 사용하면, 구현은 물론 간단합니다만 outlook과 같은 쓸데없는 프로그램을 실행해 사용자에게 불편을 초래합니다. 아래와 같이 서버 없는 순수 HTML과 자바스크립트로 메일보내기

kutar37.tistory.com

 

컴포넌트끼리 통신을 하기 위해 props와 $emit 같은 아이들을 사용하고

좀 더 복잡한 관계를 위해 provide/inject 를 사용한다고 했었더랬지...

 

그리고 대규모라면? 더더더 복잡하다면...

 

중앙집중식 저장소 역할을 하는 Vuex가 있다.

(예전에 투비소프트 제품에서 글로벌데이터셋과 비슷한 느낌)

처음에 프로젝트 생성할때 지정해도 되고~(추천)

npm install vuex 해도 되고~

 

자주 사용되는 코드 데이터나, 사용자 정보등을 담아주면 편하겠지 싶은...

 

처음 생성시 지정하면 알아서 store라는 폴더와 그 안에 기초적인 내용물이 생성되고,

main.js 에선 

import store from './store'

위와 같은 코드를 포함 하고 있게 된다.

 

1. state

사용할 변수들을 지정하는 곳!

사용 방법은 아주 간단하다.

2. mutations

이거 잘 모르겠다...

state에 저장된 값을 바꾸려면 직접 바꾸지 말고 이걸 쓰라는데...

직접 바꿔짐...

(strict를 true로 하면 오류남. 근데 운영모드에선 이거 하면 값 변경 감지에 따른 성능에 이슈가 있다고 하니...)

값 변경에 따른 추적을 위해서 라고 하는데~~

여튼 직접 바꾸지말고 이걸 사용하는걸로, 

페이로드 전달이 가능하고 동기방식이라고함.

포인트는 state의 값을 변경 한다는 점!

 

 

3. getters

이건 computed를 생각하면 된다.

기존 데이터(state)를 활용한 추가연산의 로직이 있는 경우 해당 로직을 반복사용하기보단...

computed를 쓰듯이, getters를 활용하면 되는!

 

4. actions

mutations와 비슷하지만 다른!

비동기 처리를 위주로 하고 state를 직접 변경하는 것이 아닌, 내부에서 mutations을 호출하는 형태로 사용한다.

 

 

 

 

state와 mutations가 뭔가 private한 느낌이라면

getters와 actions는 public한 느낌이랄까?

 

간단한 게시판 위주의 커뮤니티 같은 사이트를 제작하려 했으나, 

당분간 일이 바빠질 예정으로 미뤄야 할듯...ㅠ 

지난 글에서 부모에서 자식 컴포넌트로 데이터를 내려주는 props에 대해 작성하였는데!...

props의 단점은 계층구조가 복잡해지면 복잡해 질 수록~~

전달의 전달의 전달 자체가 복잡해 진다는것...ㅠ

 

이럴때 쓰는것이 Provide(상위)/Inject(하위)

 

상위 컴포넌트에서

...
  provide: function () {
    return {
      testProvide: 'testValue'
    }
  },
...

작성하고

 

하위 컴포넌트에서

...
  inject: ['testProvide'],
  mounted () {
    console.log(this.testProvide)
...

위 처럼 작성하면 됨!

계층 구조에 관계없이 순서만 맞으면 inject로 사용 가능하긴한데...

단점은 어떤 상위 컴포넌트에서 오는 데이터인지 알 수 없다는 점!

 

모르면 파일내 찾기라는 방법이 있징!!

혹은 컴포넌트를 알 수 있는 어떤 id라던가? 그런걸 옵션에 지정해 주면 어떨런지?

데이터통신하면 학부시절 D 맞았던 데이터통신을 잊을래야 잊을 수가 없다.

컴공 암기과목 끝판왕. 

 

아래는 Parent.vue

...
    <Children :p-image-style="imageStyle" :p-img-src="imgSrc" @for-child="forChild" ref="imgComp" />
    <div>
      <button @click="callChild">자식함수호출</button>
    </div>
...
import Children from '@/components/Children.vue'

...
  components: {
    Children
  }
...

아래는 Children.vue

<template>
  <div>
    <img :src="imgSrc" :style="imageStyle" ref="img">
    <div>
      <button @click="callParent">부모함수호출</button>
    </div>
  </div>
</template>

<script>
export default {
  name: 'Children',
  props: {
    pImgSrc: {
      type: String,
      required: true
    },
    pImageStyle: {
      type: Object,
      required: false
    }
  },
  mounted () {
    this.imgSrc = this.pImgSrc
    this.imageStyle = this.pImageStyle
  },
  data: function () {
    return {
      imageStyle: {
        maxWidth: '1000px'
      },
      imgSrc: ''
    }
  },
  methods: {
    forParent () {
      console.log('부모 컴포넌트에서 자식 컴포넌트의 함수를 호출')
    },
    callParent () {
      const arg01 = 'value-arg01'
      const arg02 = 'value-arg02'
      this.$emit('for-child', arg01, arg02)
    }
  }
}
</script>

<style scoped>

</style>

 

하나의 컴포넌트에 다른 컴포넌트 요소를 사용하기 위해, 위 처럼 작성을 할 수 있음

Children Element에서 다양한 속성들이 지정되어 있는데, 이에 대하여 알아보자!

 

1. props를 이용한 데이터 전달

children.vue에 props를 보면 pImgSrc와 pImgStyle이 있고, 

parent.vue에는 Children 엘리먼트에

:p-image-style="imageStyle" :p-img-src="imgSrc" 

위와 같은 내용이 있다.

 props에는 카멜로 표기되어 있으나, 위처럼 케밥으로 변경하여 표기해도 되고, 그냥 카멜로 표기해도 상관없음!

 

내용 자체는 간단한...

p-img-src 에 imgSrc를 전달 한다 라는 의미!

 

여기서 중요한 점은 v-bind(:)를 사용했을 때와 아닌때의 차이!

:를 사용하지 않았을 경우에는 단순히 문자열을 전달하는 것이고,

반대로 사용했을때는 data의 값이나 정의된 함수도 전달이 가능한점!

 

주의할점은

:를 사용하면 부모 컴포넌트에서 시시각각 변하는 데이터도 그대로 반영되기 때문에, 자식컴포넌트에서 prop을 그대로 사용하기보단 data로 전달 받아서 사용하는게 좋다고 한다.

 

children.vue의 mounted()를 보면 알 수 있쒀.

 

또한 props에서 type, required, default를 지정 할 수 있는데,

객체나 배열은 default가 팩토리 함수로 생겨먹어야 한다고 한다.

 

2. 부모 컴포넌트에서 자식놈 함수 호출(or 데이터변경)!

이건 뭐 사실 함수뿐 아니라 자식놈 data도 손 쉽게 수정은 가능하다. 바로...

children element의 ref="imgComp" 때문인데...

parent.vue에서 접근하는 방식은 this.$refs.imgComp다...

 

이게 chilren.vue에서는 this = this.$refs.imgComp 같은 맥락이라고 보면 된다.

고로 this.forParent() = this.$refs.imgComp.forParent()

이런셈...

 

 

3. 자식 컴포넌트에서 부모 함수 호출!

이것도 매우 간단하다!

일단 부모에 함수가 있어야 하고,

...

    forChild (arg01, arg02) {
        console.log('for-child', arg01, arg02)
    }

...

자식 컴포넌트를 엘리먼트로 작성해줄때 해당 함수를 사용 할 수 있게끔 속성으로 선언을 해준다.

@for-child="forChild"

위처럼...

이것도 마찬가지로 케밥이든 카멜이든 알아서 잘 되고,

좌변은 자식컴포넌트에서 사용할 이름이고 우변은 부모컴포넌트에 선언된 함수 이름이다.

호출은 자식 컴포넌트에서

...

    callParent () {
      const arg01 = 'value-arg01'
      const arg02 = 'value-arg02'
      this.$emit('for-child', arg01, arg02)
    }

...

 

위 부분을 참고하시믄 되겠다~

자 Data는 지난 글까지해서 대강 끝났어,

이제 Event에 대해 알아볼건데, 여기서는 Mehtods에 만들어진 애들을 사용 할 수 있어.

 

this.$emit 을 사용한 상하위 컴포넌트 간의 통신은 다루지 않을 생각이야, 그냥 쓰면 되는거라...

 

일단 이벤트는 클릭~ 키입력~ 변경~ 뭐 대강 이 정도? 

 

기존에 elements에 onchange, onclick 이런 속성을 사용했다면,

v-on:click, v-on:change, v-on:keyup 이렇게 할 수 있지,

그리고 v-on:이라는 디렉티브는 v-bind:를 :로 바꿀 수 있는 것 처럼,

@로 바꿀수 있어.

v-on:keyup >> @keyup

 

코드
결과

 

자 보면 함수 하나로...세가지 이벤트를 하고 있지

함수 3개 만들기 귀찮았어

 

어때 쉽지? 

 

computed & watch

 

그리고 methods와 비슷하게 computed와 watch가 있는데...

둘의 공통점은 함수 형태를 template에서 data처럼 사용 할 수 있다는거야.

 

근데 watch는 선언된 함수 안에서 사용된 데이터의 변경이 발생하지 않으면, 작동을 안한다는거지!

 

즉, computed는 무조건 실행, watch는 변경시에만 실행 이라는 차이가 있어.

jstl, jsp, freemarker, thymelaef 

이러한 서버사이드에서 렌더링을 해주는 라이브러리들이 있지!

템플릿을 표현함에 있어서 얘네들도 반복과 분기 처리를 하게 해주는 구문이 있었어...

 

Vue도 그런게 당연히 있지.

클라이언트 사이드에서 되는게 그저 신기할뿐...

 

v-for, 그리고 v-if(번외로 v-show)가 있다.

 

디렉티브 이름봐~ 뭐하는 놈인지 딱 알거 같음.

 

사용하는 방법도 매우 간편~

그럼 v-for와 v-if, v-show를 적용해 보겠음.

기존 코드에 적용하기 위해서 v-for는 select의 option에,

그리고 v-if와 v-show는 table element를 만들어서 해볼게.

 

코드
결과

자 일단 배열 데이터 만큼 v-for가 반복해준다는건 알겠지?

그리고 테이블 데이터를 보면 v-if와 v-show에 의해서 데이터가 가려지는것도!(v-else랑 v-else-if는 자매품)

하지만 크롬 콘솔모드에서 elements를 확인해 보면 큰 차이가 있어!

 

바로 v-if는 조건에 충족하지 않으면 렌더링 자체를 안하는 것!

v-show는 display 속성만 none으로 된다는 것!

 

아 그리고 추가적으로 v-for는 2.x때는 :key 라는 디렉티브가 필수가 되었어.

v-for를 쓰려면 꼭 있어야해!

 

그리고~~ 기존 코드와 조금 다른 점이 하나 더 있는데,

바로 v-bind: 디렉티브!

v-bind:value는 :value과 같아. 타이핑 수를 줄일 수 있지.

 

엇 저녁에 딸래미랑 안아주고 화해했음

 

지난글에선 v-model을 사용해서 input과 같은 유형의 elements와 value값을 동기화 시키는 작업을 했더랬지...

 

오늘은 그외 elements들의 속성!! 어트리뷰트(attribute)! 를 제어하는...

vue의 data와 연결하고 값만 띡띡 바꿔주면 동적으로 착착 변하니까 제법 편안한?

(코드 자체가 상당히 깔끔해짐)

 

img의 src와 class랑 style에 data를 바인딩 해보자.

 

v-bind: 를 사용해서 바인딩이 가능하지.

img src는 문자열의 데이터, 그리고 class나 style에 바인딩 되는 데이터는 json object의 형태를 갖고 있어.

 

결과 화면 보자고..

나는야 DIV가 우측정렬에 bold와 font크기의 변화가 있지?

그리고 첨부한 이미지 크기 또한 줄어들어 있어.

 

근데 위 코드를 보며 의문이 드는 부분 없었어?

object항목의 key값을 보면 text-align은 케밥 표기법으로, maxWidth는 카멜 표기법으로 되어 있지?

css의 속성은 모두 케밥 표기법으로 처리가 되는데 말이야...

여기서 css에 해당하는 데이터의 key값은 카멜로 표기해주면 알아서 케밥으로 변경 해준다는 점을 참고하라고.

근데 class는 안되, 그래서 보통 css를 작성할때 케밥 표기법으로 쓰잖아? 그러다보니 홀따옴표로 감싸서 사용해야하지.

 

그리고~

disabled나 readonly 속성 또한 v-bind로 처리가 가능하다는 점을 기억하며

여기서 마무리!

Vue의 장점 중 하나, 앵귤러 처럼 양방향 데이터 바인딩이 가능하다는점!~

제이쿼리나 기본 셀럭터 사용해서  $("#~"), document.getElementById 이런거 안해도 됨!

 

이게 얼마나 큰 차이인지 인지를 못 하는 분들이 간혹 계시던데,

멀리 안보고 성능과 코드 컨디션만 생각해도 엄청난 차이가 있음!

궁금하면 구글링 ㄱㄱ

 

자 그럼 다양한 Elements에 데이터를 바인딩 해보겠음.

Elemtents.vue를 하나 만들자고, new file 하면 안되고, 꼭 New > Vue Component를 해야함.

그래야 기본적인 템플릿이 생성됨.

 

간단하게 몰빵해서 위 처럼 작성해 봤징.

 

그리고 textarea 부분은 양방향 통신인걸 확인 하기 위해서 저렇게 해줬어.

element에서 수정하면 {{textarea}}에서 노출 되는 값도 변하겠지?

 

자 그럼 실행을 확인하기 위해서, index.js에서 방금 만든파일을 추가 하자고,

import Elements from '../views/Elements.vue'

...
const routes = [
...
    {
      path: '/elements',
      name: 'Elements',
      component: Elements
    }
  ]
...

 

그리고 App.vue에서도

<template>
  <div id="nav">
    <router-link to="/">Home</router-link> |
    <router-link to="/about">About</router-link> |
    <router-link to="/Elements">Elements</router-link>
  </div>
  <router-view/>
</template>

/Elements 로 접근하기 위해 한줄 추가.

 

아 물론 이건 없어도 되긴해, 그냥 주소 창에 localhost:8081/Elements 해도 들어가지니까.

위 처럼 되는거야~~

이게 얼마나 편한건지...모르는 분들도 계시겠지만, 

내 생각엔 지금까지 한 이정도만 하더라도 간단한 웹프로젝트는 가능할거라고 생각해.

아마도?ㅋㅋ

 

 

오늘 아침에  딸래미랑 싸우고 딸래미가 안아주지 않고 등원해서 속상함.

 

자 이제 라우터를 사용해보장~~

- 라우팅이란?

 나는 서버용 장비가 생각났어. 삼국지에 나오는 장비 말고, 분전함 같은 그 데이터 네비게이션 같은 역할하는 장비.

여기서는 그냥 웹브라우저에 어떤 주소 입력했는데, 해당 주소에 맞는 페이지를 보여주는거라고 보면 될듯.

미리 지정된 url에 맞는 페이지를 보여주는~~ 스프링에서 url 매핑 생각하면 될듯~~

 

앞선 글에서 나는 플러그인으로 라우터를 이미 설치했지.

 

근데 별도로 설치 할 수도 있쒀.

$ vue add router

위 처럼 cli로 할 수도 있고,

그 vue ui를 실행해서 프로젝트 매니저로 간담에 플러그인에서 추가 할 수도 있지.

설치된 플러그인 확인도 하고, 추가 설치도 가능해.

 

디폴트로 했을때랑 뭐가 다를거 같아?

위에 Home, About 보여?

폴더 구조를 보면 views에 Home.vue랑 About.vue가 있는데,

원래 default로 생성하면 Home.vue의 내용은 App.vue에 있어.

App.vue는 두 화면으로 분기가 가능하게끔 해주지

 

그리고 /src/router/index.js를 살펴보면

routes라는 배열에 두개의 정보가 있어.

각각 Home 과 About에 대한 정보인데,

component 부분을 보면 내용이 살짝 다르네?

아래에 있는 컴포넌트 위에는 주석으로 뭐라고 막 써있엉...

chunk file 에 대해 찾아보면 알테지만, 대략적으로 묶음 단위라고 생각하면 될것 같아.

빌드 이후의 파일 생성할때 하나의 파일로 묶여있으면 엄청난 양의 파일을 로딩해야겠지?

근데 나눠져 있으면 필요한 파일만 로딩하면 되는거고,

그래서 lazy load 기능도 있는건가봐, jpa에서 레이지 로딩 써봤지?

 

글구 여기서 중요한건 위 처럼 하는건 실상 prefetch(리소스를 캐시에 저장) 라는 기능을 쓰는건데,

이건 구글링하면 내용 나올 거고,

 

중요한건 해당 기능을 끄는 방법이지,

 

프로젝트 root에

(root가 어딘지 모르는 사람들도 있으니...프로젝트내 폴더 최상위 말하는거양~~

나도 예전엔 몰랐음. c:\ 에서 삽질했었지)

vue.config.js 라는 파일을 생성하고 prefetch를 안쓴다고 작성해야함.

module.exports = {
  chainWebpack: (config) => {
    config.plugins.delete('prefetch')
  }
}

 

근데 막상 꼭 혹은 자주 이용할것 같은 애들은 그래도 캐시에 올라가 있으면 좋지 않겠어?

    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
    component: () => import(
      /* webpackChunkName: "about" */
      /* webpackPrefetch: true */
      '../views/About.vue')

위 코드를 아래 처럼 바꾸면 되징.

 

그리고 /**/ 이건 꼭 오라클에서 HINT 쓰는거랑 비슷해 보이는데 ㅋㅋ

이건 매직코멘트래 

링크 남길게 이건 

https://webpack.js.org/api/module-methods/#magic-comments

 

Module Methods | webpack

webpack is a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser, yet it is also capable of transforming, bundling, or packaging just about any resource or asset.

webpack.js.org

 

+ Recent posts