728x90
반응형 데이터를 만들기 위한 함수

ref

<script setup>
import { ref } from 'vue'

let id = 0

const newTodo = ref('')
const hideCompleted = ref(false)
const todos = ref([
  { id: id++, text: 'HTML 배우기', done: true },
  { id: id++, text: 'JavaScript 배우기', done: true },
  { id: id++, text: 'Vue 배우기', done: false }
])
  • 사용 대상: 모든 종류의 값 (기본 데이터 타입 또는 객체/배열).
  • 접근 방법: .value 속성을 통해 값에 접근하고 변경합니다.
  • 주요 특징: 기본 데이터 타입(예: 문자열, 숫자, 불리언)에 반응성을 부여할 수 있으며, 객체나 배열에도 사용 가능하지만, 단일 값에 대한 반응성을 관리하는 데 주로 사용됩니다.

reactive

<script setup>
import { reactive } from 'vue'

let id = 0

const state = reactive({
  newTodo: '',
  hideCompleted: false,
  todos: [
    { id: id++, text: 'HTML 배우기', done: true },
    { id: id++, text: 'JavaScript 배우기', done: true },
    { id: id++, text: 'Vue 배우기', done: false }
  ]
})
</script>
  • 사용 대상: 객체나 배열.
  • 접근 방법: .value 속성 없이 객체나 배열 내부의 속성에 직접 접근합니다.
  • 주요 특징: 객체나 배열 전체에 대한 반응성을 부여합니다. 중첩된 객체나 배열을 포함하여 구조 내의 모든 데이터에 반응성이 적용됩니다.

 

reactive 사용의 이점

  1. 직관적인 접근과 수정: reactive 객체의 속성에 접근하거나 수정할 때, .value를 사용할 필요가 없습니다. 이는 코드를 좀 더 직관적으로 만들고, 일반 JavaScript 객체와 동일한 방식으로 작업할 수 있게 합니다.
  2. 중첩된 반응성: reactive를 사용하면, 객체 내의 중첩된 속성도 자동으로 반응성이 적용됩니다. 따라서 객체 내부 구조가 복잡해지거나 중첩된 경우에도, 별도의 처리 없이 모든 레벨에서 반응성을 유지할 수 있습니다.
  3. 코드 조직: 여러 반응형 데이터를 하나의 reactive 객체에 그룹화하여 관리할 수 있습니다. 이는 관련 데이터와 로직을 함께 묶어서 관리하기 편리하게 해줍니다, 코드의 가독성과 유지보수성을 향상시킬 수 있습니다.

선택 기준

  • 기본 타입(문자열, 숫자, 불리언 등)에 대한 반응성이 필요한 경우, 또는 Vue 템플릿에서 직접 참조되는 단일 변수에 대해서는 ref를 사용하는 것이 좋습니다.
  • 객체나 배열과 같은 복합적인 데이터 구조에 대해 반응성을 제공하고, 중첩된 데이터 구조를 다루거나 여러 관련 데이터를 함께 관리해야 하는 경우 reactive를 사용하는 것이 더 적합할 수 있습니다.
728x90

전통적인 Options API

 

Vue에서의 스크립트 구현은 크게 두가지 방식이 있다. 전통적인 Options API와 Composition API이다.

전통적인 Options API

<template>
  <div>
    <input v-model="newTodo" @keyup.enter="addTodo">
    <ul>
      <li v-for="todo in todos" :key="todo.id">
        {{ todo.text }}
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  data() {
    return {
      newTodo: '',
      todos: [],
      nextId: 0
    }
  },
  methods: {
    addTodo() {
      this.todos.push({ id: this.nextId++, text: this.newTodo });
      this.newTodo = ''; // 입력 필드 초기화
    }
  }
}
</script>

Composition API

Vue 3의 Composition API는 컴포넌트 로직을 구성하는 새로운 방법을 제공합니다. 이 API의 도입은 Vue 애플리케이션을 설계하고 개발하는 방식에 근본적인 변화를 가져왔습니다. Composition API의 특징과 장점은 다음과 같습니다:

