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