!! 나중에 필요하면 더 정리할 내용 !!
- 응용 getters에서 getters호출, actions에서 actions호출 (quick vue 366p 참고)
- vuex helper 속성 등록 방법 객체 전개 연산자 등록, 명칭 바꿔서 등록
   (명칭 : https://rnwns2.tistory.com/37?category=391381)
   (객체 전개 연산자 등록 : https://vuex.vuejs.org/kr/guide/state.html)
- 모듈화, 여러 저장소 

- vuex

- 단방향 데이터 흐름

- vue.js의 상태관리를 위한 라이브러리

- 공용으로 필요한 데이터를 중앙 저장소에서 관리하여 필요한 곳에 쉽게 전달할 수 있는 역할

store 등록

- main.js와 index.js에서 아래 코드를 작성하면 모든 컴포넌트에서 저장소(Store)객체를 this.$store로 접근 가능

// src/main.js
import store from './store';

new Vue({
  store,
  ... 생략
})

// src/store/index.js
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

 

 

State : 상태

- 컴포넌트 간에 공유할 데이터

// state 형식

state: {
        num : 10,
        currentRegion : "all",
    },

 

Mutation : 변이

- 변이(Mutation)의 목적은 상태(State)의 변경

- 상태의 변경과 관련이 없는 작업은 변이 내부에서 실행 하지 않도록 하기

- 변이(Mutation)는 동기적인 작업

   1. 비동기 처리 가능하지만 사후 스냅샷 캡쳐 후 상태가 변경 되기때문에 어떻게 변경되었는지 추적하기 힘듬

// mutations 형식
// state.속성 => 기존의 데이터 값
// payload.속성 => 변경할 데이터 값

mutations: {
        [Constant.CHANGE_REGION] : (state, payload) => {
            state.currentRegion = payload.region;
        },
    },

 

Action : 액션

- 비동기

- dispatch()

// mutations 형식
// state.속성 => 기존의 데이터 값
// payload.속성 => 변경할 데이터 값

actions: {
        [Constant.DELETE_REGION] : ({state, commit}, payload) => {
            store.commit(Constant.DELETE_REGION, payload);
        }
    }

 

Getter : 게터

- 특정 컴포넌트에 사용되는 똑같은 값을 중복해서 계산하지 않고 재사용하고 싶을때 쓰임(중복 코드를 막아줌)

  ex) 한 페이지에 글을 최대 10개 보여주는 계산식을 모든 게시판에 적용

- computed처럼 함수 형식으로 작성 해야한다.

   1. 함수 인자에 state를 받아와야 한다

// getters 형식

getters: {
        if(state.currentRegion == "all") {
                return state.countries;
            } else {
                return state.countries.filter(c => c.region == state.currentRegion)
            }
    },

 

변이 vs 액션

  변이(Mutation) 액션(Action)
인자 상태(state), 페이로드(payload) 저장소(store)객체, 페이로드(payload)
- 상태(state)
- 변이(mutation)
- 게터(getter)
- 액션(acttion)
- commit
기능 - 저장소(store)의 상태(state)를 변경
- 동기
- 여러 변이(mutation)를 commit()할 수 있다.
- 다른 액션을 dispatch()할 수 있다.
- 비동기

 

'라이브러리' 카테고리의 다른 글

Vuex(응용예제)  (0) 2020.04.27
Vuex(기본예제)  (0) 2020.04.27
vue-chartjs  (0) 2020.04.10
참고
vuex import 스타일 - https://kdydesign.github.io/2019/05/09/vuex-tutorial/
vuex 개념 - https://joshua1988.github.io/web-development/vuejs/vuex-actions-modules/
vuex helper - https://ict-nroo.tistory.com/108


1. main.js에 store 등록했는지 확인
2. 여러개 store 사용할때 모든 store를 module화 안하면 namespaced 인식 못함
3. createNamespacedHelpers 사용할거면 모듈에서 namespaced : true 하기


 

Vuex helper

vuex 기본 vuex helper
state mapState
mutations mapMutations
getters mapGetters
actions mapActions

- store에서 기존의 사용하던 속성들 이름 앞에 map을 붙여서 사용

- vuex의 속성들을 더 쉽게 사용할 수 있음

- 여러개의 store를 만들어서 사용할 수 있음 

 

vuex 속성 불러올때 유형

1. 이름을 동일하게 사용할 때(배열 형식으로 작성)

2. 이름을 다르게 사용할 때(객체 형식으로 작성)

// 1번 예제
mapGetters([ 'regions', 'currentRegion', ]),
 
// 2번 예제
mapGetters({
    re : 'regions',
    cu : 'currentRegion',
  }),

 

1. 파일 구조

- store폴더 -> index.js(상위 store) - 모듈화 한 데이터를 불러들여 모두 관리하는 저장소

- store폴더 -> 하위폴더 -> sample.js(하위 store) - 기능마다 모듈화하여 데이터 관리하는 작은 저장소

1. index 파일에서는 필요한 모듈들을 import하여 전체적으로 관리함

2. store 폴더에서 하위폴더를 만들어서 모듈화할 기능을 js파일로 만듬

 

사용법

1. 상태관리할 데이터를 모듈화 (store폴더 -> 하위폴더 -> weatherData.js파일)

2. 중앙저장소에서 필요한 모듈을 import하고 모듈에 선언 하기 (store폴더 -> index.js파일)

3. 사용하고 싶은 컴포넌트에서 import하여 사용하기(main.vue 컴포넌트파일)

 

// weatherData.js(모듈)

var axios = require('axios')
var cheerio = require('cheerio')

const state = {
    nowTemperature: '12', // 현재 온도
    nowWeatherCheck: '흐림', // 맑음, 흐림 체크
    todayMin: '1', // 최저기온
    todayMax: '15', // 최고기온
    todayDust: '2', // 미세먼지
    todayDDust: '2', // 초미세먼지
    // test: 'testsadasdwe',
  }
  // vue의 computed와 비슷
  const getters = {

  }
  // state를 수정할 때 사용
  const mutations = {
    SET_TEMPERATURE(state, data) {
      state.nowTemperature = data
    },
    SET_WEATHERCHECK(state, data) {
      state.nowWeatherCheck = data
    },
    SET_TODAYMIN(state, data) {
      state.todayMin = data
    },
    SET_TODAYMAX(state, data) {
      state.todayMax = data
    },
    SET_TODAYDUST(state, data) {
      state.todayDust = data
    },
    SET_TODAYDDUST(state, data) {
      state.todayDDust = data
    },
  }
  // 비동기를 사용할 때, 또는 여러 mutations를 연달아 송출할 때
  const actions = {
    getData({state, commit}, data) {
      axios.get('https://search.naver.com/search.naver?sm=top_hty&fbm=1&ie=utf8&query=%EB%82%A0%EC%94%A8')
      .then(res => {
        var $ = cheerio.load(res.data)
        commit('SET_TEMPERATURE', $('#main_pack > div.sc.cs_weather._weather > div:nth-child(2) > div.weather_box > div.weather_area._mainArea > div.today_area._mainTabContent > div.main_info > div > p > span.todaytemp').text())
        commit('SET_WEATHERCHECK', $('#main_pack > div.sc.cs_weather._weather > div:nth-child(2) > div.weather_box > div.weather_area._mainArea > div.today_area._mainTabContent > div.main_info > div > ul > li:nth-child(1) > p').text())
        commit('SET_TODAYMIN', $('#main_pack > div.sc.cs_weather._weather > div:nth-child(2) > div.weather_box > div.weather_area._mainArea > div.today_area._mainTabContent > div.main_info > div > ul > li:nth-child(2) > span.merge > span.min').text())
        commit('SET_TODAYMAX', $('#main_pack > div.sc.cs_weather._weather > div:nth-child(2) > div.weather_box > div.weather_area._mainArea > div.today_area._mainTabContent > div.main_info > div > ul > li:nth-child(2) > span.merge > span.max').text())
        commit('SET_TODAYDUST', $('#main_pack > div.sc.cs_weather._weather > div:nth-child(2) > div.weather_box > div.weather_area._mainArea > div.today_area._mainTabContent > div.sub_info > div > dl > dd:nth-child(2)').text())
        commit('SET_TODAYDDUST', $('#main_pack > div.sc.cs_weather._weather > div:nth-child(2) > div.weather_box > div.weather_area._mainArea > div.today_area._mainTabContent > div.sub_info > div > dl > dd:nth-child(4)').text())
      })
    },

  }


export default {
  namespaced:true,
  state,
  mutations,
  actions,
  getters,

};
// index.js(중앙저장소)

import Vue from 'vue'
import Vuex from 'vuex'

import wordStore from './wordStore/spanishWord'
import weatherStore from './weatherStore/weatherData'

Vue.use(Vuex)


export default new Vuex.Store({
    modules: {
        spanish: wordStore,
        weather: weatherStore,
    }
})
// main.vue(컴포넌트)

<script>

import {createNamespacedHelpers} from 'vuex'
const nowWeather = createNamespacedHelpers('weather')

export default {
  name: 'main',
  
  computed:{
    ...nowWeather.mapState([
      'nowTemperature',
      'nowWeatherCheck',
      'todayMin',
      'todayMax',
      'todayDust',
      'todayDDust',
    ])
  },
  
  methods: {
    ...nowWeather.mapActions([
      'getData'
    ])
  }, // methods 끝
  
  mounted() {
    this.getData()
  },
  
}
</script>

'라이브러리' 카테고리의 다른 글

Vuex(개념)  (0) 2020.12.15
Vuex(기본예제)  (0) 2020.04.27
vue-chartjs  (0) 2020.04.10
// vuex store구조

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

export default new Vuex.Store({

  //vue의 data와 비슷
  state: {
    ...
  },
  
  // 변경된 데이터 업데이트 vue의 computed와 비슷
  getters: {
	...
  },
  
  // state를 수정할 때 사용(동기적)
  mutations:{
    ...
  },
  
  // methods 역할(비동기적)
  actions: {
	...
  },
  
})

 

예제

1. main.js에 store 등록

// main.js 

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'



new Vue({
  store,
  router,
  el: '#app',
  render: h => h(App)
})

2. store에 웹 페이지에서 공동으로 사용할 데이터 등록

// store.js

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);
export default new Vuex.Store({
  const state = {
    nowTemperature: '12', // 현재 온도
    nowWeatherCheck: '흐림', // 맑음, 흐림 체크
    todayMin: '1', // 최저기온
    todayMax: '15', // 최고기온
    todayDust: '2', // 미세먼지
    todayDDust: '2', // 초미세먼지
    // test: 'testsadasdwe',
  }
  // vue의 computed와 비슷
  const getters = {

  }
  // state를 수정할 때 사용
  const mutations = {
    SET_TEMPERATURE(state, data) {
      state.nowTemperature = data
    },
    SET_WEATHERCHECK(state, data) {
      state.nowWeatherCheck = data
    },
    SET_TODAYMIN(state, data) {
      state.todayMin = data
    },
    SET_TODAYMAX(state, data) {
      state.todayMax = data
    },
    SET_TODAYDUST(state, data) {
      state.todayDust = data
    },
    SET_TODAYDDUST(state, data) {
      state.todayDDust = data
    },
  }
  // 비동기를 사용할 때, 또는 여러 mutations를 연달아 송출할 때
  const actions = {
    getData({state, commit}, data) {
      axios.get('https://search.naver.com/search.naver?sm=top_hty&fbm=1&ie=utf8&query=%EB%82%A0%EC%94%A8')
      .then(res => {
        var $ = cheerio.load(res.data)
        commit('SET_TEMPERATURE', $('#main_pack > div.sc.cs_weather._weather > div:nth-child(2) > div.weather_box > div.weather_area._mainArea > div.today_area._mainTabContent > div.main_info > div > p > span.todaytemp').text())
        commit('SET_WEATHERCHECK', $('#main_pack > div.sc.cs_weather._weather > div:nth-child(2) > div.weather_box > div.weather_area._mainArea > div.today_area._mainTabContent > div.main_info > div > ul > li:nth-child(1) > p').text())
        commit('SET_TODAYMIN', $('#main_pack > div.sc.cs_weather._weather > div:nth-child(2) > div.weather_box > div.weather_area._mainArea > div.today_area._mainTabContent > div.main_info > div > ul > li:nth-child(2) > span.merge > span.min').text())
        commit('SET_TODAYMAX', $('#main_pack > div.sc.cs_weather._weather > div:nth-child(2) > div.weather_box > div.weather_area._mainArea > div.today_area._mainTabContent > div.main_info > div > ul > li:nth-child(2) > span.merge > span.max').text())
        commit('SET_TODAYDUST', $('#main_pack > div.sc.cs_weather._weather > div:nth-child(2) > div.weather_box > div.weather_area._mainArea > div.today_area._mainTabContent > div.sub_info > div > dl > dd:nth-child(2)').text())
        commit('SET_TODAYDDUST', $('#main_pack > div.sc.cs_weather._weather > div:nth-child(2) > div.weather_box > div.weather_area._mainArea > div.today_area._mainTabContent > div.sub_info > div > dl > dd:nth-child(4)').text())
      })
    },

  },
})