특징

  1. 반응형 상태 정의: refreactive 함수를 사용하여 반응형 상태를 선언적으로 정의할 수 있습니다. 이 상태들은 컴포넌트의 템플릿에서 직접 사용될 수 있으며, 상태 변경 시 자동으로 화면을 업데이트합니다.
  2. setup 함수: 컴포넌트의 반응형 상태, 계산된 속성, 메서드 등 모든 로직을 setup 함수 내에 정의합니다. setup 함수는 컴포넌트의 옵션/라이프사이클 훅보다 먼저 실행되며, 여기에서 정의된 모든 값과 함수는 템플릿에서 직접 사용할 수 있습니다.
  3. 함수 기반의 구성: 로직을 재사용 가능한 함수로 캡슐화하고 조합하여 컴포넌트를 구성할 수 있습니다. 이러한 접근 방식은 컴포넌트 간에 코드를 재사용하고 조합하기 쉽게 만듭니다.

장점

  1. 로직의 재사용 및 조직화: Composition API를 사용하면 로직을 기능별로 구성하고 필요한 곳에서 재사용할 수 있습니다. 이는 코드의 중복을 줄이고, 프로젝트의 유지보수성을 향상시킵니다.
  2. 유연성: 컴포넌트의 로직을 더 유연하게 조직할 수 있습니다. 예를 들어, 관련된 모든 반응형 상태와 함수를 함께 그룹화하여 관리할 수 있으며, 이는 컴포넌트의 가독성을 크게 향상시킵니다.
  3. 타입스크립트와의 호환성: Composition API는 타입스크립트와 더욱 잘 호환됩니다. setup 함수 내에서 정의된 상태와 함수에 타입을 적용하기 쉬워, 타입스크립트를 사용하는 프로젝트에서 타입 안정성과 개발 경험을 향상시킬 수 있습니다.
  4. 응집력 있는 코드 베이스: 기능별로 로직을 그룹화하고 재사용할 수 있기 때문에, 관련 로직이 물리적으로 가까운 위치에 있게 됩니다. 이는 응집력 있는 코드 베이스를 유지하는 데 도움이 됩니다.
  5. 더 나은 성능: Composition API를 사용하면 필요한 로직만을 정확히 구성하여 사용할 수 있기 때문에, 불필요한 로직의 실행을 최소화할 수 있습니다. 이는 애플리케이션의 성능을 최적화하는 데 기여할 수 있습니다.

Composition API는 Vue 애플리케이션을 개발할 때 더 큰 유연성과 향상된 코드 재사용성을 제공합니다. 이는 특히 대규모 애플리케이션 또는 복잡한 컴포넌트 구조를 가진 프로젝

트에서 그 장점이 두드러집니다.

Vue 3 초기 버전에서의 Composition API 사용 예시

<template>
  <div>
    <input v-model="newTodo" @keyup.enter="addTodo" />
    <ul>
      <li v-for="todo in todos" :key="todo.id">{{ todo.text }}</li>
    </ul>
  </div>
</template>

<script>
import { ref } from 'vue';

export default {
  setup() {
    const newTodo = ref('');
    const todos = ref([]);

    const addTodo = () => {
      todos.value.push({ id: todos.value.length + 1, text: newTodo.value });
      newTodo.value = '';
    };

    return { newTodo, todos, addTodo };
  }
};
</script>

Vue 3 초기 버전에서 Composition API를 사용할 때는 setup 함수 내에서 컴포넌트의 반응형 상태, 계산된 속성, 메서드 등을 정의하고, 필요한 값들을 객체로 반환하여 템플릿에서 사용할 수 있도록 했습니다.

 

Vue 3.2 이후에서의 <script setup> 구문 사용 예시

Vue 3.2부터 도입된 <script setup> 구문을 사용하면, setup 함수 내에서 반환 과정 없이 직접 변수와 함수를 정의할 수 있으며, 이들은 자동으로 템플릿에서 사용 가능해집니다. 이로 인해 코드가 더욱 간결하고 선언적으로 변화했습니다.

 

<template>
  <div>
    <input v-model="newTodo" @keyup.enter="addTodo" />
    <ul>
      <li v-for="todo in todos" :key="todo.id">{{ todo.text }}</li>
    </ul>
  </div>
