desarrollo de proyectos vue, me encontré con estos problemas

En el trabajo diario, la mayoría de los proyectos se desarrollan utilizando vue, por lo que aquí se resumen y registran algunos problemas comunes de los proyectos vue para evitar una duplicación excesiva de trabajo en el desarrollo futuro.

Y dominar algunas habilidades útiles y usar algunos puntos técnicos más avanzados también puede hacernos mejores desarrolladores de Vue.

ver inmediatamente

Cuando watch es una variable, no se ejecutará durante la inicialización, como en el siguiente ejemplo, debe llamarlo manualmente una vez que se crea.

// bad
created() {
  this.getsearchText();
},
watch: {
  searchText: 'getSearchText',
}
复制代码

Puede agregar el atributo inmediato, para que se active durante la inicialización, y el código se puede simplificar a esto

// good
watch: {
  searchText: {
    handler: 'getSearchText',
    immediate: true,
  }
}
复制代码

salto de enrutamiento vue abre una nueva ventana

usa esto.$router.resolve

const openNewUrl=(url) => {
  let routeData = this.$router.resolve({path: url})
  window.open(routeData.href, '_blank')
  }
复制代码

el-input restringe el cuadro de entrada a solo números

<el-input v-model.number="num"  onkeyup="this.value = this.value.replace(/[^\d.]/g,'');"></el-input>
复制代码

el-filtro de entrada caracteres especiales o desensibilización de ID

v-model dividido en: valor y @input

<el-input :value="input" @input='e => input = idCardValid (e)' placeholder="请输入内容"></el-input>
复制代码
  methods:{
    idCardValid(val){
      const idCard= val.replace(/^(\d{6})\d+(\d{4})$/, "$1******$2")
      console.log(idCard)
      return idCard
    } 
},
复制代码

Use la etiqueta a para descargar archivos de recursos estáticos locales

  • 1. Los recursos estáticos a descargar se almacenan en el directorio público
  • 2. una descarga de etiquetas
 <a href="/demo.rar" download="demo.rar">点击下载</a>
复制代码

Detectar un clic fuera (o dentro) de un elemento

window.addEventListener('mousedown'e => {
  // 获取被点击的元素
  const clickedEl = e.target;
  
  if (el.contains(clickedEl)) {
   //在 "el "里面点击了
  } else {
   //在 "el "外点击了
  }
});
复制代码

La página en el marco iframe controla la página del marco principal para saltar a una dirección

const { href } = this.$router.resolve({ path: "/index", query: { key: key } });
// iframe 控制父页面跳转
window.parent.window.location.href = href
复制代码

ganchoEvento

uso en componente

Cuando usamos temporizadores en el desarrollo, generalmente hacemos esto

// bad
mounted() {
  // 创建一个定时器
    this.timer = setInterval(() => {
      // ......
    }, 500);
  },
  // 销毁这个定时器。
beforeDestroy() {
  if (this.timer) {
  clearInterval(this.timer);
  this.timer = null;
  }
}
复制代码

Con la ayuda de ganchos, es más fácil de mantener.

// good
mounted() {
    let timer = setInterval(() => {
      // ......
    }, 500);
    this.$once("hook:beforeDestroy", function() {
      if (timer) {
        clearInterval(timer);
        timer = null;
      }
    });
  }
复制代码

Escuche las funciones del ciclo de vida de los componentes secundarios

original

//父组件
<child
 :value="value"
 @childMounted="onChildMounted"
/>
method () {
 onChildMounted() {
 // do something...
 }
},

// 子组件
mounted () {
 this.$emit('childMounted')
},
复制代码

manos:

//父组件
<child
  :value="value"
  @hook:mounted="onChildMounted"
/>
method () {
  onChildMounted() {
  // do something...
  }
},
复制代码

En los componentes de Vue, puede usar $on,$onceel pasado monitorear todas las funciones de enlace del ciclo de vida.Por ejemplo, la función de enlace actualizada del componente del monitor se puede escribir comothis.$on('hook:updated', () => {})

