https://developer.mozilla.org/en-US/docs/Web/API/Element/compositionstart_event 

ㅇ를 입력하면 초성, 중성, 종성을 조합을 할 수 있게 되면서 compositionstart가 trigger되는 듯 하다.

document.addEventListener('compositionstart', function(e){
	debugger;
});

 

'정보 > Front' 카테고리의 다른 글

[React] 이벤트핸들링, ref  (0) 2022.09.26

https://ko.wikipedia.org/wiki/%EC%9C%84%EC%A7%80%EC%9C%84%EA%B7%B8#cite_note-2  // 용어공부

 

위지위그 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 위지위그(WYSIWYG: What You See Is What You Get, "보는 대로 얻는다")[1]는 인쇄된 문서, 웹 페이지, 슬라이드 프레젠테이션 등 완성된 결과물로서 인쇄 또는 표시될 때의

ko.wikipedia.org

 

Sencha htmlEditor를 이용할 때 IE와 Chrome에서 동작 차이

sencha extjs의 htmlEditor: https://examples.sencha.com/extjs/7.8.0/examples/kitchensink/#froala-document-ready 

참고로 IE디버깅을 위해서는 Edge를 켜고 IE로 로드, IE 개발자도구 (%systemroot%\system32\f12\IEChooser.exe) 를 통해 IE전용 디버그 툴을 열어야 가능하다. 

 

그리고 htmlEditor에 줄바꿈을 넣고 싶었는데, <br><br>을 두개 넣어야 cursor까지 옮길 수 있었다. 

<br>을 하나만 넣었을 때는 입력하고있던 cursor가 옮겨지지 않았는데 두개 넣으니 옮겨지더라. 

 

stackoverflow의 아래를 읽고 시도해보았다. 

https://stackoverflow.com/questions/20552474/how-does-execcommand-insertbronreturn-work 

 

How does execCommand "insertBrOnReturn" work?

I tried the following code on Chrome: document.execCommand("insertBrOnReturn", false, true); http://jsfiddle.net/uVcd5/ Wether I set the last parameter to true or false, the behaviour doesn't ch...

stackoverflow.com

 

첫 번째 차이점, <br> 태그 chrome에서는 사라지고 IE에서는 남아있다. 

줄바꿈 직 후
텍스트 입력 후

텍스트 입력 후에 두번째 <br>이 사라져있음을 볼 수 있다.

 

하지만 IE에서는 ?

줄바꿈 직 후
텍스트 입력 후

두번째 <br>태그가 여전히 남아있는 것으로 확인된다.

 

p태그를 추가하였을 때, 재밌는 현상이 있는데,

enter 직 후

<br>태그도 같이 생성된다는 것이다.

텍스트 입력 후

텍스트를 입력하면 (개발자도구에서 해당 element를 선택해놓고 텍스트입력을 해보면) <br>태그가 텍스트 입력했을 때 사라져있음을 볼 수 있다. 

하지만 IE에서는 텍스트를 입력했어도 뒤에 <br /> 태그가 남아있었다. 

 

enter 직 후
텍스트 입력 후

 

두 번째 차이점, range의 범위가 다르다. 

let selection = document.getSelection();
let range = selection.getRangeAt(0);
let currentNode = range.startContainer;

currentNode를 확인해보면 Chrome에서는 한글을 입력에 enter를 쳐서 확인해도 range의 startOffset과 endOffset이 같은데,  IE에서는 한글을 입력중에 엔터를 친 경우에 아직 조합이 끝났다고 보지않아 startOffset과 endOffset이 차이가 있었다. 

https://ko.javascript.info/comparison

 

비교 연산자

 

ko.javascript.info

 

 

equality operator (==) strict equality operator (===)
0과 false를 구별하지 못한다.
''(빈문자열)과 false를 구별하지 못한다.
자료형의 동등여부까지 검사한다. 
비교할 때 피연산자를 숫자형으로 바꾼다.
'01' == 1 // true
형 변환 없이 값을 비교할 수 있다.
'01' === 1 // false
피연산자가 undefined나 null일 때 형 변환을 하지 않는다.  

 

alert('01' == 1); //true
alert('01' === 1); //false

alert(null >= 0); //true
alert(null <= 0); //true
alert(null == 0); //false
alert(null == undefined); //true

alert(undefined >= 0); //false
alert(undefined <= 0); //false

alert(isNaN(undefined)); //true

 

