programing

Nuxt / Vuex / Vue 반응성 문제 증가

javaba 2022. 8. 1. 23:52
반응형

Nuxt / Vuex / Vue 반응성 문제 증가

여러분 안녕하세요 저는 Nuxt와 Vuex와 함께 작업할 때 어려움을 겪고 있습니다.

Vuex / Nuxt Classic Mode 예제를 실행하려고 합니다.https://nuxtjs.org/guide/vuex-store/

증분 버튼을 클릭하면 숫자가 올라가지 않습니다.내 페이지는 0에 머무릅니다.콘솔 내에서 스테이트가 숫자가 0이 아닌 것을 알 수 있습니다.리액티브를 모르는 것처럼 화면에는 표시되지 않습니다.

어딘가에서 설정이 잘못되어 0이 실제 상태가 아닌 것으로 상정하고 있습니다만, 어떻게든 카피를 작성했습니다.

템플릿에 있는 버튼입니다.

<button @click="inc">{{ counter }}</button>

여기 내 메서드 내 inc 함수가 있습니다.

inc () {
  this.$store.commit('increment')
},

여기 내 계산기가 있다.

computed: {
  counter () {
    return this.$store.getters.counter
  }
}

스토어 폴더에 포함된 Vuex/index.js 파일입니다.

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)

const createStore = () => {
  return new Vuex.Store({
    state: () => ({
      counter: 0
    }),
    getters: {
       counter: state => state.counter
    },
    mutations: {
      increment (state) {
        state.counter++
      }
    }
  })
}

export default createStore

상업용 사진

업데이트: 더 많은 코드 스니펫을 포함하여 기존 코멘트에 회신했습니다.

@Boussadjra Brahim @xaviert, 두 분 모두 참여해 주셔서 감사합니다.

@Boussadjra Brahim - 네, 저는 돌연변이라고 불리는 행동을 시도했지만, 저도 그렇게 되지 않은 것 같습니다.또, 액션만으로 상태를 조정해 보았지만, 그 변경은 할 수 없었습니다만, 동작은 돌연변이를 불러 상태가 변화하고 자신은 변화하지 않는다는 인상을 받고 있기 때문에, 더 알고 있으면 수정해 주십시오.나는 내가 그것을 제대로 시도하지 않았다는 것을 100% 인정한다.아래는 아무것도 하지 않은 행동과 돌연변이를 부른 행동이다.

actions: {
  increment (state) {
    state.counter++
  }
},   

그리고 이것은 돌연변이라고 불리는 액션이 있는 버전입니다.

actions: {
  incrementCounterUp () {
    this.commit('increment')
  }
},

@xaviert - 서버를 처음부터 다시 시작해보았습니다.또한 Nuxt 빌드에 이어 파이어베이스가 기능하는지 확인했습니다.그것이 도움이 될 수 있는지 어떤지를 조사했습니다.그렇지 않았다.보통 서버 시작은 'npm run dev'입니다.아래 저의 실수를 찾으실 수 있도록 저의 풀 아이디입니다.vue 컴포넌트 및 nuxt.config.config.config.config 파일을 사용할 수 있습니다.아직 꽤 생으로 리팩터링이 많이 필요하기 때문에 잘 정리할 수 있기를 바랍니다.

_.id.vue

<template>
  <div class="product">
    <div class="product-image">
      <div class="product-image-img">
        <img v-bind:src="product.image_file" width="450px;"/>
      </div>
    </div>
    <div class="product-details-wrapper">
      <div class="product-details">
        <h1>
          <div v-if="this.$route.query.editPage">
            <textarea @input="updateTextArea" ref="textarea2" v-model="product.item_name" type="text" />
          </div>
          <div v-else>{{product.item_name}}</div>
        </h1>
        <div class="product-description">
          <div class="product-description-text" v-if="this.$route.query.editPage">
            <textarea @input="updateTextArea" ref="textarea" v-model="product.description" type="text" />
          </div>
          <div class="product-description-text" v-else v-html="product.description"></div>
        </div>
        <p class="product-brand"><strong>Brand - </strong> {{product.brand_name}}</p>
        <hr />
        <div class="product-price">
          <div v-if="this.$route.query.editPage">
            <strong>Original Price - </strong>
            <input v-model="product.msrp" type="text" />
          </div>
          <div v-else class="product-msrp">
            <strong>Original Price - </strong>
            <span class="strike">${{product.msrp}}</span>
          </div>
          <div v-if="this.$route.query.editPage">
            <strong>Sale Price - </strong>
            <input v-model="product.price" type="text" />
          </div>
          <div v-else class="product-sale-price">
            <strong>Sale Price - </strong>
            <span class="">${{product.price}}</span>
          </div>
          <div class="product-price">
            Quantity x
            <input @input="updateQuantity" v-model="quantity" min="1" class="" type="number" value="1" />
          </div>
          <button @click="inc">{{ counter }}</button>
        </div>
      </div>
    </div>
    <div v-if="this.$route.query.editPage" class="update-product">       <button @click="updateProduct(product)">Update</button></div>
    <div class="footer">
      <router-link to="/privacy-policy" target="_blank">Privacy</router-link> |
      <router-link to="/terms" target="_blank">Terms</router-link>
    </div>

  </div>
