节点、树以及虚拟 DOM 单向数据流 Prop 验证 关系链

节点、树以及虚拟 DOM

<div>
  <h1>My title</h1>
  Some text content
  <!-- TODO: Add tagline -->
</div>
当浏览器读到这些代码时,它会建立一个“DOM 节点”树来保持追踪所有内容,如同你会画一张家谱树来追踪家庭成员的发展一样。

上述 HTML 对应的 DOM 节点树如下图所示:
在这里插入图片描述
每个元素都是一个节点。每段文字也是一个节点。甚至注释也都是节点。一个节点就是页面的一个部分。就像家谱树一样,每个节点都可以有孩子节点 (也就是说每个部分可以包含其它的一些部分)。

高效地更新所有这些节点会是比较困难的,不过所幸你不必手动完成这个工作。你只需要告诉 Vue 你希望页面上的 HTML 是什么,这可以是在一个模板里:

<h1>{{ blogTitle }}</h1>

或者一个渲染函数里:

render: function (createElement) {
  return createElement('h1', this.blogTitle)
}

在这两种情况下,Vue 都会自动保持页面的更新,即便 blogTitle 发生了改变。

虚拟 DOM
Vue 通过建立一个虚拟 DOM 来追踪自己要如何改变真实 DOM。请仔细看这行代码:

return createElement('h1', this.blogTitle)

createElement 到底会返回什么呢?其实不是一个实际的 DOM 元素。它更准确的名字可能是 createNodeDescription,因为它所包含的信息会告诉 Vue 页面上需要渲染什么样的节点,包括及其子节点的描述信息。我们把这样的节点描述为“虚拟节点 (virtual node)”,也常简写它为“VNode”。“虚拟 DOM”是我们对由 Vue 组件树建立起来的整个 VNode 树的称呼。

详细见官网:https://cn.vuejs.org/v2/guide/render-function.html#%E8%8A%82%E7%82%B9%E3%80%81%E6%A0%91%E4%BB%A5%E5%8F%8A%E8%99%9A%E6%8B%9F-DOM

单向数据流

//Vue/React单向数据流的体现:数据只能从父级组件流向子级组件
//实现父子间的数据共享,依靠的就是应用类型的地址传递

所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。

额外的,每次父级组件发生变更时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。

这里有两种常见的试图变更一个 prop 的情形:

这个 prop 用来传递一个初始值;这个子组件接下来希望将其作为一个本地的 prop 数据来使用。在这种情况下,最好定义一个本地的 data property 并将这个 prop 用作其初始值:

props: ['initialCounter'],
data: function () {
  return {
    counter: this.initialCounter
  }
}

这个 prop 以一种原始的值传入且需要进行转换。在这种情况下,最好使用这个 prop 的值来定义一个计算属性:

props: ['size'],
computed: {
  normalizedSize: function () {
    return this.size.trim().toLowerCase()
  }
}

注意:在 JavaScript 中对象和数组是通过引用传入的,所以对于一个数组或对象类型的 prop 来说,在子组件中改变变更这个对象或数组本身将会影响到父组件的状态。

详细参考:https://cn.vuejs.org/v2/guide/components-props.html#%E5%8D%95%E5%90%91%E6%95%B0%E6%8D%AE%E6%B5%81

Prop 验证

// props的值可以是对象,在里面可以对父组件传过来的数据做出验证,如果验证失败,会抛出警告
//如果子组件没有通过props来接收父组件传递的某个数据,该属性就会出现在子组件模板的最外层节点上面

<body>
    <div id="app">
        <father :msg="msg"></father>
    </div>
    <template id="father">
        <div>
            <p>这是father组件... {{msg}} </p>
        </div>
    </template>
</body>
<script src="./base/vue.js"></script>
<script>
new Vue({
    el:"#app",
    data:{
        msg:10
    },
    components:{
        father:{
            template:"#father",
            // props:["msg"]
            // props:{
            //     msg:[Number,String] //验证传的值是什么类型
            // }
            props:{
                msg:{
                    type:Number,
                    // required: true, //必传
                    default:1 //默认值
                }
            }
        }
    }
})

</script>

注意那些 prop 会在一个组件实例创建之前进行验证,所以实例的 property (如 data、computed 等) 在 default 或 validator 函数中是不可用的。
详细参考:https://cn.vuejs.org/v2/guide/components-props.html#%E5%8D%95%E5%90%91%E6%95%B0%E6%8D%AE%E6%B5%81

关系链

<body>
    <div id="app">
        <aaa></aaa>
    </div>

<template id="aaa">
    <div>
        <p>这是A组件...</p>
        <input type="text" v-model="msg">
        <hr>
        <bbb :msg="msg"></bbb>  
    </div>
</template>
<template id="bbb">
    <div>
        <input type="text" v-model="ownMsg">
    </div>
</template>
</body>
<script src="./base/vue.js"></script>
<script>
// 组件、实例对象上有这样的属性:$parent,$children,$root,
//这样的话,就形成了viewmodel链(关系链),理论上来说,
//任何两个组件之间的数据都可以互相调用,获取
//缺点:太乱了 this.$root.$children[3].$children[4]....

Vue.component("aaa",{
    template:"#aaa",
    data(){
        return {
            msg:"hello"
        }
    }
})
Vue.component("bbb",{
    template:"#bbb",
    props:["msg"],
    computed:{
        // ownMsg(){
        //     return this.msg
        // }
        ownMsg:{
            get(){
                return this.msg;
            },
            set(val){
                //需要aaa组件自己更改自身数据
                this.$parent.msg = val
            }
        }
    }
})
var vm = new Vue({
    el:"#app"
})
</script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值