mergeField解析


mergeOptions 配置选项合并,它存在2种情况 子组件合并根实例合并, 参数中的 parent 会根据调用上下文的不同而不同,可能是 Vue.option 中的配置,也可能是 组件中用户传入的配置

mergeOptions 代码片段

var options = {}
var key

for(key in parent) {mergeField(key)}
for(key in child) {mergeField(key)}

function mergeField(key) {
	var strat = strats[key] || defaultStrat
	options[key] = strat(parent[key],child[key],vm)
}

strats 对象

starts 对象预制了一些方法用来处理一些固定的配置项

el 、propsData

这2个选项将使用默认合并方法defaultStrat 合并数据, 但是它们只有在通过new创建实例的时候才有效, 如果不是在实例时合并,就会提示错误

strats.el = strats.propsData = function(parent,child,vm,key){
	if(!vm) {...}
	return defaultStrat(parent,child)
}

defaultStrat函数在文章最后有说明

data

合并data配置项,parentV 是 Vue.options.data 或者 一个父组件 , childV就是用户传入的 data选项, 第三个参数为vue实例

strats.data = function(parentV,childV,vm) {
	if(!vm) {
		if(childV && typeof childV != "function") {
			return parentV
		}
		return mergeDataOrFn(parentV,childV)
	}
	return mergeDataOrFn(parentV,childV,vm)
}

第三个参数vm, 它在子组件合并时是不存在的

Sub.options = mergeOptions(
	Super.options,
	extendOptions
)

mergeDataOrFn

  1. 子组件合并
  2. Vue创建实例时合并

第一种: 子组件的合并

  • 在通过 Vue.component 创建一个子组件的时候,合并 data 的参数是 Vue.options.data 和 子组件传入的data函数
const childVm = Vue.component("childVm ",{data(){...}})

// 模拟合并时参数
mergeDataOrFn(Vue.options.data , data)
  • extend 继承另一个子组件
const super = Vue.component("super",{data(){...}})
const parent = Vue.component("parent",{data(){...}})
const child = parent.extend(super)

// 模拟合并时参数
mergeDataOrFn(super.options.data , parent.options.data)
  • mixin 混入配置选项
const parent = Vue.component("parent",{})
parent.mixin({data(){...}})

// 模拟合并时参数
mergeDataOrFn(parent.options.data , data)

根据上面的原则,返回data函数 或者 mergeDataFn函数

function mergeDataOrFn(parentV,childV,vm) {
	if(!vm) {
		if(!childV) {
			return parentV
		}
		if(!parentV) {
			return childV
		}
		return function mergeDataFn() {
			return mergeData(
				typeof childV === "function" ? childV.call(this,this) : childV,
				typeof parentV === "function" ? parentV.call(this,this) : parentV 
			)
		}
	}
}

第二种:vue实例的合并,它直接返回一个闭包函数,其实策略与子组件合并大同小异

if(!vm){
	...
} else {
	return function mergedInstanceDataFn() {
		var instanceData = typeof childVal === 'function' ? childVal(vm,vm) : childVal
		var defaultData = typeof parentVal === 'function' ? parentVal(vm,vm) : parentVal
		if(instanceData) {
			return mergeData(instanceData,defaultData)
		} else {
			return defaultData
		}
	}
}

props、methods、inject、computed

这几个属性公用一个函数,功能是一致的. 如果 parentV上有这几项配置, 那么就和传入的配置项合并到一个空的对象中并返回, 否则就直接返回用户传入的配置项 . 完整代码:

strats.props = 
strats.methods = 
strats.inject = 
strats.computed = function (parentV,childV,vm,key) {
	if(!parentV) {return childV}
	var ret = Object.create(null)
	extend(ret,parentV)
	if(childV){extend(ret,childV)}
	return ret
}

watch

先看看合并后的结果,如果两边都有数据,则合并后的watch是一个数组

watch: {
  test: [fn,fn]
}
  • 只要有一侧没有设置 watch,就原样返回另一侧
  • 两边都有时,先遍历 parentV 的watch把属性添加到临时变量ret上,再遍历用户传入的配置
stras.watch =  function (parentV,childV,vm,key) {
  if(!parentV) {return childV}
  var ret = {}
  extend(ret,parentV)
  for(var key$1 in childV) {
    var parent = ret[key$1]
    var child = child[key$1]
    if(parent && !Array.isArray(parent)) {
      parent = [parent]
    }
    ret[key$1] = parent ? parent.concat(child) : Array.isArray(child) ? child : [child]
  }
  return ret
}

现在对遍历用户传入的配置做一下拆分,那么for-in的代码可以理解为:

for(var key in childV) {
  var parent = parentV[key]
  var child = childV[key]
  if(parent && !Array.isArray(parent)) {
    parent = [parent]
  }
  if(child && !Array.isArray(child)) {
    child = [child]
  }
  ret[key] = parent ? parent.concat(child): child
}

