1.0.1 • Published 5 years ago
@ijiabao/vue-any v1.0.1
Vue any
Vue开发时经常用的小轮子
安装
npm i -S @ijiabao/vue-any
全局使用
import VueAny from "@ijiabao/vue-any"
Vue.use(VueAny);
组件使用
import {Plugin1, Plugin2, ...} from "@ijiabao/vue-any"
export default{
components:{Plugin1},
directives: {name: Plugin2}
}
扩展: v-toggle
直接切换上下文的值(true|false), 相当于@click=this.foo.bar=!this.foo.bar
可以指定 <v-toggle.hover="someVal">
, 则mouseenter时置为true, mouseleave时置为false
<template>
<div>
<button v-toggle="opt.state1">点我直接修改$this.opt.state1</button>
状态: {{opt.state1}}
</div>
</template>
<script>
export default{
data(){
opt:{
state1: false
}
}
}
</script>
简单实现原理,参考v-model
的双向绑定方法,当input有变时,直接修改上下文引用的值 (并不是通过$emit)
Vue.directive('toggle', {
bind(el, binding, vnode){
let attr = binding.expression, $vm = vnode.context;
el.addEventListener("click", ()=>{
$vm[attr] = !$vm[attr];
})
}
})
// 如果表达式是多级子域对象,使用evel("$vm."+attr+"="+val);
Router view自动加载
例如,动态匹配 /demo/foo-bar
将自动加载 @/views/{子目录/}FooBar.vue
仅用于router-view
import ViewPromise from "@ijiagao/vue-any/src/lib/view-promise";
export default new Router({
mode: "history",
base: process.env.BASE_URL,
routes: [
{
path: "/demo/abc", // 非匹配的放在前面,优先
},
{
path: "/demo/:view", // 匹配参数必须是:view, 会把 :view 的蛇形名称 解析为首字母大写形式的文件名
component: ViewPromise,
props:{dir: "demos"} // 可指定子目录
}
]
});
实现原理
使用渲染函数实现
<component :is=()=>import(dir+someVal) />
(vue version : 2.6)createElement 中的
tag
参数, 在官方文档里没有说明- 无论是否使用此组件
- 在使用
() => import(目录 + 名称)
时, 目录须写死,告诉编译器在哪个目录, 且目录下的所有文件都会预编译成chunk
, 在实际需要的时候动态加载到页面里去 - render 函数里不可出现
()=>import(someVal)
的形式,否则Promise
死循环
- 在使用
export default {
computed: {
viewPromise() {
let viewName = this.$route.params["view"] + ".vue"; // 需进行大小写转换
return () => import("@/views/" + viewName);
}
},
render(createElement) {
// viewPromise 必须是本地变量,不能直接写在此函数里,否则死循环
return createElement(this.viewPromise, { tag: "component" });
}
};