欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

记录Vue开发过程碰到的一些问题记录

程序员文章站 2022-04-24 14:25:37
...

组件

组件样式

scoped会把样式限制在组件内,不能影响其他组件或子组件,要想影响子组件可以使用深度选择器>>>,例如:.m-con >>> .u-center

解决前后端分离开发阶段测试跨域问题

proxyTable: {
    // 用于开发,解决前后端分离开发的跨域问题
    '/api': {
        target: 'http://127.0.0.1:8000/',
        changeOrigin: true
    },
}
// 跨域解决后还有个问题就是后端重定向,需要将重定向的地址也代理到相应的地址上,配置如下:
onProxyRes: function(proxyRes, req, res) { // 监听代理的返回结果
  const location = proxyRes.headers['location']
  const locationRE = /http(?:s)?:\/\/[0-9.:]+?(\/.*?[a-zA-Z]+)$/
  if(location) {  // 解决前后端分离,后端重定向问题
      const matched = location.match(locationRE)
      const matchGroup = matched && matched[1]
      proxyRes.headers['location'] =  matchGroup ? `http://xx.xx.xx.xx:8081${matchGroup}` : location
      }
  }

动画组件

// 几个注意的点,容易被坑
// 各个过渡阶段的类名会添加到根节点上,即transition组件中的根节点
// 类名中如果嵌套使用选择器在过渡类名下需要加入过渡时间,动画也是如此,否则过渡或动画会一闪而过
.match-slider-enter-active{
  transition: all 5s;
  .g-top{
    .m-top {
      animation: leftSlider 5s;
    }
    .m-bottom{
      animation: rightSlider 5s;
    }
  }
}

采坑

配置网站facvicon.ico,图片要放在项目的根目录下,然后在build目录下的webpack.dev.conf.js和webpack.prod.conf.js的new HtmlWebpackPlugin中配置

new HtmlWebpackPlugin({
  filename: 'index.html',
  template: 'index.html',
  inject: true,
  favicon: path.resolve('favicon.png')
})

解决IE上placeholder的兼容性问题,使用到vue的mixins

// 定义mixin
import {isIE, supportPlaceholder} from 'common/js/env.js'

export const fixPlaceholder = {
  methods: {
    _fixPlaceholder() {
      if(isIE && !supportPlaceholder) {
        const inputs = document.querySelectorAll('input')
        for(let i = 0; i < inputs.length; i++) {
          const input = inputs[i]
          const placeholder = input.getAttribute('placeholder')
          if (input.type === 'password') {
            input.setAttribute('data-passwd', true)
            input.type = 'text'
            input.value = placeholder
          } else {
            input.value = placeholder
          }

          input.onfocus = function (e) {
            if(e.target.value === placeholder) {
              e.target.value = ''
            }
          }

          input.onblur = function (e) {
            if(e.target.value.trim() === '') {
              e.target.value = placeholder
            }
          }
        }
      }
    }
  }
}

Axios采坑

// post请求默认把请求对象转成json,不管是否设置了Content-Type': 'application/x-www-form-urlencoded,如果要传入表单类型的数据就需要使用qs

import qs from 'qs'

export function login(userName, passWord, validateCode) {
  return netWork.post(apis.common.login, qs.stringify({
    userName: userName,
    passWord: hex_md5(passWord),
    validateCode: validateCode.toUpperCase()
  })).then((res) => {
    return Promise.resolve(res.data)
  })
}

Element-ui采坑

table组件表头和内容错误,使用如下样式代码解决

@aaa: ~'>>>';

.wrap {
    @{aaa} .component1 {
        width: 120px;
    }
  /deep/ .component2 {
        width: 130px;
  }
}

table组件列宽度设置百分比使用min-width属性

设置表头颜色,在el-table上设置:header-cell-style="{background: ‘#f2f2f2’, color: ‘#666’}"

vuecli3

