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
<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

- URL 해시

#id를 사용해 지정한 anchor(책갈피)로 이동 (한 페이지 내에서 특정 요소 위치로 이동)

 

Vue Router에서는 기본적으로 해시모드를 사용하나 아래와 같이 히스토리 모드를 사용할 수도 있다.

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

hash mode 에서는 URL 해시를 사용하여 전체 URL을 시뮬레이트하므로 URL이 변경될 때 페이지가 다시 로드 되지 않으나 history모드에서도 history.pushState API를 활용하여 페이지를 다시 로드하지 않고도 URL 탐색을 할 수 있다.

 

url에 #이 포함되지 않길 원하면 히스토리 모드를 사용한다.

 

  • 해시 모드가 아닌 히스토리 모드에서 서버는 이 페이지가 새로운 페이지라는 것을 알지 못한다. 예를 들어, 로그인 링크를 클릭했을 때 url이 이동을 하더라도 서버 입장에서는 모른다.
  • 따라서 히스토리 모드에서는 우리의 앱이 적절한 서버 설정이 없는 단일 페이지 클라이언트 앱이기 때문에 사용자가 직접 http://oursite.com/login 에 접속하면 404 오류가 발생한다.
 

HTML5 히스토리 모드 | Vue Router

HTML5 히스토리 모드 vue-router의 기본 모드는 hash mode 입니다. URL 해시를 사용하여 전체 URL을 시뮬레이트하므로 URL이 변경될 때 페이지가 다시 로드 되지 않습니다. 해시를 제거하기 위해 라우터의

router.vuejs.org

 

728x90

!important 무한대 점수(최우선이나 되도록 사용하지 않는 것 추천)

인라인 요소 : 1000점 (마찬가지로 되도록 사용하지 않는 것 추천)

 

전체선택자 ( * ) : 0점

태그 : 1점

클래스 : 10점

ID : 100점

최고점이 동일 점수면 가장 아래 (해석이 맨 나중) 코드가 우선적용

 

예시)

index.html

(...)
<body>    
    <div class="hello">        
        Hello World!
    </div>    
</body>
</html>

main.css

.div {
  color: antiquewhite;
}

div.hello {
  color: gold;
}

.hello {
  color: blue;
}

 

.div : 10점

div.hello : 1 + 10 점

 

728x90

 

stackoverflow.com/questions/15266533/jquery-attrchecked-checked-works-only-once

 

jquery attr('checked','checked') works only once

I have a problem finding reason for the following jquery/checkbox behaviour. $( this.obj + ' table.sgrid-content > thead > tr > th > input.select_all' ).on( 'click' , {grid:this} , fun...

stackoverflow.com

답은 간단하게 .attr 대신  .prop 를 사용하는 것이다.

 

//$('input:checkbox[id="is_include_fees"]').attr("checked", false);
$('input:checkbox[id="is_include_fees"]').prop('checked', false);

 

 

You can change the attribute, and that will also change the property, if the element is untouched. Once the element leaves this initial state, changing the attribute no longer affects the property. The exact behavior probably varies between browsers.

 

 

Instead of .attr('checked', 'cheked') use .prop('checked', true)

+ Recent posts