</template>

<script setup>
import { ref } from 'vue';

const newTodo = ref('');
const todos = ref([]);

const addTodo = () => {
  todos.value.push({ id: todos.value.length + 1, text: newTodo.value });
  newTodo.value = '';
};
</script>

주요 차이점

  • 코드 간결성: <script setup> 구문을 사용하면, 컴포넌트의 로직을 더욱 간결하게 작성할 수 있습니다. setup 함수 내에서 반환 과정 없이 모든 로직을 정의할 수 있으며, 이는 코드의 가독성과 유지보수성을 크게 향상시킵니다.
  • 자동 import 추론: <script setup>은 IDE와 도구에서 더 나은 타입 추론과 자동 완성을 제공합니다. 또한, Vue 컴파일러는 <script setup> 내에서 사용된 Vue API를 자동으로 감지하여 필요한 코드를 자동으로 import 합니다.
  • 컴포넌트 정의의 선언적 표현: <script setup> 구문은 컴포넌트의 정의를 더 선언적으로 만들어 줍니다. 이는 Vue 컴포넌트의 구조와 로직을 더 명확하게 표현할 수 있게 해줍니다.

<script setup> 구문은 Vue 3.2 이상에서 Composition API를 사용하는 새로운 표준이 되었으며, 많은 개발자들이 이 새로운 패턴을 선호하고 있습니다.

728x90

Template

 <tr
    v-for="(diary, idx) in f_rec_diary_list"
    :key="idx"
    draggable="true"
    @dragstart="drag_area(idx, 'M')"
    @dragend="drag_end_area"
    @dragover.prevent
    @dragenter="drag_enter_area(idx)"
    @drop="drop_area(idx, f_rec_diary_list)"
>

 

Data

data() {
        return {            
            dragged_area_index: null,
            hover_area_index: null,
            dragged_item_index: null,
            hover_item_index: null,
            dragged_type: null,
        };
},

 

Methods

drag_area(index, type) {
    console.log("drag_area -> index", index, "type", type);
    this.dragged_area_index = index;
    this.dragged_type = type;
},
drag_enter_area(index) {
    this.hover_area_index = index;
},
drag_end_area() {
    this.hover_area_index = null;
},
async drop_area(drop_index, parent) {
    if (this.dragged_type !== "M") {
        return;
    }

    const dragged_item = parent.splice(this.dragged_area_index, 1)[0];
    parent.splice(drop_index, 0, dragged_item);

    console.log('parent', parent);

    // Update seq_no values after reordering
    for (let i = 0; i < parent.length; i++) {
        parent[i].seq_no = i + 1;
    }

    console.log("dragged_item", dragged_item);

    this.dragged_area_index = null;
    this.hover_area_index = null;
    this.dragged_type = null;
},
drag_item(index, type) {
    this.dragged_item_index = index;
    this.dragged_type = type;
},
drag_enter_item(index) {
    this.hover_item_index = index;
},
drag_end_item() {
    this.hover_item_index = null;
},
728x90

MathJax는 웹 브라우저에 수학 표기법을 표시하기 위한 JS Library이며 아래와 같은 형식을 따른다.

\(-{1 \over {500}}x + 212\)

 

프론트엔드에서 위 MathJax 수식을 올바르게 보여주기 위해 아래 과정이 필요하다.

 

1. nuxt.config.js의 head에 스크립트 코드 추가

 // Global page headers: https://go.nuxtjs.dev/config-head
    head: {
         ( ... ) 
        script: [
            {
              src: 'https://polyfill.io/v3/polyfill.min.js?features=es6',
              type: 'text/javascript',
              body: true
            },
            {
              src: 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js',
              type: 'text/javascript',
              body: true
            }
        ]
    },

 

2. 프론트 페이지의 mounted에 아래 코드 추가

async mounted() {
    // mathjax 수식 렌더링 적용
    if (window.MathJax) {
        window.MathJax.typeset();
    }
}

 

그러면 아래와 같은 html 요소가 있을 때 수식이 제대로 보여지게 된다.

<p v-html="math_exp"></p>
 