3. 필요한 컴포넌트에서 store import하고 데이터 받아오기

// main.vue(해당 컴포넌트)

<script>
import mainTitle from './main/mainTitle'
import nowWeather from './weather/nowWeather'

import store from './store'
export default {
  name: 'main',
  store,

  components:{
    'mainTitle': mainTitle,
    'nowWeather': nowWeather,
  },

  computed:{
  	// state
    nowTemperature() {
      return this.$store.state.nowTemperature
    },
    
    // ... 생략
    
    // getters
    test() {
      return this.$store.getters.test
    },
  },
  methods: {
    getData () {
      // actions
      this.$store.dispatch('액션명', payload) // payload 생략 가능
      
      // mutations
      this.$store commit('변이명', payload) // payload 생략 가능
  },
}
</script>

'라이브러리' 카테고리의 다른 글

Vuex(개념)  (0) 2020.12.15
Vuex(응용예제)  (0) 2020.04.27
vue-chartjs  (0) 2020.04.10
- 주의 -
1. 하위 컴포넌트에서 <template></template> 태그 없애기
2. axios로 전달받은 데이터가 화면에 부착 안될때는 v-if='true' 사용하기
3. <script>안에 해당 차트import 꼭 넣기

- 참고 사이트 -
1. vue-chart.js 사용예제(블로그) : https://chuckolet.tistory.com/8
2. vue-chart.js 공식사이트 : https://vue-chartjs.org/guide/#introduction
3. chart.js 공식사이트 : https://www.chartjs.org/docs/latest/general/responsive.html
4. chart.js 사용예제(블로그) : https://ming9mon.tistory.com/122?category=841705

상위 컴포넌트

// weather.vue

<template>
  <div class="all">

    <div class="canvas">
      <weather-chart v-bind:class="size" v-bind:weather="weather" v-bind:time="time" v-bind:temperature="temperature" v-if="loaded"/>
    </div>

  </div>
</template>

<script>
import {Line} from 'vue-chartjs'
import weatherChart from './weatherChart'

var axios = require('axios')
var cheerio = require('cheerio');

export default {
  extends: Line,
  components:{
    weatherChart
  },
  data() {
    return {
      number : '',
      temperature : [],
      weather: [],
      time : [],
      loaded: false,
      size: 'firstClass'
    }
  },

  methods: {
    getData: function(){
      axios.get('https://search.naver.com/search.naver?sm=top_hty&fbm=1&ie=utf8&query=%EB%82%A0%EC%94%A8')
      .then(res => {
        var $ = cheerio.load(res.data)
        this.loaded = true
        var number = $("#main_pack > div.sc.cs_weather._weather > div:nth-child(2) > div.weather_box > div.weather_area._mainArea > div.today_area._mainTabContent > div.table_info.bytime._todayWeatherByTime > div.info_list.weather_condition._tabContent > ul > li").length
        this.number = number
        for(var i=1; i<=number; i++){
          this.temperature.push($("#main_pack > div.sc.cs_weather._weather > div:nth-child(2) > div.weather_box > div.weather_area._mainArea > div.today_area._mainTabContent > div.table_info.bytime._todayWeatherByTime > div.info_list.weather_condition._tabContent > ul > li:nth-child("+i+") > dl > dd.weather_item._dotWrapper > span:nth-child(1)").text())
        }
        for(var i=1; i<=number; i++){
          this.weather.push($("#main_pack > div.sc.cs_weather._weather > div:nth-child(2) > div.weather_box > div.weather_area._mainArea > div.today_area._mainTabContent > div.table_info.bytime._todayWeatherByTime > div.info_list.weather_condition._tabContent > ul > li:nth-child("+i+") > dl > dd.item_condition > span").text())
        }
        for(var i=1; i<=number; i++){
          this.time.push($("#main_pack > div.sc.cs_weather._weather > div:nth-child(2) > div.weather_box > div.weather_area._mainArea > div.today_area._mainTabContent > div.table_info.bytime._todayWeatherByTime > div.info_list.weather_condition._tabContent > ul > li:nth-child("+i+") > dl > dd.item_time > span").text())
        }
      }) // axios 끝
    }, // getData함수 끝
  },
  mounted(){
    this.getData()
  }
}
</script>

<style scoped>
  .detail{
    display: flex;
    flex-direction: row;
    width: 600px;
  }
  .weather {
    padding-left: 27px;
  }
  .firstClass{
    padding-top: 30px;
    height: 150px;
    width: 700px;
  }

</style>

하위 컴포넌트

// weatherChart.vue

<script>
import {Line} from 'vue-chartjs'
export default {
  extends: Line,
  props:{
    time: {
      type: Array,
    },
    temperature: {
      type: Array
    }
  },
  data() {
    return {
      datacollection: {
        labels: this.time, // 가로축 데이터
        datasets: [
          {
            label: '온도', // 차트 상단에 차트 이름
            data: this.temperature, // 세로축 데이터
            backgroundColor: 'azure',
            borderColor: 'aqua',
          }
        ]
      }, // chart데이터 끝

      options: {
        responsive: true,
        maintainAspectRatio: false, // 차트 width, height 크기조절

        legend:{
          display:false, // 차트 위에 label 표시 여부
        },

        tooltips: {
				enabled: false // 차트에 마우스 올렷을때 데이터 표시 여부
			  },

  			hover: {
  				animationDuration: 0
  			},

  			animation: { // 데이터 항상 표시
  				duration: 1,
  				onComplete: function () {
  					var chartInstance = this.chart,
  					ctx = chartInstance.ctx;
  					ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, Chart.defaults.global.defaultFontStyle, Chart.defaults.global.defaultFontFamily);
  					ctx.fillStyle = 'black';
  					ctx.textAlign = 'right';
  					ctx.textBaseline = 'bottom';

  					this.data.datasets.forEach(function (dataset, i) {
  						var meta = chartInstance.controller.getDatasetMeta(i);
  						meta.data.forEach(function (bar, index) {
  							var data = dataset.data[index];
  							ctx.fillText(data, bar._model.x, bar._model.y - 5);
  						});
  					});
  				}
  			},

        scales: {

          yAxes: [{
            // display: false, // y축 기준 표시 여부
            ticks: { // y축 기준 데이터 변경
              // beginAtZero:true,
              min: 0, // y축 최소값
						  // max: 13, // y축 최대값
              stepSize: 10, // y축 간격
						  fontSize : 12, // 글자크기
            },
            gridLines: {
              display: false, // 차트 안에 가로선 표시 여부
              drawBorder: false
            }
          }],

          xAxes: [{
            display: false,
            gridLines:{
              display: false,
              brawBorder:false
            }
          }]

        }, // scales 끝

      }, //옵션 끝

    } // 모든 data 끝
  },
  mounted(){
    this.renderChart(this.datacollection, this.options)
  }
}
</script>

<style scoped>

</style>

 

결과물

'라이브러리' 카테고리의 다른 글

Vuex(개념)  (0) 2020.12.15
Vuex(응용예제)  (0) 2020.04.27
Vuex(기본예제)  (0) 2020.04.27

+ Recent posts