Vuex(二) —— 用Vuex完成購物車案例

目錄

  • 需求
  • 需求分析
    • 組件分析
    • 組件通信
  • 開發(fā)
    • 準備環(huán)境
    • 準備模塊結(jié)構(gòu)
    • 商品列表組件
      • 展示商品列表
      • 添加購物車
    • 我的購物車組件
      • 購物車列表
      • 商品數(shù)量和統(tǒng)計功能
      • 刪除購物車商品
    • 購物車列表組件
      • 購物車列表
      • 全選操作
      • 數(shù)字加減并統(tǒng)計小計
      • 刪除功能
      • 統(tǒng)計總數(shù)量和總錢數(shù)
      • 處理金額小數(shù)的問題
    • 本地存儲
  • 完整案例

上一節(jié)介紹了Vuex的核心原理及簡單使用,這里來一個實際案例

image

需求

  • 商品列表展示商品、價格和【加入購物車】按鈕
    • 點擊【加入購物車】按鈕加入購物車,【我的購物車】提示數(shù)量增加
  • 【我的購物車】按鈕
    • 鼠標懸停出現(xiàn)popover,展示購物車里面的商品,價格數(shù)量,【刪除】按鈕,還有總數(shù)量和總價格,還有【去購物車】按鈕
    • 【刪除】按鈕可以刪除整個商品,總價和數(shù)量都會改變
    • 點擊【去購物車】按鈕可以跳到購物車界面
  • 展示多選框,商品,單價,數(shù)量及【加減按鈕車】,小計,【刪除】按鈕,總量和總價,【結(jié)算】按鈕
    • 數(shù)量加減改變數(shù)量,小計,總數(shù)量和總價
    • 【刪除】按鈕刪除整個商品
    • 多選框不選中的不計入總數(shù)量和總價格。
  • 刷新頁面,狀態(tài)還在,存在本地存儲中

需求分析

組件分析

  • 路由組件
    • 商品列表(①)
    • 購物車列表(②)
  • 我的購物車彈框組件(③)

組件通信

②和③都依賴購物車的數(shù)據(jù),①中點擊添加購物車,主要把數(shù)據(jù)傳遞給②和③,②和③之間的數(shù)據(jù)修改也互相依賴,如果沒有Vuex需要花時間精力在如何在組件中傳值上。

開發(fā)

準備環(huán)境

  1. 下載模板vuex-cart-demo-template,里面已經(jīng)將路由組件、樣式組件和數(shù)據(jù)都寫好了,我們只要負責(zé)實現(xiàn)功能即可。項目中還有一個server.js的文件,這個是node用來模擬接口的。
const _products = [
  { id: 1, title: 'iPad Pro', price: 500.01 },
  { id: 2, title: 'H&M T-Shirt White', price: 10.99 },
  { id: 3, title: 'Charli XCX - Sucker CD', price: 19.99 }
]

app.use(express.json())
// 模擬商品數(shù)據(jù)
app.get('/products', (req, res) => {
  res.status(200).json(_products)
})
// 模擬支付
app.post('/checkout', (req, res) => {
  res.status(200).json({
    success: Math.random() > 0.5
  })
})
  1. 首先npm install安裝依賴,之后node server將接口跑起來,然后再添加終端輸入npm run serve讓項目跑起來,這個時候訪問http://127.0.0.1:3000/products可以訪問到數(shù)據(jù),訪問http://localhost:8080/可以訪問到頁面

準備模塊結(jié)構(gòu)

  1. store文件夾中創(chuàng)建modules文件夾,創(chuàng)建兩個模塊products.jscart.js
image
  1. products.jscart.js文件中搭建基本結(jié)構(gòu)
const state = {}
const getters = {}
const mutations = {}
const actions = {}

export default {
  namespaced: true,
  state,
  getters,
  mutations,
  actions
}
  1. index.js中導(dǎo)入并且引用模塊
import Vue from 'vue'
import Vuex from 'vuex'
// 1. 導(dǎo)入模塊
import products from './modules/products'
import cart from './modules/cart'
Vue.use(Vuex)

export default new Vuex.Store({
  state: {
  },
  mutations: {
  },
  actions: {
  },
  // 2. 引用模塊
  modules: {
    products,
    cart
  }
})