去掉代码混淆config.optimization.minimize(false)
打包时去掉console
configureWebpack: (config)=>{
    if(process.env.NODE_ENV === 'production'){
    // 返回一个将会被合并的对象
    return {
     optimization:{
       minimizer: [
         new TerserPlugin({
           sourceMap:false,
           terserOptions:{
             compress:{
               drop_console : true
             }
           }
         })
       ]
     }
    }
    }
}
分析工具:webpack-bundle-analyzer,需要做如下配置,然后npm run build --report
chainWebpack (config) {
  if (process.env.NODE_ENV === 'production') {
    // 为生产环境修改配置
    config.optimization.minimizer('terser').tap((args) => {
      args[0].terserOptions.compress.drop_console = true // 打包时去掉console输出
      return args
    })

    // 打包分析工具
    config.plugin('webpack-bundle-analyzer')
      .use(require('webpack-bundle-analyzer).BundleAnalyzerPlugin).end()
  }
}

插槽

基本使用

// 父级:
<template v-slot:header="scope">
  {{scope.xxx}}
</template>

// 父级(Render):
h('SlotChildRender', {
  props: {
    columns: ['name', 'age'],
  },
  scopedSlots: {
    default(props) {
      return h('div', `slot child render ${props.message}`)
    },
    name(props) {
      return h('div', `name: ${props.name}`)
    },
    age(props) {
      return h('div', `age:${props.age}`)
    }
  }
})


// 子级(template写法):
<slot name="header" :name1="name1"></slot>
// 子级(Render写法):
return h('div', [
  this.$scopedSlots.default({
    message: this.message,
    name: this.name,
    age: this.age
  }),
  ...this.columns.map(item => {
    console.log('item');
    console.log(item);
    return this.$scopedSlots[item]({
      name: this.name,
      age: this.age
    })
  })
])

静态插槽使用this. s l o t s , 动 态 插 槽 使 用 t h i s . slots,动态插槽使用this. slots使this.scopedSlots

// 静态插槽:
render: function (createElement) {
  // `<div><slot></slot></div>`
  return createElement('div', this.$slots.default)
}
// 动态插槽:
props: ['message'],
render: function (createElement) {
  // `<div><slot :text="message"></slot></div>`
  return createElement('div', [
    this.$scopedSlots.default({
      text: this.message
    })
  ])
}

如果要用渲染函数向子组件中传递作用域插槽,可以利用 VNode 数据对象中的 scopedSlots 字段:

render: function (createElement) {
  // `<div><child v-slot="props"><span>{{ props.text }}</span></child></div>`
  return createElement('div', [
    createElement('child', {
      // 在数据对象中传递 `scopedSlots`
      // 格式为 { name: props => VNode | Array<VNode> }
      scopedSlots: {
        default: function (props) {
          return createElement('span', props.text)
        }
      }
    })
  ])
}

Render渲染组件

事件 & 按键修饰符

对于 .passive、.capture 和 .once 这些事件修饰符,Vue 提供了相应的前缀可以用于 on:

修饰符 前缀

.passive	&
.capture	!
.once	~
.capture.once 或
.once.capture	~!

例如:

on: {
  '!click': this.doThisInCapturingMode,
  '~keyup': this.doThisOnce,
  '~!mouseover': this.doThisOnceInCapturingMode
}

对于所有其它的修饰符,私有前缀都不是必须的,因为你可以在事件处理函数中使用事件方法:

修饰符 处理函数中的等价操作

.stop	event.stopPropagation()
.prevent	event.preventDefault()
.self	if (event.target !== event.currentTarget) return

按键:
.enter, .13 if (event.keyCode !== 13) return (对于别的按键修饰符来说,可将 13 改为另一个按键码)
修饰键:
.ctrl, .alt, .shift, .meta if (!event.ctrlKey) return (将 ctrlKey 分别修改为 altKey、shiftKey 或者 metaKey)
这里是一个使用所有修饰符的例子:

on: {
  keyup: function (event) {
    // 如果触发事件的元素不是事件绑定的元素
    // 则返回
    if (event.target !== event.currentTarget) return
    // 如果按下去的不是 enter 键或者
    // 没有同时按下 shift 键
    // 则返回
    if (!event.shiftKey || event.keyCode !== 13) return
    // 阻止 事件冒泡
    event.stopPropagation()
    // 阻止该元素默认的 keyup 事件
    event.preventDefault()
    // ...
  }
}

插件

通过全局方法 Vue.use() 使用插件。它需要在你调用 new Vue() 启动应用之前完成:

// 调用 `MyPlugin.install(Vue)`
Vue.use(MyPlugin)

// 也可以传入一个可选的选项对象:
Vue.use(MyPlugin, { someOption: true })

开发插件:
Vue.js 的插件应该暴露一个 install 方法。这个方法的第一个参数是 Vue 构造器,第二个参数是一个可选的选项对象:

MyPlugin.install = function (Vue, options) {
  // 1. 添加全局方法或 property
  Vue.myGlobalMethod = function () {
    // 逻辑...
  }

  // 2. 添加全局资源
  Vue.directive('my-directive', {
    bind (el, binding, vnode, oldVnode) {
      // 逻辑...
    }
    ...
  })

  // 3. 注入组件选项
  Vue.mixin({
    created: function () {
      // 逻辑...
    }
    ...
  })
  
  // 4. 添加实例方法
  Vue.prototype.$myMethod = function (methodOptions) {
    // 逻辑...
  }
}

Vue底层原理

Vue 将遍历此对象所有的 property,并使用 Object.defineProperty 把这些property 全部转为 getter/setter

vuex插件

Vuex 的 store 接受 plugins 选项,这个选项暴露出每次 mutation 的钩子。Vuex 插件就是一个函数,它接收 store 作为唯一参数:

相关标签: Vue