data() {
	return {
		math_exp : "<div class="math">&nbsp;<p>The graph of \(y = 3x - 5\) in the \(xy\)-plane is a line. What is the slope of the line?</p></div>"
}

728x90

라디오박스라면 하나만 체크되니 css 를 수정해서 체크박스처럼 보일 수도 있겠지만

체크박스로 이미 퍼블이 된 상태에서 수정할 필요가 있어 직접 코드를 짜보았다.

 

템플릿내 코드 

 <input type="checkbox" v-model="pay_method.card" name="chkbox" id="card"
 @change="check_one( {type:'card' })" >
                            
<input type="checkbox" v-model="pay_method.bank" name="chkbox"  @change="check_one( {type:'bank' })"
 id="noBankBook">

 

data 정의

data(){
        return{            
            pay_method: { card: true, bank: false },
        }
    },

method 정의

methods: {
	check_one(element) {
      console.log('checkbox check : ', element.type)
      let obj = this.pay_method

      if (element.type) {
        for(const [key, value] of Object.entries(obj)) {          
          console.log(`${key}: ${value}`);

          if (key == element.type) {
            obj[key] = true
          } else {
            obj[key] = false
          }
        }

        const check = document.getElementById(`${element.type}`);
        
        if (check && check.checked != undefined) {
          check.checked = true;
        }
        console.log('checked', check.checked)
      } 

      console.log('type', JSON.stringify(this.search_type))

    },
}

'Web Develop > Web Programming' 카테고리의 다른 글

WebRTC 및 Node 등 스터디  (0) 2022.02.25
Spring Boot시작하기  (0) 2021.08.10
html 기초  (0) 2021.01.07
반응형 웹 만들기  (0) 2017.03.23
HTML 5 미지원 브라우저 고려하기  (0) 2017.03.21
728x90
<script>
const TYPE = Object.freeze({
    ONE: 0, TWO: 1,THREE: 2
})
export default{
 ( ... )
}
</script>

위와 같이 const로 정의하고 Object.freeze하면 변경 불가능한 enum 상수가 된다.

 

TYPE.ONE과 같이 접근가능하고

백엔드에서는 value인 0값을 받아 처리가능하다.

728x90
<input v-model="inputText" @keyup.enter="input_key" type="text" placeholder="입력후 엔터를 눌러주세요">

위와 같은 input이 있을 경우 안드로이드 앱의 웹뷰에서 엔터를 감지하지 못하는 현상이 있다.

 

참고 : https://blog.naver.com/crucifyer/222749456743

 

Android Web Form - Enter Event 동작의 이상함.

평소 안드로이드를 안써서 몰랐는데, input type=text 에서 엔터를 눌렀을 경우 모든경우에 엔터로 ...

blog.naver.com

 

iOS에는 해당 문제가 없다.

textarea로 바꾸니 해결. 스타일을 input 박스와 동일하게 해주기 위해 인라인 태그도 추가해주었다.

<textarea rows="1" v-model="inputText" @keyup.enter="input_key" 
 style="min-height: 0px; resize: none; "  placeholder="입력후 엔터를 눌러주세요">
</textarea>

 

아주 오래된 글이지만 아래와 같은 포럼글도 있으니 참고

https://issuetracker.google.com/issues/36993179

 

Google Issue Tracker

 

issuetracker.google.com

 

728x90

자식창은 닫고 부모창의 경로를 이동하는 방법이다. (vue에서도 적용가능)

 

// 자식 (팝업창)
opener.location.replace("https://123.co.kr/test/");
window.close();

 

728x90

1. node에서 jar파일을 불러올 수 있는 java패키지 설치

https://www.npmjs.com/package/java

 

java

Bridge API to connect with existing Java APIs.. Latest version: 0.12.2, last published: 10 months ago. Start using java in your project by running `npm i java`. There are 155 other projects in the npm registry using java.

www.npmjs.com

npm i java

2. 프로젝트에 jar파일 추가

 

3. 코드 연동

연동 시에 결과를 리턴받으려면 정의한 함수 뒤에 Sync를 붙여주면된다.

예) getMethod   -> getMethodSync

var java = require("java")
java.classpath.push("./test_JDK18.jar")