商品列表組件

  • 展示商品列表
  • 添加購物車

展示商品列表

  1. products.js中要實現(xiàn)下面的方法
  • state中定義一個屬性記錄所有的商品數(shù)據(jù)
  • mutations中添加方法去修改商品數(shù)據(jù)
  • actions中添加方法異步向接口請求數(shù)據(jù)
// 導(dǎo)入axios
import axios from 'axios'
const state = {
  // 記錄所有商品
  products: []
}
const getters = {}
const mutations = {
  // 給products賦值
  setProducts (state, payLoad) {
    state.products = payLoad
  }

}
const actions = {
  // 異步獲取商品,第一個是context上下文,解構(gòu)出來要commit
  async getProducts ({ commit }) {
    // 請求接口
    const { data } = await axios({
      method: 'GET',
      url: 'http://127.0.0.1:3000/products'
    })
    // 將獲取的數(shù)據(jù)將結(jié)果存儲到state中
    commit('setProducts', data)
  }
}

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

  1. products.vue中將原來的data刪除,導(dǎo)入模塊并使用
<script>
// 導(dǎo)入需要的模塊
import { mapActions, mapState } from 'vuex'
export default {
  name: 'ProductList',
  // 創(chuàng)建計算屬性,映射products數(shù)據(jù),因為開啟了命名空間,這里添加了命名空間的寫法,后面是映射的屬性products
  computed: {
    ...mapState('products', ['products'])
  },
  // 把actions里面的方法映射進來,第一個依舊是命名空間的寫法
  methods: {
    ...mapActions('products', ['getProducts'])
  },
  // 組件創(chuàng)建之后調(diào)用getProducts獲取數(shù)據(jù)
  created () {
    this.getProducts()
  }
}
</script>
  1. 打開瀏覽器,可以看到商品界面已經(jīng)出現(xiàn)了三個商品。

添加購物車

把當前點擊的商品存儲到一個位置,將來在購物車列表組件中可以訪問到,所以需要一個位置記錄所有的購物車數(shù)據(jù),這個數(shù)據(jù)在多個組件中可以共享,所以將這個數(shù)據(jù)放在cart模塊中

  1. 在模塊cart.js中寫數(shù)據(jù)
const state = {
  // 記錄購物車商品數(shù)據(jù)
  cartProducts: []
}
const getters = {}
const mutations = {
  // 第二個是payLoad,傳過來的商品對象
  addToCart (state, product) {
    // 1. 沒有商品時把該商品添加到數(shù)組中,并增加count,isChecked,totalPrice
    // 2. 有該商品時把商品數(shù)量加1,選中,計算小計
    // 判斷有沒有該商品,返回該商品
    const prod = state.cartProducts.find(item => item.id === product.id)

    if (prod) {
      // 該商品數(shù)量+1
      prod.count++
      // 選中
      prod.isChecked = true
      // 小計 = 數(shù)量 * 單價
      prod.totalPrice = prod.count * prod.price
    } else {
      // 給商品列表添加一個新商品
      state.cartProducts.push({
        // 原來products的內(nèi)容
        ...product,
        // 數(shù)量
        count: 1,
        // 選中
        isChecked: true,
        // 小計為當前單價
        totalPrice: product.price
      })
    }
  }
}
const actions = {}

export default {
  namespaced: true,
  state,
  getters,
  mutations,
  actions
}
  1. products.vue中導(dǎo)入cart的添加購物車mutation
<template>
  <div>
    ...
    <el-table
      :data="products"
      style="width: 100%">
      ...
      <el-table-column
        prop="address"
        label="操作">
        <!-- 這一行可以通過插槽獲取作用域數(shù)據(jù) -->
        <!-- <template slot-scope="scope"> 這是2.6之前的寫法,2.6之后已經(jīng)過時了換成下里面的寫法了-->
        <template v-slot="scope">
          <!--添加點擊事件,傳入當前列表-->
          <el-button @click="addToCart(scope.row)">加入購物車</el-button>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>

<script>
import { mapActions, mapMutations, mapState } from 'vuex'
export default {
  name: 'ProductList',
  computed: {
    ...mapState('products', ['products'])
  },
  methods: {
    ...mapActions('products', ['getProducts']),
    // 將添加購物商品的數(shù)據(jù)映射到methods中
    ...mapMutations('cart', ['addToCart'])
  },
  created () {
    this.getProducts()
  }
}
</script>

