周末在家刷如懿传,顺带在youtube看了一个7-secret-patterns-about-vue的视频,讲得还蛮有意思的,确实有些地方意想不到。更多内容参见作者的github仓库

productivity Boosts

smart watchers

watch : {
  msg: {
    handler: 'fetchUserList', // fetchUserList is one of this.methods
    immediate: true  // call it on created
  }
}

component Registration

用webpack的require.context来引入到处都会用到的components,注意缺点是打出来的包体积会变大,不如用到哪个引入哪个小。

// main.js
const requireComponent = require.context('.', false, /base-[\w-]+\.vue$/)

requireComponent.keys().forEach(fileName => {
  const componentConfig = requireComponent(fileName)
  const copmponentName = upperFirst(
    camelCase(fileName.replace(/^\.\//,'').replace(/\.\w+$/,''))
  )
  Vue.component(componentName, componentConfig.default || componentConfig)
})

这里先去找default再去找本身,是因为import/export的机制与commonjs的引入机制不同。es6里的import会自动import它的default,commonjs则不同。另外我用的是vue-cli3,在main.js中引入.vue文件,内容是在default中,不管有没有<script>标签。

module Registration

跟component Registration 原理一样,但不用考虑增加了包体积的问题,相比更为实用。注意在forEach中需要加上这句,把本身摘出去。

// index.js
if(fileName === './index.js') return

// 如果要加上namespaced, 用解构写法
modules[moduleName] = {
  namespaced: true,
  ...requireModule(fileName)
}

radical Tweaks

cleaner views

在router-view上挂一个key,每次都重新生成。就不用watch route 的变化了。

// html
<router-view :key="$route.params.id">
// .vue
created() {
  this.getPost(this.$route.params.id)
}

transparent Wrappers

适用于表单控件,把父组件的$listeners传给了子组件。v-on上和v-bind上都可以传入对象,分别绑$attrs和$listeners。

<!--BaseInput.vue-->
<template>
  <label>
    {{ label }}
    <input v-bind="$attrs" :value="value" v-on="listeners" />
  </label>
</template>
<!--App.vue -->
<BaseInput placeholder="who am i" @focus="doSomething" />
listeners() {
  return {
    ...this.$listeners,
    input: event => this.$emit('input', event.target.value)
  }
}

unlocked Possibilities

single-root component

适用于要列表渲染但没有一个根元素的时候。直接render jsx。

// LI.vue
<script>
export default {
  functional: true,
  render(h, {props}) {
    return props.route.map(route => 
      <li key={route.name}>
        <router-link to={route}>
         {route.title}
        </router-link>
      </li>
    )
  }
}
</script>

rendering non-html

用于和第三方库共同使用的时候,实际的渲染是第三方库做的。主要包括三点:

  • created的时候 从$parent里拿到父组件,获取其data来操作。
  • beforeDestroy的时候,同样获取$parent的属性,移除第三方库的方法。
  • 手写render,return null。
    这个代码比较多,具体可以参见作者的sandbox
Logo

前往低代码交流专区

更多推荐