var something = java.import('com.test.comm.some.Manager'); 
var instance = new something(); // 인스턴스 생성

console.log('instance', instance);
console.log('===================test', instance.getMethodSync("test", ""))

 

728x90

WebRTC 특징

웹에서 사용할 수 있는 P2P 기술

  • 기본적으로 별도의 서버를 사용하지 않으므로 두 피어가 연결 방법을 공유하기 위한 가상의 신호 서비스인 Signalling 사용
  • 클라이언트가 동일 로컬 네트워크가 아닌 이상 다이렉트 소켓을 사용할 수 없는 경우(P2P연결불가)가 많으므로, 릴레이 서버인 TURN 서버를 사용
  • UDP 기반

  • 1:1 , 1:N, N:N 응용서비스 개발 모두 가능

1:1 - 카카오 보이스톡

1:N - 방송서비스 (대량 접속 환경에선 P2P 성격은 버려짐)

N:N - 화상회의형서비스

WebRTC 어려움

  • 관련 기술 문서 부족
  • UDP기반의 RTP프로토콜로 품질 불확실성
  • 고난이도의 미디어 처리

강의 : https://nomadcoders.co/noom

줌 클론코딩

WebSockets, SocketIO, WebRTC

요구사항 :

ExpressJS, app.get(), Pug, JS

Node v14.17.3 이상

pug

: html을 조금 더 세련되게 쓸 수 있는 템플릿 언어. express 뷰 엔진

node.js

__filename 은 현재 실행 중인 파일 경로

__dirname 은 현재 실행 중인 폴더 경로

위는 CommonJS 모듈내에서만 동작하며 ES모듈에서는 동작안하므로 아래 코드 추가 필요

import path from 'path';
const __dirname = path.resolve();

“Uncaught SyntaxError: Cannot use import statement outside a module” 에러시 package.json에 아래 코드 추가

 "type": "module",

express내에서 템플릿 엔진을 사용하려면
app.set으로 설정

https://expressjs.com/ko/guide/using-template-engines.html

Express와 함께 템플리트 엔진 사용

Express와 함께 템플리트 엔진을 사용 Express가 템플리트를 렌더링하려면 다음과 같은 애플리케이션 설정이 필요합니다. views, 템플리트가 있는 디렉토리. 예: app.set('views', './views') view engine, 사용할

expressjs.com

nodemon 특정 경로 파일 수정할때는 재시작되지 않도록 설정하려면 nodemon.js에 ignore 추가

{
    "ignore": ["src/public/*"],
    "exec": "babel-node src/server.js"
}

바벨은 그 자체로 아무것도 하지 않으므로 플러그인을 사용해야한다.

babel foundation에서는 plugin들을 포함한 번들파일을 포함한 preset을 제공하며 (plugin 자동 설치) "@babel/preset-env"는 공식적인 기본 프리셋이다.

https://developer.mozilla.org/ko/docs/Web/API/WebSocket

WebSocket - Web API | MDN

WebSocket 객체는 서버와의 WebSocket 연결을 생성하고 관리할 수 있는 API 들을 제공합니다. 이는 데이터를 전송하거나 주고 받는 등의 API 들을 포함합니다.

developer.mozilla.org

webSocket에는 아래와 같이 자유롭게 어트리뷰트를 추가하고 설정할 수 있다.

 socket["nickname"] = parsedMsg.payload;

SocketIO

소켓IO는 웹소켓의 일부분이 아니다. 대부분의 브라우저가 웹소켓을 지원하지만 미지원인 경우 롱폴링(long polling) 으로 연결이 이뤄진다.

*클라이언트가 서버에 있는 정보를 요청하면 지정한 시간동안 연결을 열어둔다. 서버에 정보가 없으면 클라이언트가 요청한 정보가 생길 때 까지 또는 지정한 시간이 끝날 때까지 해당 요청을 열어둔다. 지정 시간이 끝나면 클라이언트는 서버에 있는 정보를 다시 요청한다. 코멧은 서버가 클라이언트로 뭔가를 송신할 수 있을때까지 HTTP 응답 완료를 지연시킨다. 이 기법을 'GET' 또는 '미결 POST(pending -POST) 라고 부른다.

+ Recent posts