<style></style>

  1. 點開瀏覽器,可以點擊加入購物車按鈕,點開調(diào)試臺可以看到數(shù)據(jù)的變化
image

我的購物車組件

  • 購買商品列表
  • 統(tǒng)計購物車總數(shù)和總價
  • 刪除按鈕

購物車列表

  1. component/pop-cart.vue中導(dǎo)入購物車數(shù)據(jù)
<template>
  <el-popover
    width="350"
    trigger="hover"
  >
  <!-- 這里是cartProducts的數(shù)據(jù),不需要修改 -->
    <el-table :data="cartProducts" size="mini">
      <el-table-column property="title" width="130" label="商品"></el-table-column>
      ...
    </el-table>
    ...
  </el-popover>
</template>

<script>
// 導(dǎo)入vuex模塊
import { mapState } from 'vuex'
export default {
  name: 'PopCart',
  computed: {
    // 把cart模塊中的cartProducts導(dǎo)入
    ...mapState('cart', ['cartProducts'])
  }
}
</script>

<style></style>

  1. 打開瀏覽器,點擊商品添加購物車,可以看到彈窗里有新加的商品
image

商品數(shù)量和統(tǒng)計功能

  1. 因為總數(shù)和總量可以用store中的getters來寫,因為是對數(shù)據(jù)的簡單修改,在cart.jsgetters中這么寫:
const getters = {
  // 接收state為參數(shù),返回結(jié)果
  totalCount (state) {
    // 返回數(shù)組中某個元素的和,用reduce方法
    // reduce方法接收兩個參數(shù),第一個參數(shù)是函數(shù),第二個參數(shù)是起始數(shù)(這里從0開始)
    // 函數(shù)內(nèi)部接收兩個參數(shù),第一個參數(shù)是求和變量,第二個數(shù)組的元素
    return state.cartProducts.reduce((sum, prod) => sum + prod.count, 0)
  },
  // 與上面同樣寫法
  totalPrice () {
    return state.cartProducts.reduce((sum, prod) => sum + prod.totalPrice, 0)
  }
}
  1. components/pop-cart.vue中引用
<template>
  <el-popover
    width="350"
    trigger="hover"
  >
    ...
    <div>
      <!-- 總數(shù)和總量也改成插值表達式 -->
      <p>共 {{ totalCount }} 件商品 共計¥{{ totalPrice }}</p>
      <el-button size="mini" type="danger" @click="$router.push({ name: 'cart' })">去購物車</el-button>
    </div>
    <!-- 徽章這里,將value修改成totalCount -->
    <el-badge :value="totalCount" class="item" slot="reference">
      <el-button type="primary">我的購物車</el-button>
    </el-badge>
  </el-popover>
</template>

<script>
// 把mapGetters導(dǎo)入
import { mapGetters, mapState } from 'vuex'
export default {
  name: 'PopCart',
  computed: {
    ...mapState('cart', ['cartProducts']),
    // 把cart模塊中的totalCount和totalPrice導(dǎo)入
    ...mapGetters('cart', ['totalCount', 'totalPrice'])
  }
}
</script>

<style>

</style>

  1. 打開瀏覽器,添加兩個商品,可以看到徽章和總計都發(fā)生了變化
image

刪除購物車商品

刪除商品要修改cart模塊中的state,所以要在cart模塊中添加一個mutation

  1. cardmutation中添加
const mutations = {
  addToCart (state, product) {
    ...
  },
  // 刪除購物車商品,第二個參數(shù)是商品id
  deleteFromCart (state, prodId) {
    // 使用數(shù)組的findIndex獲取索引
    const index = state.cartProducts.findIndex(item => item.id === prodId)
    // 判斷這個是不是等于-1,如果不是說明有這個商品,就執(zhí)行后面的刪除該元素
    // splice接收刪除元素的索引,第二個元素是刪除幾個元素,這里寫1
    index !== -1 && state.cartProducts.splice(index, 1)
  }
}
  1. components/pop-cart.vue中引用
