A: usage
The props property of vue is used by a parent component to pass values to a child component, and is a frequently used feature.
Using props requires both the parent and child components. Use v-bind in the parent to bind the props to be passed, and declare the type and default value of the props attribute in the child component. Example:
// app.vue <hello-world :testData="testData"></hello-world> export default{name:'App', Data (){return{testData:{}}}} // subcomponent export default {name:'HelloWorld', props:{testData:{type:Object, default:()=>{} } } }Copy the code
2. Processing in parent app.vue
As you can see from the example above, a property is bound to the child component tag of the parent component’s Template using the V-bind directive. We know that the contents of the template tag will pass through AST and Codegen and eventually be converted to the render function.
2.1: Processing during AST conversion
During AST transformation, attributes on the label are processed. For v-bind attributes, attrs array attributes are added to the nodes of the AST
// Vue source code SRC \compiler\parser\index.js
function processAttrs (el){
const list = el.attrsList
let i, l, name, rawName, value, modifiers, syncGen, isDynamic
for (i = 0, l = list.length; i < l; i++) {
......
if (bindRE.test(name)) { // v-bind
// line 842addAttr(el, name, value, list[i], isDynamic) } ...... }}Copy the code
2.2: Codegen processing
Codegen transforms each AST node to generate the render function. When processing nodes, the attrs attribute is processed as follows:
// Vue source code SRC \compiler\ codeGen \index.js
export function genData (el: ASTElement, state: CodegenState) :string {
let data = '{'.// attributes
if (el.attrs) {
data += `attrs:${genProps(el.attrs)}, `}... return data }Copy the code
2.3: Forms in the render function
Let’s take a look at the render function that app.vue finally generates
// app.vue's render function
var render = function() {
var _vm = this
var _h = _vm.$createElement
var _c = _vm._self._c || _h
return _c(
"div",
{ attrs: { id: "app" } },
[
_c("img", { attrs: { src: require("./assets/logo.png") } }),
_vm._v(""),
_c("HelloWorld", { attrs: { testData: _vm.testData } })
],
1)}Copy the code
_c(“HelloWorld”, {attrs: {testData: _vm.testData}})
As you can see, the property bound in the template, which is finally set to the second parameter of createElement, comes into play when the HelloWorld component is created.
Processing in the subcomponent HelloWorld.vue
The child component uses the initProps method to bind the props property to the vm._props, sets it as a responsive property, and then uses the proxy method to proxy the props property to the VM, so that the child component can access the vm directly through this.
// vue source SRC \core\instance\state.js
// Delete some code
function initProps (vm: Component, propsOptions: Object) {
const propsData = vm.$options.propsData || {}
const props = vm._props = {}
for (const key in propsOptions) {
const value = validateProp(key, propsOptions, propsData, vm)
// Set to a responsive property
defineReactive(props, key, value)
if(! (keyin vm)) {
// Proxy to the VM and can be accessed directly via this
proxy(vm, `_props`, key)
}
}
}
Copy the code