</template>

<script>
// @ is an alias to /src

import firebase from '@/services/fireinit'
import foo from '@/components/foo'
const db = firebase.firestore()
export default {
  name: 'ProductPage',
  head () {
    return {
      title: this.product.item_name
    }
  },
  components: {
    foo
  },
  data: function () {
    return {
      product: {},
      image: '',
      name: 'Checkout',
      description: '',
      currency: 'USD',
      amount: '',
      msrp: '',
      quantity: 1
    }
  },
  methods: {
    inc () {
      this.$store.dispatch('incrementCounterUp', true)
    },
    updateProduct: function (product) {
      db.collection('products').doc(product.item_id).set(product)
        .then(function () {
          console.log('Document successfully written!')
        })
        .catch(function (error) {
          console.error('Error writing document: ', error)
        })
    },
    updateQuantity () {
      this.product.msrp = (this.quantity * this.product.orgMsrp)
      this.product.msrp = Math.round(100 * this.product.msrp) / 100
      this.product.price = this.quantity * this.product.orgPrice
      this.product.price = Math.round(100 * this.product.price) / 100
    },
    updateTextArea () {
      this.$refs.textarea.style.minHeight = this.$refs.textarea.scrollHeight + 'px'
      this.$refs.textarea2.style.minHeight = this.$refs.textarea2.scrollHeight + 'px'
    }
  },
  async asyncData({app, params, error}) {
    const ref = db.collection("products").doc(params.id)
    let snap
    let thisProduct = {}
    try {
      snap = await ref.get()
      thisProduct = snap.data()
      thisProduct.orgMsrp =  thisProduct.msrp
      thisProduct.orgPrice =  thisProduct.price
    } catch (e) {
      // TODO: error handling
      console.error(e)
    }
    return {
      product: thisProduct
    }
  },
  mounted () {
    if(this.$refs.textarea) {
      this.$refs.textarea.style.minHeight = this.$refs.textarea.scrollHeight + 'px'
      this.$refs.textarea2.style.minHeight = this.$refs.textarea2.scrollHeight + 'px'
    }
  },
  computed: {
    counter () {
      return this.$store.getters.counter
    }
  }
}
</script>


<style lang="less">
body {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  color: #2c3e50;
  margin: 0
}
p{
  margin-top: 1em;
  margin-bottom: 1em;
}
html, body, #__nuxt, #__layout, .default,  .product{
  height: 100%;
}
.product {
  justify-content: center;
  display: flex;
  max-width: 1150px;
  margin: 0 auto;
  flex-wrap: wrap;
  align-items: center;
  padding: 0 24px;
  &-price{
    input {
      border: 1px solid;
      padding: 0 .3em;
      text-align: center;
      width: 50px;
    }
  }
}
  .product-details{
    width: 100%;
    textarea {
      width: 100%;
      font-size: inherit;
      color: inherit;
      font-family: inherit;
      font-weight: inherit;
      height: initial;
      resize: none;
      background-color: transparent;
      border: none;
    }
    h1{
      font-size: 1.9rem;
      margin: 15px 0 20px;
    }
    hr{
      width: 50%;
      margin: .5rem 0px;
    }
    p{

    }
  }
  .product-description-text{
    margin: 10px 0;
  }
  .product-image, .product-details-wrapper{
    align-items: center;
    display: flex;
    justify-content: center;
  }
  .product-details-wrapper{
    flex: 0 1 535px;
  }
  .product-image{
    flex: 0 1 535px;
    img{
      width: 100%;
    }
  }
  .product-price{
    .strike{
      text-decoration: line-through;
    }
    button{
      display: flex;
      width: 150px;
      height: 50px;
      border-radius: 5px;
      justify-content: center;
      font-size: 24px;
      margin-top: 20px;
      &:hover{
        cursor: pointer;
        background-color: #f1f1f1;
        box-shadow: 3px 3px 11px -1px rgba(0, 0, 0, 0.48);
      }
    }
  }
  .product-sale-price{
    color: #f30000;
  }
  .footer {
    flex: 1 1 100%;
    text-align: center;
    color: #ccc;
    margin-top: 25px;
    padding: 15px;
    a {
      color: #ccc;
      text-decoration: none;
      &:hover{
        text-decoration: underline;
      }
    }
  }
  .update-product{
    position: absolute;
    top: 0;
    text-align: center;
  }