<template>
  <el-popover
    width="350"
    trigger="hover"
  >
    <el-table :data="cartProducts" size="mini">
      ...
      <el-table-column label="操作">
        <!-- 獲取當前元素的id,添加slot插槽 -->
        <template v-slot="scope">
          <el-button size="mini" @click="deleteFromCart(scope.row.id)">刪除</el-button>
        </template>
      </el-table-column>
    </el-table>
    ...
  </el-popover>
</template>

<script>
// 導(dǎo)入mapMutations模塊
import { mapGetters, mapMutations, mapState } from 'vuex'
export default {
  name: 'PopCart',
  computed: {
    ...
  },
  methods: {
    // 把cart模塊中的deleteFromCart映射到methods中
    ...mapMutations('cart', ['deleteFromCart'])
  }
}
</script>

<style></style>

  1. 在瀏覽器中預(yù)覽,添加商品之后點擊刪除按鈕當前商品刪除成功

購物車列表組件

  • 購物車列表
  • 全選操作
  • 數(shù)字加減并統(tǒng)計小計
  • 刪除功能
  • 統(tǒng)計選中商品價格數(shù)量

購物車列表

  1. 在views/cart.vue中引入vuex
<template>
  <div>
    ...
    <!-- 這里也要寫成cartProducts -->
    <el-table
      :data="cartProducts"
      style="width: 100%"
    >
      ...
    </el-table>
    ...
  </div>
</template>

<script>
// 導(dǎo)入vuex
import { mapState } from 'vuex'
export default {
  name: 'Cart',
  computed: {
    // 將cartProducts映射到computed中
    ...mapState('cart', ['cartProducts'])
  }
}
</script>

<style></style>

  1. 在瀏覽器中看,添加商品到我的購物車,購物車列表中有了對應(yīng)的數(shù)據(jù)
image

全選操作

  • 點擊子checkbox,選中變不選中,不選中變選中
    • checkbox的狀態(tài)是其商品的isChecked的值決定
    • 使用mutation
  • 點擊父checkbox的時候,子checkbox與父保持一致,并且會重新進行計算值。全部點中子checkbox,父checkbox也會選中
    • checkbox的狀態(tài),是購物車頁面單獨顯示的,不需要寫到store中, 直接寫到當前組件。
    • 其依賴子checkboxisChecked狀態(tài),所以使用計算屬性
    • 改變父checkbox的狀態(tài),store的子狀態(tài)也需要改變,不需要定義方法,設(shè)置其set方法即可
  1. 先寫改變子checkbox狀態(tài)的mutation
const mutations = {
  addToCart (state, product) {
    ...
  },
  deleteFromCart (state, prodId) {
    ...
  },
  // 改變所有商品的isChecked屬性
  // 需要兩個參數(shù),第二個是checkbox的狀態(tài)
  updateAllProductChecked (state, checked) {
    // 給每個商品的isChecked屬性為checkbox狀態(tài)
    state.cartProducts.forEach(prod => {
      prod.isChecked = checked
    })
  },
  // 改變某個商品的isChecked屬性
  // 需要兩個屬性,第二個是商品對象,這里是解構(gòu),一個是checked,一個是id
  updateProductChecked (state, {
    checked,
    prodId
  }) {
    // 找到對應(yīng)id的商品對象
    const prod = state.cartProducts.find(item => item.id === prodId)
    // 如果商品對象存在就給其isChecked進行賦值
    prod && (prod.isChecked = checked)
  }
}
  1. views/cart.vue中進行引入修改
  • 引入mutation
  • 找到父checkbox綁定計算屬性
  • 定義checkbox計算屬性,完成getset
  • checkbox中使用
<template>
  <div>
    ...
    <el-table
      :data="cartProducts"
      style="width: 100%"
    >
      <el-table-column
        width="55">
        <template v-slot:header>
          <!-- 2. 這里綁定一個v-model,計算屬性 -->
          <el-checkbox size="mini" v-model="checkedAll">
          </el-checkbox>
        </template>
         <!-- 4. 這里不能直接綁定v-model,因為我們綁定的是vuex的狀態(tài),不能直接更改狀態(tài)
            4.1 先綁定其isChecked屬性
            4.2 注冊改變事件change,當checkbox改變的時候調(diào)用change,接收兩個參數(shù),id就通過scope.row獲取,checked狀態(tài)就通過$event獲取 -->
        <template v-slot="scope">
          <el-checkbox
            size="mini"
            :value="scope.row.isChecked"
            @change="updateProductChecked({
              prodId: scope.row.id,
              checked: $event
            })"
          >
          </el-checkbox>
        </template>
      </el-table-column>
      ...
    </el-table>
    ...
  </div>