provide

provide 则使用与 data 合并时一样的 mergeDataOrFn函数, 只要有一侧没有 provide 就不会合并, 原样返回有数据的那一侧.否则返回 mergeDataFn 闭包函数,将在实例化的时候调用

strats.provide = mergeDataOrFn

components、directives、filters

这3个配置项将使用 mergeAssets 合并, 首先将 Vue.options 中对应的属性作为原型创建一个新的对象(之前Vue.extend的分析中了解到初始的Vue.options中是含有默认的 components、directives、filters),然后遍历用户传入的配置,依次添加到这个对象上

var res = Object.create(parent || null)
return extend(red,child)
/************************/
function extend(to,from) {
	for(var key in from) {
		to[key] = from[key]
	}
	return to
}

生命周期函数合并

生命周期函数使用 mergeHook 合并数据, 处理后的生命周期是一个数组

var LIFECYCLE_HOOLS = [
	'beforeCreate',
	'created',
	'beforeMount',
	'mounted',
	'beforeUpdate',
	'updated',
	'beforeDestroy',
	'destroyed',
	'activated',
	'deactivated'
]
LIFECYCLE_HOOLS.forEach(function(hook){
	strats[hook] = mergeHook
})

/************************/

function mergeHook(parentV,childV) {
	var res = childV ? (parentV ? parentV.concat(childV) : Array.isArray(childV) ? childV : [childV]) : [parentV]
	return res ? dedupeHooks(res) : res
}

为了简述这个三元表达式,我以 if() 表述帮助分析,大致如下:

  • 用户传入了某个生命周期函数并且Vue.options中也有一样的,则把用户传入的添加到数组的末尾.也就是这样形式
    created: [fn,fn]
    
  • 用户传入了但是Vue.options上没有,如果不是数组则包装成数组[ childV ],否则原样返回
  • 用户没有传入,但Vue.options上有,则把它包装成数组[ parentV ] 返回
var res = null
if(childV) {
	if(parentV) {
		res = parentV.concat(childV)
	} else {
		res = Array.isArray(childV) ? childV : [childV]
	}
} else {
	res = [parentV]
}

最后再调用去重方法 dedupHooks, 这部分就不分析了,代码也很简单

function dedupHooks(hooks) {
	var res = []
	for(var i = 0; i < hooks.length; i++) {
		if(res.indexOf(hooks[i] === -1)) {
			res.push(hooks[i])
		}
	}
	return res
}

defaultStrat 合并方法

除了 strats 预制的合并方法, 其余的都用 defaultStart 来处理合并, 它内部就是一个三元表达式, 用户有传入配置就使用用户传入的,否则使用 parentV 上的

function defaultStart(parentVal,childVal) {
  return childVal === undefind ? parentVal : childVal 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据你的描述,我理解你的问题是想要将一个包含复选框、多行数据的DataGridView控件中选中的行的第8列和第10列数据导入到一个Word文档中的域。 如果我的理解有误,请指出并提供更具体的描述。 首先,你需要遍历DataGridView控件中的所有行,找到被选中的行。对于被选中的每一行,你需要获取第8列和第10列的数据,并将这些数据插入到Word文档的域中。最后,你需要保存并关闭Word文档。 下面是一个示例代码,可以实现上述功能: ```c# private void ExportToWord() { // 创建Word文档对象 Microsoft.Office.Interop.Word.Application wordApp = new Microsoft.Office.Interop.Word.Application(); Microsoft.Office.Interop.Word.Document doc = wordApp.Documents.Add(); // 遍历DataGridView中的所有行 foreach (DataGridViewRow row in dataGridView1.Rows) { // 如果当前行被选中 if (row.Selected) { // 获取第8列和第10列的数据 string col8Data = row.Cells[7].Value.ToString(); string col10Data = row.Cells[9].Value.ToString(); // 在Word文档中插入域,并设置域的内容为第8列和第10列的数据 Microsoft.Office.Interop.Word.Range range = doc.Content; range.Collapse(Microsoft.Office.Interop.Word.WdCollapseDirection.wdCollapseEnd); range.InsertAfter("{" + col8Data + "}"); range.Fields.Add(range, Microsoft.Office.Interop.Word.WdFieldType.wdFieldEmpty, "MERGEFIELD " + col8Data, true); range.Collapse(Microsoft.Office.Interop.Word.WdCollapseDirection.wdCollapseEnd); range.InsertAfter("{" + col10Data + "}"); range.Fields.Add(range, Microsoft.Office.Interop.Word.WdFieldType.wdFieldEmpty, "MERGEFIELD " + col10Data, true); } } // 保存并关闭Word文档 doc.SaveAs2(@"C:\test.docx"); doc.Close(); wordApp.Quit(); } ``` 请注意,此代码仅供参考,你需要根据自己的具体需求进行修改和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值