null은 기타 비교 연산자(>, <. >=, <=)와 연산될 때는 숫자형으로 변환돼 0으로 취급된다. 

undefined는 숫자형으로 변환될 때 NaN으로 변환된다. NaN이 피연산자인 경우 비교 연산자는 항상 false를 반환한다.

아래 포스팅 참고

 

/xl/sharedStrings.xml ~

 

xlsx 확장자를 zip으로 바꾼 후 /xl/sharedStrings.xml 파일을 열어 error가 나는 문자열을 확인한다.

 

 

https://bathildis.tistory.com/76 

 

[ABAP] 엑셀다운로드 후 파일이 깨질 때 원인 찾는 방법

읽을 수 없는 내용을 복구하거나 제거하여 파일을 열 수 있습니다. 제거된 요소: XML 오류가 있는 /xl/sharedStrings.xml 부분. (문자열) 잘못된 xml 문자입니다. 1 행, 440759 열. 제거된 레코드: /xl/worksheets/

bathildis.tistory.com

 

 

https://velog.io/@hslim8888/%EC%97%91%EC%85%80%EC%9D%B4-ZIP-%ED%8C%8C%EC%9D%BC%EC%9D%B4%EC%97%88%EB%8B%A4%EB%8B%88

 

엑셀이 ZIP 파일이었다니!!

외부에 엑셀 파일 업로드 API를 연동했는데, 에러가 난다고 해 살펴보니 xlsx 포맷이 아니라 csv 포맷을 올려서 문제였던 것.openpyxl 라이브러리를 이용해 엑셀 파일을 열게끔 코드가 짜져있었는데,

velog.io

 

https://learn.microsoft.com/en-us/previous-versions/office/developer/office-xp/aa140066(v=office.10)?redirectedfrom=MSDN

 

XML Spreadsheet Reference

XML Spreadsheet Reference Article 06/14/2014 In this article --> This content is no longer actively maintained. It is provided as is, for anyone who may still be using these technologies, with no warranties or claims of accuracy with regard to the most rec

learn.microsoft.com

 

str.replace(/([\u2700-\u27BF]|[\uE000-\uF8FF]|\uD83C[\uDC00-\uDFFF]|\uD83D[\uDC00-\uDFFF]|[\u2580-\u27BF]|\uD83E[\uDD10-\uDDFF])/g, '');

 

참고

https://stackoverflow.com/questions/10992921/how-to-remove-emoji-code-using-javascript

 

How to remove emoji code using javascript?