</template>

<script>
import { mapMutations, mapState } from 'vuex'
export default {
  name: 'Cart',
  computed: {
    ...mapState('cart', ['cartProducts']),
    // 3. 父checkbox的狀態(tài),因為有g(shù)et和set所以直接寫成對象形式
    checkedAll: {
      // 返回當前購物車的商品是否都是選中狀態(tài),如果有一個沒有選中直接返回false
      get () {
        return this.cartProducts.every(prod => prod.isChecked)
      },
      // 狀態(tài)改變的時候觸發(fā)的方法,需要一個參數(shù),checkbox的狀態(tài)
      set (value) {
        this.updateAllProductChecked(value)
      }
    }
  },
  methods: {
    // 1. 將cart模塊的mutations映射到methods
    ...mapMutations('cart', ['updateAllProductChecked', 'updateProductChecked'])
  }
}
</script>

<style></style>

  1. 打開瀏覽器,選中商品進入購物車,可以對全選框進行點擊

數(shù)字加減并統(tǒng)計小計

  1. cart模塊中,定義一個mutation方法,更新商品
const mutations = {
  ...
  // 更新商品,把商品id和count進行解構(gòu)
  updateProduct (state, { prodId, count }) {
    // 找到當前商品
    const prod = state.cartProducts.find(prod => prod.id === prodId)
    // 如果找到了就更新數(shù)量和總價
    if (prod) {
      prod.count = count
      prod.totalPrice = count * prod.price
    }
  }
}
  1. cart.vue中添加一個mapMutations
<script>
...
export default {
  ...
  methods: {
    // 將cart模塊的mutations映射到methods
    ...mapMutations('cart', [
      'updateAllProductChecked',
      'updateProductChecked',
      'updateProduct'
    ])
  }
}
</script>
  1. 在數(shù)字框中進行方法綁定
<el-table-column
    prop="count"
    label="數(shù)量">
    <!-- 這里先定義一個插槽,綁定value是count,定義一個改變的change方法,將updateProduct傳入兩個參數(shù),一個是id,一個是當前input的值$event -->
    <template v-slot="scope">
      <el-input-number :value="scope.row.count" @change="updateProduct({
        prodId: scope.row.id,
        count: $event
      })" size="mini"></el-input-number>
    </template>
  </el-table-column>
  1. 在瀏覽器中查看,添加商品之后,修改數(shù)字,會有對應(yīng)的商品數(shù)量和小計
image

刪除功能

  1. 之前已經(jīng)在cart.js的模塊中有了刪除商品的mutation,這里直接使用,在cart.vue中添加
<script>
...
export default {
  ...
  methods: {
    // 將cart模塊的mutations映射到methods
    ...mapMutations('cart', [
      'updateAllProductChecked',
      'updateProductChecked',
      'updateProduct',
      'deleteFromCart'
    ])
  }
}
</script>
  1. 在上面的刪除按鈕中定義方法
<el-table-column
    label="操作">
    <!-- 定義一個插槽,刪除按鈕綁定事件,傳入商品id -->
    <template v-slot="scope">
    <el-button size="mini"
        @click="deleteFromCart(scope.row.id)">刪除</el-button>
    </template>
</el-table-column>
  1. 瀏覽器中,添加商品之后進入購物車頁面,點擊刪除按鈕可以刪除整個商品。

統(tǒng)計總數(shù)量和總錢數(shù)

統(tǒng)計的過程中需要添加條件,判斷當前商品是否是選中狀態(tài)。

  1. cart.jsgetters中添加商品數(shù)量和總價的方法,并且對選中狀態(tài)進行判斷