Funciones del ciclo de vida del oyente externo

A veces nos encontramos con una situación de este tipo, utilizando un componente de terceros, cuando necesitamos monitorear los cambios en los datos del componente de terceros, pero el componente no proporciona un evento de cambio. @hook:updatedPodemos usar la función de gancho de vida actualizada proporcionada por Vue para escuchar el componente

<template>
  <!--通过@hook:updated监听组件的updated生命钩子函数-->
  <!--组件的所有生命周期钩子都可以通过@hook:钩子函数名 来监听触发-->
  <custom-select @hook:updated="onSelectUpdated" />
</template>
<script>
import CustomSelect from './components/custom-select'
export default {
  components: {
    CustomSelect
  },
  methods: {
    onSelectUpdated() {
      console.log('custom-select组件的updated钩子函数被触发')
    }
  }
}
</script>
复制代码

Vue salta a la misma ruta e informa un error

Agregue el siguiente código al enrutador js de vue, antes del nuevo VueRouter

const originalPush = VueRouter.prototype.push
const originalReplace = VueRouter.prototype.replace
// push
VueRouter.prototype.push = function push(location, onResolve, onReject) {
  if (onResolve || onReject) return originalPush.call(this, location, onResolve, onReject)
  return originalPush.call(this, location).catch(err => err)
}
// replace
VueRouter.prototype.replace = function push(location, onResolve, onReject) {
  if (onResolve || onReject) return originalReplace.call(this, location, onResolve, onReject)
  return originalReplace.call(this, location).catch(err => err)
}
复制代码

Vue-cli3 informa el error Error al cargar el recurso: net::ERR_FILE_NOT_FOUND después del empaquetado

Cree un nuevo archivo vue.config.js en el directorio raíz

// vue.config.js
module.exports = {
  publicPath: './'
}
复制代码

默认情况下,Vue CLI 会假设你的应用是被部署在一个域名的根路径上,例如 www.my-app.com/。如果应用被部署在一个… www.my-app.com/my-app/,则设置 publicPath 为 /my-app/。

这个值也可以被设置为空字符串 ('') 或是相对路径 ('./'),这样所有的资源都会被链接为相对路径,这样打出来的包可以被部署在任意路径。

css解决fixed布局不会出现滚动条的问题

如果我们布局的是fixed并且想要高度为100%的时候,我们一般会这样设置:

div {
    display:fixed;
    height:100%;
    overflow:scroll;
}
复制代码

但是这样的话不会出现滚动条,设置

div {
  top: 0;
  bottom:0;
  position:fixed;
  overflow-y:scroll;
  overflow-x:hidden;
}
复制代码

require.context() 自动注册

require.context():

你可以通过 require.context() 函数来创建自己的 context。

可以给这个函数传入三个参数:一个要搜索的目录,一个标记表示是否还搜索其子目录, 以及一个匹配文件的正则表达式。

webpack 会在构建中解析代码中的 require.context() 。

// 利用require.context()自动引入 除 index.js 外其他 js 文件
const routerContext = require.context('./', true, /\.js$/)
routerContext.keys().forEach(route => {
  // 如果是根目录的 index.js 、不处理
  if (route.startsWith('./index')) {
    return
  }
  const routerModule = routerContext(route)
  /**
   * 兼容 import export 和 require module.export 两种规范
   */
  routes = routes.concat(routerModule.default || routerModule)
})
复制代码

生产环境去除 console.log

vue.config.js 中配置

configureWebpack: (config) => {
  if (process.env.NODE_ENV === "production") {
    config.optimization.minimizer[0].options.terserOptions.compress.drop_console = true;
    config.optimization.minimizer[0].options.terserOptions.compress.pure_funcs = [
      "console.log",
    ];
  }
}
复制代码

vue+elementUI在输入框中按回车键会刷新页面

当一个 form 元素中只有一个输入框时,在该输入框中按下回车应提交该表单。如果希望阻止这一默认行为,可以在 <el-form> 标签上添加 @submit.native.prevent。

<templat>
<el-form   @submit.native.prevent >< /el-form >
</templat>
复制代码

