步步向前之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访问地址,手机在同局域网下就能够预览了未完待续

相关文章
相关标签/搜索