步步向前之vue

疑難雜症

全局使用axios

  • 結合 vue-axios使用

    import axios from 'axios'
    import VueAxios from 'vue-axios'
        
    Vue.use(VueAxios,axios);
    
    getNewsList(){
      this.axios.get('api/getNewsList').then((response)=>{
        this.newsList=response.data.data;
      }).catch((response)=>{
        console.log(response);
      })
    },
  • axios 改寫爲 Vue 的原型屬性

    首先在主入口文件main.js中引用,以後掛在vue的原型鏈上css

    import axios from 'axios'
       Vue.prototype.$ajax= axios

    在組件中使用html

    this.$ajax.get('api/getNewsList').then((response)=>{
               this.newsList=response.data.data;
             }).catch((response)=>{
               console.log(response);
             })
  • 結合 Vuexaction

    vuex的倉庫文件store.js中引用,使用action添加方法vue

    import Vue from 'Vue'
       import Vuex from 'vuex'
       
       import axios from 'axios'
       
       Vue.use(Vuex)
       const store = new Vuex.Store({
         // 定義狀態
         state: {
           user: {
             name: 'xiaoming'
           }
         },
         actions: {
           // 封裝一個 ajax 方法
           login (context) {
             axios({
               method: 'post',
               url: '/user',
               data: context.state.user
             })
           }
         }
       })
       
       export default store

    在組件中發送請求的時候,須要使用 this.$store.dispatchwebpack

    methods: {
         submitForm () {
           this.$store.dispatch('login')
         }
       }

Vue中的圖片資源的引入

  • csstemplate中的圖片靜態路徑可正常寫入,webpack可正常打包
  • js即放在script中的圖片路徑必須使用require引入,不然webpack打包時將沒法識別這些資源,包括templatev-bind:綁定的值,例如:ios

    data () {
          return {
            slides: {
                src: require('../assets/slideShow/pic1.jpg'), //require
                title: 'xxx1',
                href: 'detail/analysis'
              }
          }
      }

設置props默認值報錯

父子組件的值的傳遞在vue中很經常使用到,設置props的默認值時會遇到如下錯誤:git

props: {
    selections: {
      type: Array,
      default: [{
        label: 'test',
        value: 0
      }]
    }
  }

報錯Props with type Object/Array must use a factory function to return the defaut value
翻譯過來就是 對象或數組的屬性默認值必須以一個工廠函數返回
也就是相似組件中data聲明同樣github

data () {
    return {
    }
}

以上屬性值應修改成:web

props: {
    selections: {
      type: Array,
      default () {
        return [{
          label: 'test',
          value: 0
        }]
      }
    }
  }

使用事件拋出一個值$event 實現子組件向父組件傳值

有的時候用一個事件來拋出一個特定的值是很是有用的。例如咱們可能想讓 <blog-post> 組件決定它的文本要放大多少。這時可使用 $emit第二個參數來提供這個值:ajax

<button v-on:click="$emit('enlarge-text', 0.1)">
  Enlarge text
</button>

而後當在父級組件監聽這個事件的時候,咱們能夠經過 $event 訪問到被拋出的這個值:vuex

<blog-post
  ...
  v-on:enlarge-text="postFontSize += $event"
></blog-post>

或者,若是這個事件處理函數是一個方法

<blog-post
  ...
  v-on:enlarge-text="onEnlargeText"
></blog-post>

那麼這個值將會做爲第一個參數傳入這個方法:

methods: {
  onEnlargeText: function (enlargeAmount) {
    this.postFontSize += enlargeAmount
  }
}

問題來了,當你須要在事件處理函數中既要傳入子組件拋出的值,又想再傳入其餘參數呢?

<blog-post
      ...
      v-on:enlarge-text="onEnlargeText(index, $event)"
    ></blog-post>

$event能代替一個參數,若是是子組件多個參數呢?

aruments接收,這樣獲得一個數組,逐個取便可,或者在emit時就以 數組或對象傳遞就好

vue項目根目錄下index.html引入公共樣式如reset.css注意事項