el-select 下拉框样式修改

使用样式穿透修改下拉框样式,你会发现打死都不生效,那是因为下拉框是默认挂载在 body 下面。解决办法:设置 :popper-append-to-body="false",然后再用样式穿透

element-ui select组件change事件传递多个参数的方法

  1. 方法一
@change="onChange($event,customParam)"
复制代码
  1. 方法二
@change="((val)=>{changeEvent(val,args)})"  
复制代码

其他组件的的默认事件同样的方法传递

<el-dropdown trigger="click" @command="((val)=>{handleCommand(val,scope.row)})">
  <span class="el-dropdown-link">
    <i class="el-icon-more el-icon--right"></i>
  </span>
    <el-dropdown-menu slot="dropdown">
        <el-dropdown-item command="volumes">新增</el-dropdown-item>
        <el-dropdown-item command="log">查看</el-dropdown-item>
        <el-dropdown-item command="shell">更新</el-dropdown-item>
        <el-dropdown-item command="container">删除</el-dropdown-item>
    </el-dropdown-menu>
</el-dropdown>
复制代码

el-input type=number 去除聚焦时的上下箭头

解决

<el-input class="clear-number-input" type="number"></el-input>

<style scoped>
.clear-number-input ::v-deep input[type="number"]::-webkit-outer-spin-button,
.clear-number-input ::v-deep input[type="number"]::-webkit-inner-spin-button {
    -webkit-appearance: none !important;
}
</style>
复制代码

chrome表单自动填充导致input文本框背景失效

我们在开发登录页的时候经常遇到,登陆页的表单自动填充导致input文本框背景失效的问题。

// 自动填充样式覆盖
input:-internal-autofill-previewed,
input:-internal-autofill-selected {
  -webkit-text-fill-color: #fff; 
  transition: background-color 5000s ease-out 0.5s;
}
复制代码

巧用$options

$options是一个记录当前Vue组件的初始化属性选项,当我们想把 data 里的某个值重置为初始值时,非常有用

例如:

this.value = this.$options.data().value;
复制代码

dialog 里重置表单

利用上面介绍的 $options 特性

我们经常的业务场景是这样:一个el-dialog中有一个el-form,而且我们通常是新增和编辑复用同一个组件,现在我们要求每次打开el-dialog时都要重置el-form里的数据,并且清除校验状态。

  // 弹框打开时
initForm(){
  this.$refs['form'] && this.$refs['form'].resetFields()
  this.form = this.$options.data.call(this).form;
}
复制代码

将一个 prop 限制在一个类型的列表中

我们在使用 prop 时,可能会有时候需要判断该 prop 是否在我们规定的范围内(或者说规定的值内),这个时候我们可以使用 prop 定义中的 validator 选项,将一个 prop 类型限制在一组特定的值里。

  // 只能选择一个
  props: {
    type: String,
    validator(value) {
      return ['A', 'B', 'C'].indexOf(value) > -1
    }
  }
复制代码

validator 函数接收一个prop值,如果 prop 有效或无效,则返回 true 或 false。

Vue在子组件中判断父组件是否传来事件

在做二次封装时,我们经常用到,v-bind="$attrs"v-on="$listeners"进行多层组件监听,那么我们还可以利用 $listeners在子组件中判断父组件是否传来事件

例如我们封装一个搜索组件,里面有重置按钮,当我们点击重置按钮时,默认操作是清空搜索栏的值并且刷新列表,而如果父组件传来事件,则以自定义事件为准,即我们想点击重置按钮做一些其他的自定义操作。

resetFields() {
  //...
  if (this.$listeners.resetFields) {
    // 自定义事件
      this.$emit('resetFields')
    } else {
      // 默认刷新列表事件
      this.loadList()
    }
}
复制代码

同一组件上存在多个table进行tabs和v-if/v-show切换时,多表格的数据会相互混淆,串在一起,引发bug

为每个table指定对应且唯一的key属性。

其他一些类似的问题也可以尝试为其添加key属性来解决