How do I remove emoji code using JavaScript? I thought I had taken care of it using the code below, but I still have characters like 🔴. function removeInvalidChars() { return this.replace(/[\...

stackoverflow.com

 

ScrollView는 여러 컴포넌트와 view를 담을 수 있는 스크롤되는 container

 

https://reactnative.dev/docs/using-a-scrollview

 

Using a ScrollView · React Native

The ScrollView is a generic scrolling container that can contain multiple components and views. The scrollable items can be heterogeneous, and you can scroll both vertically and horizontally (by setting the horizontal property).

reactnative.dev

 

import React from 'react';
import {Image, ScrollView, Text} from 'react-native';

const logo = {
  uri: 'https://reactnative.dev/img/tiny_logo.png',
  width: 64,
  height: 64,
};

// 아래로 스크롤바를 밀어서 페이지 이동할 수 있다. 
// pagiongEnabled prop을 넣으면 swipe 될 때 scroll view의 size 몇 개를 넘기고 멈춘다. 
// 자세한 사항: https://reactnative.dev/docs/scrollview#pagingenabled
// maximumZoomScale, minimumZoomScale prop을 통해서 사용자가 줌인, 줌아웃 가능하게 할 수도 있음.
// 화면에 맞지 않는 긴 리스트가 있다면 FlatList 사용 권장
const App = () => (
  <ScrollView>
    <Text style={{fontSize: 96}}>Scroll me plz</Text>
    <Image source={logo} />
    <Image source={logo} />
    <Image source={logo} />
    <Image source={logo} />
    <Image source={logo} />
    <Text style={{fontSize: 96}}>If you like</Text>
    <Image source={logo} />
    <Image source={logo} />
    <Image source={logo} />
    <Image source={logo} />
    <Image source={logo} />
    <Text style={{fontSize: 96}}>Scrolling down</Text>
    <Image source={logo} />
    <Image source={logo} />
    <Image source={logo} />
    <Image source={logo} />
    <Image source={logo} />
    <Text style={{fontSize: 96}}>What's the best</Text>
    <Image source={logo} />
    <Image source={logo} />
    <Image source={logo} />
    <Image source={logo} />
    <Image source={logo} />
    <Text style={{fontSize: 96}}>Framework around?</Text>
    <Image source={logo} />
    <Image source={logo} />
    <Image source={logo} />
    <Image source={logo} />
    <Image source={logo} />
    <Text style={{fontSize: 80}}>React Native</Text>
  </ScrollView>
);

export default App;

 

FlastList 변하지만 구조적으로 유사한 데이터의 스크롤되는 리스트를 담는 컴포넌트. 시간이 지남에 따라 변하는 아이템이 있는 데이터의 긴 리스트에 잘 작동한다.

★ 일반적인 ScrollView와 달리 화면에 현재 보이는 요소들만 렌더링한다. 한 번에 모드 요소를 렌더링하지 않음. ★

FlastList 컴포넌트는 data와 rederItem 두 가지의 prop이 필수이다. data는 리스팅할 데이터. renderItem은 데이터에서 하나 꺼내서 렌더링되는 컴포넌트를 돌려준다. 

import React from 'react';
import {FlatList, StyleSheet, Text, View} from 'react-native';

const styles = StyleSheet.create({
  container: {
    flex: 1,
    paddingTop: 22,
  },
  item: {
    padding: 10,
    fontSize: 18,
    height: 44,
  },
});

const FlatListBasics = () => {
  return (
    <View style={styles.container}>
      <FlatList
        data={[
          {key: 'Devin'},
          {key: 'Dan'},
          {key: 'Dominic'},
          {key: 'Jackson'},
          {key: 'James'},
          {key: 'Joel'},
          {key: 'John'},
          {key: 'Jillian'},
          {key: 'Jimmy'},
          {key: 'Julie'},
        ]}
        // 데이터들을 전부 Text 컴포넌트로 렌더링 된다. 
        renderItem={({item}) => <Text style={styles.item}>{item.key}</Text>}
      />
    </View>
  );
};

export default FlatListBasics;

 

section header 를 통해 논리적으로 구분되는 데이터를 렌더링하고 싶으면 SectionList를 사용할 수 있다.

 

import React from 'react';
import {SectionList, StyleSheet, Text, View} from 'react-native';

const styles = StyleSheet.create({
  container: {
    flex: 1,
    paddingTop: 22,
  },
  sectionHeader: {
    paddingTop: 2,
    paddingLeft: 10,
    paddingRight: 10,
    paddingBottom: 2,
    fontSize: 14,
    fontWeight: 'bold',
    backgroundColor: 'rgba(247,247,247,1.0)',
  },
  item: {
    padding: 10,
    fontSize: 18,
    height: 44,
  },
});

const SectionListBasics = () => {
  return (
    <View style={styles.container}>
      <SectionList
        sections={[
          {title: 'D', data: ['Devin', 'Dan', 'Dominic']},
          {
            title: 'J',
            data: [
              'Jackson',
              'James',
              'Jillian',
              'Jimmy',
              'Joel',
              'John',
              'Julie',
            ],
          },
        ]}
        renderItem={({item}) => <Text style={styles.item}>{item}</Text>}
        renderSectionHeader={({section}) => (
          <Text style={styles.sectionHeader}>{section.title}</Text>
        )}
        keyExtractor={item => `basicListEntry-${item}`}
      />
    </View>
  );
};

export default SectionListBasics;

list view 공통의 특징으로 서버에서 가져오는 데이터를 보여준다. 

서버에서 가져오는 데이터에 관한 자세한 문서: https://reactnative.dev/docs/network 

'정보 > App' 카테고리의 다른 글

[React Native] The Basics: Handling Text Input  (0) 2024.11.27
[React Native] The Basics: React Fundamentals  (0) 2024.11.26

Text input은 사용자가 글을 입력할 수 있게하는 핵심 컴포넌트.

onChangeText: 텍스트가 변할때마다 호출되는 함수

onSubmitEditing: submit될 때 호출되는 함수

 

https://reactnative.dev/docs/handling-text-input

 

Handling Text Input · React Native

TextInput is a Core Component that allows the user to enter text. It has an onChangeText prop that takes a function to be called every time the text changed, and an onSubmitEditing prop that takes a function to be called when the text is submitted.

reactnative.dev

 

import React, {useState} from 'react';
import {Text, TextInput, View} from 'react-native';

const PizzaTranslator = () => {
  // text는 시간에 따라 변하므로 state에 저장한다.
  const [text, setText] = useState('');
  return (
    <View style={{padding: 10}}>
      <TextInput
        style={{height: 40}}
        placeholder="Type here to translate!"
        onChangeText={newText => setText(newText)}
        defaultValue={text}
      />
      <Text style={{padding: 10, fontSize: 42}}>
        {text
          .split(' ')
          .map(word => word && '🍕')
          .join(' ')}
      </Text>
    </View>
  );
};

export default PizzaTranslator;

 

※ 변하는 것만 re-render 한다.

https://react.dev/reference/react-dom/components/input#controlling-an-input-with-a-state-variable 

 

<input> – React

The library for web and native user interfaces

react.dev

 

// AS-IS
function App() {
  /* 여기에서 키보드 타자를 칠 때마다 (onChange될 때 마다) 
     setFirstName 을 통해 함수를 호출하고 다시 렌더링 되는데, 
     re-rendering performance를 최적화 하기 위해서는,
     <PageContent /> 는 input의 state에 영향을 받지 않으므로
     input의 state를 다루는 컴포넌트를 따로 만든다. */
  const [firstName, setFirstName] = useState('');
  return (
    <>
      <form>
        <input value={firstName} onChange={e => setFirstName(e.target.value)} />
      </form>
      <PageContent />
    </>
  );
}

// TO-BE
function App() {
  return (
    <>
      <SignupForm />
      <PageContent />
    </>
  );
}

function SignupForm() {
  const [firstName, setFirstName] = useState('');
  return (
    <form>
      <input value={firstName} onChange={e => setFirstName(e.target.value)} />
    </form>
  );
}
/* 이 경우 performance가 상당히 향상되는데, 
   이제는 키입력에 따라 onChange 이벤트가 호출될 때,
   SignupForm만 다시 렌더링하기 때문이다. */

https://reactnative.dev/docs/intro-react

 

React Fundamentals · React Native

To understand React Native fully, you need a solid foundation in React. This short introduction to React can help you get started or get refreshed.

reactnative.dev

 

공식문서 읽고 공부...:) 

 

The Basics

import React from 'react';
import {Text} from 'react-native';

// 컴포넌트는 함수로 시작.
const Cat = () => {};
// 컴포넌트를 청사진으로 간주. 함수 컴포넌트가 return하는 무엇이든간에 React element로 랜더링 된다.
// React element는 스크린에 보고싶은 것을 묘사해줌.

// 예시로 <Text>를 렌더링하는 Cat 컴포넌트.
const Cat = () => {
  return <Text>Hello, I am your cat!</Text>;
};

// export default를 통해 어플에 걸쳐서 사용할 수 있게 export 할 수 있다. 
export default Cat;

 

Curly Braces

import React from 'react';
import {Text} from 'react-native';

// 중괄호{} 안에 변수 값을 넣을 수 있다. 
const Cat = () => {
  const name = 'Maru';
  return <Text>Hello, I am {name}!</Text>;
};

const getFullName = (
  firstName: string,
  secondName: string,
  thirdName: string,
) => {
  return firstName + ' ' + secondName + ' ' + thirdName;
};

// 중괄호{} 안에 함수를 넣을 수 있다.
const Cat = () => {
  return <Text>Hello, I am {getFullName('Rum', 'Tum', 'Tugger')}!</Text>;
};

export default Cat;

이런 JSX 문법은 React library안에 있는 것이므로 import React from 'react' 를 작성하지 않으면 기능하지 않는다. 

 

import React from 'react';
import {Text, TextInput, View} from 'react-native';

const Cat = () => {
  return (
  // <View>안에 <Text>와 <TextInput>을 들여쓰면 React Native는 함께 랜더링 한다. 
    <View>
      <Text>Hello, I am...</Text>
      <TextInput
        style={{
          height: 40,
          borderColor: 'gray',
          borderWidth: 1,
        }}
        defaultValue="Name me!"
      />
    </View>
  );
};

export default Cat;
import React from 'react';
import {Text, View} from 'react-native';

const Cat = () => {
  return (
    <View>
      <Text>I am also a cat!</Text>
    </View>
  );
};

// 다른 컴포넌트를 렌더링하는 컴포넌트를 parent component라고 한다.
// 여기에서는 Cafe가 parent component이고, Cat이 child component이다. 
const Cafe = () => {
  return (
    <View>
      <Text>Welcome!</Text>
      <Cat />
      <Cat />
      <Cat />
    </View>
    /* Cat 컴포넌트를 <Cat> 을 사용함으로써 여러번 렌더링 시킬 수 있다.  */
  );
};

export default Cafe;

 

import React from 'react';
import {Text, View} from 'react-native';
//Props는 properties의 줄임말로 Props를 통해 React component를 커스터마이징 할 수 있다.

// 각각의 Cat이 다른 name을 갖게 하는 예제이다. 
type CatProps = {
  name: string;
};

const Cat = (props: CatProps) => {
  return (
    <View>
      <Text>Hello, I am {props.name}!</Text>
    </View>
  );
};

const Cafe = () => {
  return (
    <View>
      <Cat name="Maru" />
      <Cat name="Jellylorum" />
      <Cat name="Spot" />
    </View>
  );
};

export default Cafe;
import React from 'react';
import {Text, View, Image} from 'react-native';

const CatApp = () => {
  return (
  /* <Image>를 사용할 경우 source라는 prop을 이용한다. 
     {{ }} 를 주목해보면 두 개의 중괄호가 있다.
     JSX에서 JavaScript 값은 {}로 참조되는데, 이것은 문자열보다 props로 넘길 때 유용하다.
     하지만 JS오브젝트 또한 중괄호로 표시된다. 
     따라서 JS오브젝트를 JSX에서 넘길 때 {}로 감싸게 된다.*/
    <View>
      <Image
        source={{
          uri: 'https://reactnative.dev/docs/assets/p_cat1.png',
        }}
        style={{width: 200, height: 200}}
      />
      <Text>Hello, I am your cat!</Text>
    </View>
  );
};

export default CatApp;

 

State

컴포넌트가 어떻게 보여지는지 설정하는데 사용하는 argument --> props

컴포넌트의 개인 데이터 저장소 --> state

state는 사용자와의 상호작용에서 혹은 시간이 지남에 따라 변화되는 데이터를 다루는데 유용하다.

state는 컴포넌트에게 기억할 수 있게 한다. 

--> 시간이 지남에 따라 변화될 것이라고 생각되는 컴포넌트 데이터를 추적하는데 state를 쓴다. 

 

예시로, cat cate에서 두마리의 배고픈 고양이가 있고 시간이 지남에 따라 허기의 상태가 달라질 것임. 밥주기 버튼을 누르면 배고픈 고양이가 배불러지는 상태로 변경된다.

컴포넌트에 state를 추가하는 방법은 React's useState Hook을 부르는 것이다. Hook 이란 함수가 React 의 특징으로 채여지는 것. 예를 들어 useState는 함수 컴포넌트에 state를 추가하는 Hook이다. 

 

// useState를 import한다.
import React, {useState} from 'react';
import {Button, Text, View} from 'react-native';

type CatProps = {
  name: string;
};

const Cat = (props: CatProps) => {
  /* 시간이 지남에 따라, 혹은 사용자와의 상호작용을 통해 변화될 것이라고 생각되는 데이터에 useState
     useState는 문자열, 숫자, Boolean, 배열, Object 어느 데이터라도 추적하는데 사용된다.
     useState는 초기 값으로 상태 변수를 만드는데, 여기서 isHungry라는 상태변수의 초기 값은 true이다.
     어떻게 이름을 짓는 상관 없는데, 아래의 패턴으로 하면 편리하다.
     [<getter>, <setter>] = useState(<initialValue>)
     
     useState를 통해 isHungry 라는 상태 변수를 만든다. */
  const [isHungry, setIsHungry] = useState(true);

  return (
    <View>
      <Text>
        I am {props.name}, and I am {isHungry ? 'hungry' : 'full'}!
      </Text>
      
      <Button
        //Button에 onPress라는 Prop을 줘, 누구든 버튼을 누르면 onPress가 fire하고, setIsHungry(false)를 부른다.
        onPress={() => {
          setIsHungry(false);
        }}
        // isHungry가 false면 Button의 disabled prop이 true가 되어 타이틀이 바뀐다. 
        disabled={!isHungry}
        title={isHungry ? 'Give me some food, please!' : 'Thank you!'}
      />
    </View>
  );
};

const Cafe = () => {
  return (
    <>
      <Cat name="Munkustrap" />
      <Cat name="Spot" />
    </>
  );
};

export default Cafe;

※ isHungry가 const임에도 재할당이 가능하다. state-setting function이 불러질 때 컴포넌트가 다시 랜더링되고, Cat function이 다시 실행된다. 

+ Recent posts