index.html不能引入src裏的文件,src裏文件的會用webpack打包。webpack在開發時把static的文件複製到電腦內存裏,打包時會複製到static目錄下,所以建議非要在頁面頭部引入的話能夠放在static目錄下,或者能夠選擇在main.js使用import導入

例如:

<link rel="stylesheet" type="text/css" href="./static/reset.css">

或者

// main.js
import './common/style/reset.css'

vue各個生命週期該幹什麼

  • beforecreate : 能夠在這加個loading事件
  • created :在這結束loading,還作一些初始化,data已渲染,也能夠在這裏發送請求獲取頁面初始數據,實現函數自執行
  • mounted : 在這發起axios請求,拿回數據,配合路由鉤子作一些事情
  • beforeDestorydestoryed :當前組件已被刪除,清空相關內容

附生命週期圖:
lifecycle.png

Vue中使用less給元素添加背景圖片出現的問題

按照less官方文檔,url應當以下使用:

URLs
// Variables
@images: "../img";

// Usage
body {
  color: #444;
  background: url("@{images}/white-sand.png");
}

故而有了根據屏幕分辨率設置背景圖片代碼

.bg-image(@url) {
  background-image: url('@{url}@2x.png');
  @media (-webkit-min-device-pixel-ratio: 3),(min-device-pixel-ratio: 3){
    background-image: url('@{url}@3x.png');
  }
}  // 報錯報錯 找不到路徑的
這裏要使用「~」符號來告訴less引號裏面的內容不須要編譯。

正確代碼:

.bg-image(@url) {
    background-image:~"url('@{url}@2x.png')";
    @media (-webkit-min-device-pixel-ratio: 3), (min-device-pixel-ratio: 3) {
        background-image: ~"url('@{url}@3x.png')";
    }
}

若是組件裏用使用計時器

// 在組件銷燬時(即切換組件或關閉頁面),
// 調用destroyed方法清除計時器
destroyed(){
  clearTimeout(this.timer)
}

向子組件傳遞props值爲ArrayObject時的默認值設置

不能直接設置爲[]或{},最好應設置爲一個函數,好比:

{
  type: Object,
  default () {
    return {}
  }

vue 偵聽器 watch 檢查 對象鍵值的變化

先來看官方教程watch的示例應用:

watch: {
    firstName: function (val) {
      this.fullName = val + ' ' + this.lastName
    },
    lastName: function (val) {
      this.fullName = this.firstName + ' ' + val
    }
  }

可是若是監聽的是data中的對象類型的值,直接用就不妥了。
受現代 JavaScript 的限制 (以及廢棄 Object.observe),Vue 不能檢測到對象屬性的添加或刪除。因爲 Vue 會在初始化實例時對屬性執行 getter/setter 轉化過程,因此屬性必須在 data 對象上存在才能讓 Vue 轉換它,這樣才能讓它是響應的。

sell: {
//事件函數名稱必須是`handler`!!!
      handler(val) {
        if (Number(this.availSymbol)) {
          this.sellQuanPro = Math.round(val.quantity / this.availSymbol * 100) > 100 ? 100 : Math.round(val.quantity / this.availSymbol * 100);
        }
      },
      deep: true, //深度遞歸查看對象
      immediate: true, //開始時便加載一次該函數
    },
事件函數名稱必須是 handler!!!

這樣監聽了對象全部鍵值,性能開銷大,解決方案:用字符串

以下:

'sell.price': {
      handler(val) {
        console.log('TCL: handler -> val', val); //這裏`val`是`sell.price`而不是`sell`
      }
    }

安裝配置問題

部分參考可能會因時效性、版本等不適用,但願你們靈活參考使用。

vue改造多頁面應用配置注意問題(踩了神坑...)

首先修改webpack配置,文章不少,主要參考這篇連接vue多頁面開發
不想移步的童鞋來:

  1. util.js裏面尾部直接加入

    /* 這裏是添加的部分 ---------------------------- 開始 */
      
      // glob是webpack安裝時依賴的一個第三方模塊,還模塊容許你使用 *等符號, 例如lib/*.js就是獲取lib文件夾下的全部js後綴名的文件
      var glob = require('glob')
      // 頁面模板
      var HtmlWebpackPlugin = require('html-webpack-plugin')
      // 取得相應的頁面路徑,由於以前的配置,因此是src文件夾下的pages文件夾
      var PAGE_PATH = path.resolve(__dirname, '../src/pages')
      // 用於作相應的merge處理
      var merge = require('webpack-merge')
    
      //多入口配置
      // 經過glob模塊讀取pages文件夾下的全部對應文件夾下的js後綴文件,若是該文件存在
      // 那麼就做爲入口處理
      exports.entries = function () {
          var entryFiles = glob.sync(PAGE_PATH + '/*/*.js')
          var map = {}
          entryFiles.forEach((filePath) => {
              var filename = filePath.substring(filePath.lastIndexOf('\/') + 1, filePath.lastIndexOf('.'))
              map[filename] = filePath
          })
          return map
      }
    
      //多頁面輸出配置
      // 與上面的多頁面入口配置相同,讀取pages文件夾下的對應的html後綴文件,而後放入數組中
      exports.htmlPlugin = function () {
          let entryHtml = glob.sync(PAGE_PATH + '/*/*.html')
          let arr = []
          entryHtml.forEach((filePath) => {
              let filename = filePath.substring(filePath.lastIndexOf('\/') + 1, filePath.lastIndexOf('.'))
              let conf = {
                  // 模板來源
                  template: filePath,
                  // 文件名稱
                  filename: filename + '.html',
                  // 頁面模板須要加對應的js腳本,若是不加這行則每一個頁面都會引入全部的js腳本
                  chunks: ['manifest', 'vendor', filename],
                  inject: true
              }
              if (process.env.NODE_ENV === 'production') {
                  conf = merge(conf, {
                      minify: {
                          removeComments: true,
                          collapseWhitespace: true,
                          removeAttributeQuotes: true
                      },
                      chunksSortMode: 'dependency'
                  })
              }
              arr.push(new HtmlWebpackPlugin(conf))
          })
          return arr
      }
      /* 這裏是添加的部分 ---------------------------- 結束 */
  2. webpack.base.conf.js 文件

    /* 修改部分 ---------------- 開始 */
        entry: utils.entries(),
        /* 修改部分 ---------------- 結束 */
  3. webpack.dev.conf.js 文件

    /* 註釋這個區域的文件 ------------- 開始 */
          // new HtmlWebpackPlugin({
          //   filename: 'index.html',
          //   template: 'index.html',
          //   inject: true
          // }),
          /* 註釋這個區域的文件 ------------- 結束 */
          new FriendlyErrorsPlugin()
          //**注意我在新版本生成的這裏是保存static目錄的東西不用在乎**
          new CopyWebpackPlugin([{
              from: path.resolve(__dirname, '../static'),
              to: config.dev.assetsSubDirectory,
              ignore: ['.*']
          }])
          /* 添加 .concat(utils.htmlPlugin()) ------------------ */
        ].concat(utils.htmlPlugin())
  4. webpack.prod.conf.js 文件

    /* 註釋這個區域的內容 ---------------------- 開始 */
          // new HtmlWebpackPlugin({
          //   filename: config.build.index,
          //   template: 'index.html',
          //   inject: true,
          //   minify: {
          //     removeComments: true,
          //     collapseWhitespace: true,
          //     removeAttributeQuotes: true
          //     // more options:
          //     // https://github.com/kangax/html-minifier#options-quick-reference
          //   },
          //   // necessary to consistently work with multiple chunks via CommonsChunkPlugin
          //   chunksSortMode: 'dependency'
          // }),
          /* 註釋這個區域的內容 ---------------------- 結束 */
          // copy custom static assets
          new CopyWebpackPlugin([
            {
              from: path.resolve(__dirname, '../static'),
              to: config.build.assetsSubDirectory,
              ignore: ['.*']
            }
          ])
          /* 該位置添加 .concat(utils.htmlPlugin()) ------------------- */
        ].concat(utils.htmlPlugin())
  5. 改造目錄
    圖片描述

    值得注意的是:這裏的 js必定要和 html名稱同樣,我由於這個不同,卡了很久,在別的地方有說必須是 App.vue的,這個如圖,我沒用,測試界面正常顯示,可是我把默認 main.js直接移動到文件夾裏時, index.html一直是空白頁,把 main.js改成 index.js正常,若是有問題我還會探究改正
  6. 訪問方式

  7. 修改config目錄下的assetsPublicPath路徑的問題

    相信不少人都查過 npm run build後空白頁的問題而後修改 assetsPublicPath的值 /./,然而這裏改的話,全部頁面都會沒法獲取,cannot get,此處困擾我三天,一度令我以爲本身不適合這行,適合喝西北風,原本就新手學vue,也沒什麼資源,這裏解決了,但build後的問題呢,未完待續,先調好開發效果,步步爲營吧