vue element 多个 Form 表单同时验证

<template>
<el-form   ref="form1"></el-form>
<el-form   ref="form2"></el-form>
<el-form   ref="form3"></el-form>
</template>
<script>
export default{
    methods: {
      onValidate() { // 保存操作
      const formArr =['form1', 'form2','form3']//三个form表单的ref
      const resultArr = [] //用来接受返回结果的数组
      let _self = this
      function checkForm(formName) { //封装验证表单的函数
        let result = new Promise(function (resolve, reject) {
          _self.$refs[formName].validate((valid) => {
            if (valid) {
              resolve();
            } else { reject() }
          })
        })
        resultArr.push(result) // 得到promise的结果
      }
      formArr.forEach(item => { // 根据表单的ref校验
        checkForm(item)
      })
      Promise.all(resultArr).then(values => {
         // 此时必填完成,做保存后的业务操作
        //  ...
        console.log('success');
      }).catch(_ => {
        console.log('err')
      })
    },
    }
}
</script>
复制代码

Vue中的method赋值为高阶函数

<script>
  import { debounce } from "lodash";

  export default {
    methods: {
      search: debounce(async function (keyword) {
        // ... 请求逻辑
      }, 500),
    },
  };
</script>
复制代码

给 slot 插槽绑定事件

  • 1、作用域插槽 slot-scope 传方法
<!-- 伪代码:下拉框组件 -->
 
<template>
    <slot change-display="changeDisplay"></slot>
    <div v-show="visiable">*下拉框代码省略*<div>
<template>
 
<script>
export default {
    data(){
        return {
            visiable: false
        }
    }
 
    methods:{
        changeDisplay(){
            this.visiable = !this.visiable
        }
    }
}
</script>
复制代码

使用:

<!--使用下拉弹窗组件-->
<dropdown v-model="value" :list="list">
  <button slot-scope="{changeDisplay}" 
    @click="changeDisplay">{{value}}</button>
</dropdown>
复制代码
  • 2、vnode 中对应的页面元素
<!-- 伪代码:下拉框组件 -->
<template>
    <slot></slot>
    <div v-show="visiable">*下拉框代码省略*<div>
<template>
 
<script>
export default {
    data(){
        return {
            visiable: false
            reference: undefined
        }
    }
 
    methods:{
        changeDisplay(){
            this.visiable = !this.visiable
        }
    }
 
    mounted() {
        if (this.$slots.default) {
          this.reference = this.$slots.default[0].elm
        }
        if (this.reference) {
          this.reference.addEventListener('click', this.changeVisiable, false)
          // hook
          this.$once('hook:beforeDestroy', () => {
          this.reference.removeEventListener('click', this.changeVisiable)
      })
        }
    }
}
</script>
复制代码

二次封装作用域插槽

在二次封装组件时,我们知道可以通过判断 $slots.xxx 是否存在来判断我们在使用这个组件时是否传递了插槽内容。从而更好的定制默认的插槽内容。

那么在二次封装一个原本具有作用域插槽的组件时,我们可以通过 $scopedSlots.xxx 来进行判断

子组件

<template>
<Tree class="tree" v-if="items.length" :data="items" :options="options" :filter='search' ref="tree" v-model="treeModel">
<!-- 作用域插槽 -->
  <template slot-scope="{node}">
    <span v-if="!$scopedSlots.default">{{node.text}}</span>
    <slot v-else :node="node"></slot>
  </template>
</Tree>
</template>

使用

```vue
<template>
  <custom-tree ref="tree" checkbox :data='data' :props="{children:'children',text: 'text'}">
    <template slot-scope="{node}">
      <span class="tree-text">
      <!-- 自定义插槽内容 -->
        <template v-if="!node.children">
          <van-icon name="user-o" size="18" class="icon" />
            {{ node.text }}
        </template>
        <template v-else>
          {{ node.text }}
        </template>
      </span>
    </template>
  </custom-tree>
</template>
复制代码

Supongo que te gusta

Origin juejin.im/post/7119018849353072677
Recomendado
Clasificación