</style>

nuxt.confgs.displaces

const pkg = require('./package')
const { STRIPE_TOKEN } = process.env;

module.exports = {
  vue: {
    config: {
      productionTip: false,
      devtools: true
    }
  },
  buildDir: './functions/nuxt',
  mode: 'universal',

  /*
  ** Headers of the page
  */
  head: {
    title: pkg.name,
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      { hid: 'description', name: 'description', content: pkg.description }
    ],
    link: [
      { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
    ]
  },

  /*
  ** Customize the progress-bar color
  */
  loading: { color: '#fff' },

  /*
  ** Global CSS
  */
  css: [
  ],

  /*
  ** Plugins to load before mounting the App
  */

  /*
  ** Nuxt.js modules
  */
  modules: [
    // Doc: https://github.com/nuxt-community/axios-module#usage
    '@nuxtjs/axios',
    'nuxt-stripe-module'
  ],
  stripe: {
    version: 'v3',
    publishableKey: 'pk_test_XXX',
  },
  /*
  ** Axios module configuration
  */
  axios: {
    // See https://github.com/nuxt-community/axios-module#options
  },

  /*
  ** Build configuration
  */
  build: {
    /*
    ** You can extend webpack config here
    */
    publicPath: '/public/',
    vendor: [],
    extractCSS: true,
    bable: {
      presets: [
        'es2015',
        'stage-8'
      ],
      plugins: [
        ['transform-runtime', {
          'polyfill': true,
          'regenerator': true
        }]
      ]
    },
    extend (config, { isDev }) {
      if (isDev && process.client) {
        config.module.rules.push({
          enforce: 'pre',
          test: /\.(js|vue)$/,
          loader: 'eslint-loader',
          exclude: /(node_modules)/
        })
      }
    },
    router: {
      middleware: 'router-auth'
    }
  },
  plugins: [
    { src: '~/plugins/fireauth', ssr: true }
  ]
}

store/index.displaces

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)

const createStore = () => {
  return new Vuex.Store({
    state: () => ({
      counter: 0
    }),
    actions: {
      incrementCounterUp () {
        this.commit('increment')
      }
    },
    getters: {
      counter: state => state.counter
    },
    mutations: {
      increment (state) {
        state.counter++
      }
    }
  })
}

export default createStore

결국, 나는 내 어플리케이션에서 정확히 무엇이 오류인지 알아낼 수 없었다.

초기화, 설정 또는 개발 중에 만져서는 안 되는 것을 만지거나 설치해서는 안 되는 것을 만지거나 nuxt.config.js 변경 시 패키지가 엉망이 되거나 굵은 글씨로 변경되었을 수 있습니다.

같은 설치 절차에 따라 새로운 nuxt 앱을 만들었습니다.https://nuxtjs.org/guide/installation/

위의 _id를 이동.vue 컴포넌트는 그대로이며, 의존관계를 업데이트 받은 후 아래 이미지와 같이 완벽하게 동작합니다.

도와주신 @Bousadjra Brahim, @xaviert, @Andrew1325님 감사합니다.

여기에 이미지 설명 입력

언급URL : https://stackoverflow.com/questions/53670125/nuxt-vuex-vue-reactivity-issue-increment

반응형