關於新版vue-cli安裝json-server在build文件裏沒生成出dev-server文件

新版的vue-cli取消了dev-server.js和dev-client.js 改用webpack.dev.conf.js代替,因此 配置本地訪問在webpack.dev.conf.js裏配置便可

打開webpack.dev.conf.js,(在build目錄下),

const portfinder = require(‘portfinder’)後添加如下兩行代碼

const appData = require('./db.json')//加載本地數據文件
const seller = appData.seller//獲取對應的本地數據,

添加完以上代碼繼續在此文件裏面向下查找devServer:{ }

在這個對象裏添加配置,(不要刪除或覆蓋之前默認配置的值)

before(app) {
  app.get('/api/seller', (req, res) => {
    res.json({
      errno:0,
      data: seller
    })
  })
},
每更改過 webpack.dev.conf.js這個文件或者 db.json文件,記得從新 npm run dev

express啓動數據服務模擬post請求

* `config`目錄下的`index.js`,修改`dev`中的`proxyTable`爲:      
        
            proxyTable: {
                '/api/': 'http://localhost:3000/'
                }
*  `build`目錄下`webpack.dev.conf.js`文件增長             
            // express配置server
            var express = require('express')
            var apiServer = express()
            var bodyParser = require('body-parser')
            apiServer.use(bodyParser.urlencoded({ extended: true }))
            apiServer.use(bodyParser.json())
            var apiRouter = express.Router()
            var fs = require('fs')
            //apiName是你請求的方法/數據集合 不要動
            apiRouter.route('/:apiName') //接口路徑  
            .all(function (req, res) {
                fs.readFile('./data.json', 'utf8', function (err, data) {  //讀取接口文件
                    console.log(err)
                    if (err) throw err
                    var data = JSON.parse(data)
                    if (data[req.params.apiName]) {
                        res.json(data[req.params.apiName])
                    } else {
                        res.send('no such api name')
                    }
                })
            })
            apiServer.use('/api', apiRouter);
            apiServer.listen(3000, function (err) {
            
            if (err) {
                console.log(err)
                return
            }
            console.log('Listening at http://localhost:' + 3000 + '\n')
            })
*  修改build目錄下webpack.dev.conf.js文件中的devServer,增長:
            // Invalid Host header問題修復
            disableHostCheck: true
測試地址:`http://localhost:8080/apiPost/getNewsList`
這裏的請求 getpost都適用

vue項目localhost能夠訪問,IP地址替換後沒法訪問的問題

vue生成的項目啓動地址默認在http://localhost:8080/#,但若將開發移動端則需在手機上測試效果,之前老是知道hbulider本地外置服務器手機掃碼能夠訪問項目,Vue則需修改根目錄下/config/index.js

host: '0.0.0.0', // can be overwritten by process.env.HOST

即可支持ip訪問地址,手機在同局域網下就能夠預覽了未完待續

相關文章
相關標籤/搜索