vue中实用小技巧,长期更新
1、在vue 中使用webpack require.context工程化配置组件,不用一个一个import注册了
main.js中
import Vue from 'vue'
//使用lodsh插件
import upperFirst from 'lodash/upperFirst' import camelCase from 'lodash/camelCase' const requireComponent = require.context( // 其组件目录的相对路径 './components', // 是否查询其子目录 false, // 匹配基础组件文件名的正则表达式 /Base[A-Z]\w+\.(vue|js)$/ ) requireComponent.keys().forEach(fileName => { // 获取组件配置 const componentConfig = requireComponent(fileName) // 这个地方直接传入filename其实就是内部会调用了resolve方法,会返回对应的文件内容(不理解可以console一下看看) // 获取组件的 PascalCase 命名 const componentName = upperFirst( camelCase( // 获取和目录深度无关的文件名 fileName .split('/') .pop() .replace(/\.\w+$/, '') ) ) // 全局注册组件 Vue.component( componentName, // 如果这个组件选项是通过 `export default` 导出的, // 那么就会优先使用 `.default`, // 否则回退到使用模块的根。 componentConfig.default || componentConfig ) })
解释
实际上是 webpack 的方法,vue 工程一般基于 webpack,所以可以使用
require.context(directory,useSubdirectories,regExp)
接收三个参数:
directory:说明需要检索的目录
useSubdirectories:是否检索子目录
regExp: 匹配文件的正则表达式,一般是文件名
2、$attrs和$listeners
1.$attrs
场景:如果父传子有很多值,那么在子组件需要定义多个 props
解决:$attrs获取子传父中未在 props 定义的值
// 父组件 <home title="这是标题" width="80" height="80" imgUrl="imgUrl"/> // 子组件 mounted() { console.log(this.$attrs) //{title: "这是标题", width: "80", height: "80", imgUrl: "imgUrl"} },
相对应的如果子组件定义了 props,打印的值就是剔除定义的属性
props: { width: { type: String, default: '' } }, mounted() { console.log(this.$attrs) //{title: "这是标题", height: "80", imgUrl: "imgUrl"} },
2.$listeners
场景:子组件需要调用父组件的方法
解决:父组件的方法可以通过 v-on="$listeners" 传入内部组件——在创建更高层次的组件时非常有用
// 父组件 <home @change="change"/> // 子组件 mounted() { console.log(this.$listeners) //即可拿到 change 事件 }
如果是孙组件要访问父组件的属性和调用方法,直接一级一级传下去就可以
正常情况下 我们使用emit就可以解决父子之间执行函数的问题 但是当孙子组件需要执行爷爷组件的函数时,我们可以使用这种方法,一层一层绑定 第二层绑定$listeners.xxx
3.动态组件
场景:做一个 tab 切换时就会涉及到组件动态加载
<component v-bind:is="currentTabComponent"></component>
但是这样每次组件都会重新加载,会消耗大量性能,所以<keep-alive> 就起到了作用
<keep-alive> <component v-bind:is="currentTabComponent"></component> </keep-alive>
这样切换效果没有动画效果,这个也不用着急,可以利用内置的<transition>
<transition> <keep-alive> <component v-bind:is="currentTabComponent"></component> </keep-alive> </transition>
transition效果参考:https://cn.vuejs.org/v2/guide/transitions.html#%E5%8D%95%E5%85%83%E7%B4%A0-%E7%BB%84%E4%BB%B6%E7%9A%84%E8%BF%87%E6%B8%A1
4.extend
场景:vue 组件中有些需要将一些元素挂载到元素上,这个时候 extend 就起到作用了
是构造一个组件的语法器
写法:
// 创建构造器 var Profile = Vue.extend({ template: '<p>{{extendData}}</br>实例传入的数据为:{{propsExtend}}</p>',//template对应的标签最外层必须只有一个标签 data: function () { return { extendData: '这是extend扩展的数据', } }, props:['propsExtend'] }) // 创建的构造器可以挂载到元素上,也可以通过 components 或 Vue.component()注册使用 // 挂载到一个元素上。可以通过propsData传参. new Profile({propsData:{propsExtend:'我是实例传入的数据'}}).$mount('#app-extend') // 通过 components 或 Vue.component()注册 Vue.component('Profile',Profile)
demo参考:https://www.jianshu.com/p/b931abe383e3
5 transformToRequire
场景:以前在写 Vue 的时候经常会写到这样的代码:把图片提前 require 传给一个变量再传给组件
// page 代码 <template> <div> <avatar :img-src="imgSrc"></avatar> </div> </template> <script> export default { created () { this.imgSrc = require('./assets/default-avatar.png') } } </script>
现在:通过配置 transformToRequire 后,就可以直接配置,这样vue-loader会把对应的属性自动 require 之后传给组件
// vue-cli 2.x在vue-loader.conf.js 默认配置是 transformToRequire: { video: ['src', 'poster'], source: 'src', img: 'src', image: 'xlink:href' } // 配置文件,如果是vue-cli2.x 在vue-loader.conf.js里面修改 avatar: ['default-src'] // vue-cli 3.x 在vue.config.js // vue-cli 3.x 将transformToRequire属性换为了transformAssetUrls module.exports = { pages, chainWebpack: config => { config .module .rule('vue') .use('vue-loader') .loader('vue-loader') .tap(options => { options.transformAssetUrls = { avatar: 'img-src', } return options; }); } } // page 代码可以简化为 <template> <div> <avatar img-src="./assets/default-avatar.png"></avatar> </div> </template>
6.为路径设置别名
1.场景:在开发过程中,我们经常需要引入各种文件,如图片、CSS、JS等,为了避免写很长的相对路径(../),我们可以为不同的目录配置一个别名
2.vue-cli 2.x 配置
// 在 webpack.base.config.js中的 resolve 配置项,在其 alias 中增加别名 resolve: { extensions: ['.js', '.vue', '.json'], alias: { 'vue$': 'vue/dist/vue.esm.js', '@': resolve('src'), } },
3.vue-cli 3.x 配置
// 在根目录下创建vue.config.js var path = require('path') function resolve (dir) { console.log(__dirname) return path.join(__dirname, dir) } module.exports = { chainWebpack: config => { config.resolve.alias .set(key, value) // key,value自行定义,比如.set('@@', resolve('src/components')) } }
7.img 加载失败
场景:有些时候后台返回图片地址不一定能打开,所以这个时候应该加一张默认图片
8、slot插槽
9、mixins混入
10、$parents与$ref
demo:https://www.cnblogs.com/hy96/p/12195131.html