Vue两大核心
- 组件化
- 数据驱动
插件开发核心
- 以默认配置为优先,以用户配置为覆盖;
- 自定义策略
- vue自定义策略配置
<script>
//配置对象
let vm = new Vue({
data: {
id: 'fiona'
}
});
console.log(vm.$options);
</script>
从上图可以看到,传入的data是个对象,但是vue将options变成了一个function,为什么了?
function initMixin (Vue) {
Vue.prototype._init = function (options) {
vm.$options = mergeOptions(
resolveConstructorOptions(vm.constructor),
options || {},
vm
);
}
}
function resolveConstructorOptions (Ctor) {
options = Ctor.options = mergeOptions(superOptions, Ctor.extendOptions);
}
//组件:parent:父组件对象 child:组件 vm实例
function mergeOptions (
parent,
child,
vm
) {
if (!child._base) {
if (child.extends) {
parent = mergeOptions(parent, child.extends, vm);
}
if (child.mixins) {
for (var i = 0, l = child.mixins.length; i < l; i++) {
parent = mergeOptions(parent, child.mixins[i], vm);
}
}
}
var options = {};
var key;
//key指的是components directives filters var ASSET_TYPES = ['component','directive', 'filter'];
for (key in parent) {
mergeField(key);
}
for (key in child) {
//父组件和子组件都有的字段,只做一次策略处理
if (!hasOwn(parent, key)) {
mergeField(key);
}
}
//自定义策略
function mergeField (key) {
var strat = strats[key] || defaultStrat;
options[key] = strat(parent[key], child[key], vm, key);
}
return options
}
//自定义策略处理
strats.data = function (
parentVal,
childVal,
vm
) {
if (!vm) {
if (childVal && typeof childVal !== 'function') {
warn(
'The "data" option should be a function ' +
'that returns a per-instance value in component ' +
'definitions.',
vm
);
return parentVal
}
return mergeDataOrFn(parentVal, childVal)
}
return mergeDataOrFn(parentVal, childVal, vm)
};
function mergeDataOrFn (
parentVal,
childVal,
vm
) {
return function mergedInstanceDataFn () {
}
}
//自定义策略函数:比如count 策略函数
Vue.config.optionMergeStrategies.count = function(parent,child,vm){
return child>=10?child:10;
}
function initGlobalAPI (Vue) {
// config
var configDef = {};
configDef.get = function () { return config; };
{
configDef.set = function () {
warn(
'Do not replace the Vue.config object, set individual fields instead.'
);
};
}
Object.defineProperty(Vue, 'config', configDef);
}
- 从上面源码可以分析得知vue组装配置的过程:
- 有默认策略,以默认配置为优先,用户配置为覆盖;
- 有自定义策略,如strats.data,里面组装了data的策略;
- 提供用户自第一策略接口,可以自定义一些策略,比如这里可以权限处理;
无所不能的render函数
//Button.vue
<script>
export default{
props:{
type:{
type:String,
default:'normal'
},
text:{
type:String,
default:'demo'
}
},
render(h){
return h('div',{
class:{
btn:true,
'btn-success':this.type === 'success',
'btn-danger':this.type === 'danger',
'btn-warning':this.type === 'warning',
'normal':this.type === 'normal',
},
domProps:{
innerText:this.text
},
on:{
click:this.clickEvent
}
})
},
methods:{
clickEvent:function(){
this.$emit('childClick');
}
}
}
</script>
<style scoped>
.btn{
width:100px;
height:40px;
line-height:40px;
text-align:center;
color:#ffffff;
}
.btn-success{
background:green;
}
.btn-danger{
background:red;
}
.btn-warning{
background:orange;
}
.normal{
background:blueviolet;
}
</style>
路由分区,动态路由,按需加载
注册全局组件
//global.js,在main.js引入该文件
import Vue from 'vue';
function changeStr(str){
return str.charAt(0).toUpperCase() + str.slice(1);
}
const requireComponent = require.context('.',false,/\.vue$/);
requireComponent.keys().forEach(fileName => {
const config = requireComponent(fileName);
const componentName = changeStr(fileName.replace(/^\.\//,'').replace(/\.w+$/,''));
Vue.component(componentName,config.default || config)
});
路由分区,并且统一加入路由
//router下的index.js中统一注册
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
Vue.use(Router)
const routerList = [];
function importAll(r){
r.keys().forEach(key => {
routerList.push(r(key).default);
});
}
importAll(require.context('.',true,/\.routes\.js/));
export default new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
},
...routerList
]
})