const getters = {
  totalCount (state) {
    ...
  },
  totalPrice () {
    ...
  },
  // 選中的商品數(shù)量
  checkedCount (state) {
    // 返回前判斷是否是選中狀態(tài),如果是就進行添加,并且返回sum
    return state.cartProducts.reduce((sum, prod) => {
      if (prod.isChecked) {
        sum += prod.count
      }
      return sum
    }, 0)
  },
  // 選中的商品價格,同理上面
  checkedPrice () {
    return state.cartProducts.reduce((sum, prod) => {
      if (prod.isChecked) {
        sum += prod.totalPrice
      }
      return sum
    }, 0)
  }
}
  1. cart.vue中導(dǎo)入mapGetters
<script>
import { mapGetters, mapMutations, mapState } from 'vuex'
export default {
  name: 'Cart',
  computed: {
    ...mapState('cart', ['cartProducts']),
    // 將cart模塊中的getters映射到computed中
    ...mapGetters('cart', ['checkedCount', 'checkedPrice']),
    ...
  },
  ...
}
</script>
  1. 在總價格處引用
<div>
  <p>已選 <span>{{ checkedCount }}</span> 件商品,總價:<span>{{ checkedPrice }}</span></p>
  <el-button type="danger">結(jié)算</el-button>
</div>

處理金額小數(shù)的問題

多添加商品的時候發(fā)現(xiàn)商品金額會出現(xiàn)很多位小數(shù)的問題,所以這里進行處理

  1. mutations中會價格的乘積進行保留兩位小數(shù)的操作
const mutations = {
  // 添加商品
  addToCart (state, product) {
    const prod = state.cartProducts.find(item => item.id === product.id)
    if (prod) {
      prod.count++
      prod.isChecked = true
      // 小計 = 數(shù)量 * 單價
      prod.totalPrice = (prod.count * prod.price).toFixed(2)
      console.log(prod.totalPrice)
    } else {
      ...
    }
  },
  // 更新商品
  updateProduct (state, { prodId, count }) {
    const prod = state.cartProducts.find(prod => prod.id === prodId)
    if (prod) {
      prod.count = count
      // 保留兩位小數(shù)
      prod.totalPrice = (count * prod.price).toFixed(2)
    }
  }
}

  1. getters中將總價進行保留兩位小數(shù),記得轉(zhuǎn)化成數(shù)字
const getters = {
  // 價格總計
  totalPrice () {
    return state.cartProducts.reduce((sum, prod) => sum + Number(prod.totalPrice), 0).toFixed(2)
  },
  // 選中的商品價格
  checkedPrice () {
    return state.cartProducts.reduce((sum, prod) => {
      if (prod.isChecked) {
        sum += Number(prod.totalPrice)
      }
      return sum
    }, 0).toFixed(2)
  }
}

本地存儲

刷新頁面,購物車的數(shù)據(jù)就會消失,因為我們把數(shù)據(jù)添加到了內(nèi)存中存儲,而實際購物的時候,有兩種存儲方式:

  • 如果用戶登錄,購物車的數(shù)據(jù)是在服務(wù)器中
  • 如果用戶沒有登錄,購物車的數(shù)據(jù)是存在本地存儲中

現(xiàn)在實現(xiàn)本地存儲的功能

  1. 首先在cart.js中,首次進入界面的時候,從本地獲取數(shù)據(jù)
const state = {
  // 從本地獲取購物車商品數(shù)據(jù),如果沒有初始化為空數(shù)組
  cartProducts: JSON.parse(window.localStorage.getItem('cart-products')) || []
}
  1. mutations中更改數(shù)據(jù),所以每次更改過的數(shù)據(jù),都需要記錄到本地存儲中,這里使用vuex的插件,在index.js
...
Vue.use(Vuex)

const myPlugin = store => {
  store.subscribe((mutation, state) => {
    // mutation 的格式為 { type, payload }
    // type里面的格式是cart/cartProducts
    // state 的格式為 { cart, products }
    if (mutation.type.startsWith('cart/')) {
      // 本地存儲cartProducts
      window.localStorage.setItem('cart-products', JSON.stringify(state.cart.cartProducts))
    }
  })
}
export default new Vuex.Store({
  ...
  // 將myPlugin掛載到Store上
  plugins: [myPlugin]
})

  1. 刷新瀏覽器可以看到購物車的商品列表的數(shù)據(jù)還存在。

完整案例

vuex-cart-temp

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容