22-mini-vue props

实现组件 props 功能

  1. 功能
  • 通过 setup 函数传递 props 属性
  • 在模板中通过 this 访问 props 属性
  • 不可以修改 props 属性
  1. 思路
  • 在 mountElement 函数中拦截 props 属性
  • 将 props 属性通过 el.setAttribute 设置到元素上
  1. 代码实现
  • 页面上要实现的功能,创建完 Foo,引入就可以把 子组件不涉及 props 的文本渲染过来
js 复制代码
// exmaple/Foo.js  // ✅
import {h} from '../lib/guide-mini-vue.esm.js'
export const Foo = {
  render() {
    return h("div", {},"foo:" + this.count)
  },
  setup (props) {
    console.log(props.count,'count');
    return {
    }
  }
}
js 复制代码
// example/App.js
import { h } from '../lib/guide-mini-vue.esm.js'
import { Foo } from './Foo.js'

window.self = null
export const App = {
  name: 'App',
  render() { 
    window.self = this
    return h("div",{
      id: 'root',
      class: ['red', 'hard'],
    },
    [h("p",{class:"red"}, "hi"),h(Foo,{count: 1})]  // ✅
    )
  },
  setup() {
    return {
      msg: "mini-vue-haha",
    }
  }
}
  • 具体实现
js 复制代码
// runtime-core/component.ts
import { shallowReadonly } from "../reactivity/reactive"
import { initProps } from "./componentProps"
export function setupComponent(instance) {
  initProps(instance, instance.vnode.props) // ✅ 将props挂载到实例上
  setupStatefulComponents(instance)
}

function setupStatefulComponents(instance: any) {
  const Component = instance.vnode.type
  const { setup } = Component
  instance.proxy = new Proxy({_: instance}, PublicInstanceProxyHandlers)
  if(setup) {
    // ✅ 将props传递到 setup 函数, 此时控制台已经能够打印出 props的值 在 Foo.js 中
    // ✅ 这里的 shallowReadonly 做了容错处理,具体在下面
    const setupResult = setup(shallowReadonly(instance.props))  
    handleSetupResult(instance, setupResult) 
  }
}
js 复制代码
// runtime-core/componentProps.ts 
export function initProps(instance, rawProps) {
  instance.props = rawProps || {} // ✅ 这里是做了兼容性处理,如果不做,在获取 value 时,会因为 props 为空而报错,要知道不是每个组件都有给子组件传递 props 属性
}
js 复制代码
// runtime-core/ componentPublicInstance.ts
import { hasOwn } from "../shared/index" // ✅

const publicPropertiesMap = {
  $el:(i)=>i.vnode.el
}

export const PublicInstanceProxyHandlers = {
  get({_: instance}, key) {
    let { setupState, props } = instance
    if(hasOwn(setupState,key)) { 
      return setupState[key]
    } else if(hasOwn(props, key)) { // ✅ 判断访问的 key 是否在 props 上,如果在就返回属性值,此时页面已经可以渲染到 props
      return props[key] // ✅
    }
    const publicGetter = publicPropertiesMap[key]
    if(publicGetter) {
      return publicGetter(instance)
    }
  }
}
js 复制代码
// reactive/reactive.ts
function createReactiveObject(target, baseHandlers) {
  if(!isObject(target)) { // ✅ 这是 shallowReadonly 做的容错处理
    console.warn(`target ${target} 必须是一个对象`)
    return target
  }
  return new Proxy(target, baseHandlers)
}
js 复制代码
export const hasOwn = (val, key) => {  // ✅
  if(!val) {
    return false
  }
  return Object.prototype.hasOwnProperty.call(val, key)
}
相关推荐
崔庆才丨静觅13 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby606113 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了14 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅14 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅14 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅14 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment14 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅15 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊15 小时前
jwt介绍
前端
爱敲代码的小鱼15 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax