Vue2.0笔记——组件2

组件组合


父子组件的通信

组件 A 在它的模板中使用了组件 B。它们之间必然需要相互通信:父组件可能要给子组件下发数据,子组件则可能要将它内部发生的事情告知父组件。



首先,需要在Vue实例里定义一个组件,设置data,然后在这个组件里再添加一个conponents选项,注意不要添错位置。
示例:

<div id="app">
    <my-father></my-father>
</div>
//父组件的模板
<template id="fatherTl">
    <div>
        <p>这是父组件</p>
        <p>访问父组件数据:{{name}},{{age}},姓名:{{user.name}},年龄:{{user.age}}</p>
        <my-child></my-child>
    </div>
</template>
//子组件的模板
<template id="childTl">
    <div>
        <p>这是子组件</p>
        <p>访问子组件数据:性别:{{sex}},身高:{{height}}</p>
    </div>
</template>
var vm = new Vue({
    el:‘#app‘,
    components:{
        ‘my-father‘:{
            template:‘#fatherTl‘,
            data:function(){
                return {
                    name:‘Xiao‘,
                    age:19,
                    user:{name:‘小幂幂‘,age:31}
                }
            },
            components:{
                ‘my-child‘:{
                    template:‘#childTl‘,
                    data:function(){
                        return {
                            height:166,
                            sex:‘Female‘
                        }
                    }
                }
            }
        }
    }
});

作为子组件my-child,<my-child></my-child>标签应放在父组件标签<my-father></my-father>标签内,而不能是实例挂载元素下。
如果你尝试直接在父组件模板或子组件模板中通过{{}}模板语法引用则会出现错误。
运行此案例,完美运行,你可以通过vue-devtool查看组件结构图。
目前还没有通信,只是显示了一下各自的数据,接下来传递数据了。

父向子传递数据

父向子传递数据,我们需要做的就是将要传递的数据绑定到子组件的标签上,并在子组件内通过props选项来接收。

//father模板中添加
<my-child :childName="user.name" :age="user.age"></my-child>
//接着,在my-child组件中添加选项
props:[‘childName‘,‘age‘]
//最后,我们引用name和age
//my-child模板中
<div>
    <p>这是子组件</p>
    <p>访问子组件数据:性别:{{sex}},身高:{{height}}</p>
    <p>访问父组件数据:{{childName}},{{age}}</p>//添加了这一条
</div>

接下来访问,即可看到数据显示了。
分析一下,:name和:age,这个冒号“:”后的name和age,就是,props中接收的属性名,将作为子组件的属性名,就是说这两个名可以改,无论改成什么,最后都需要通过这个名字访问。
而属性值就是引号中的user.name,user.age,它直接也是父组件的属性名

子向父传递数据

子向父传递书序需要通过事件的方式向上传递数据。要做的就是通过$emit方法触发事件,并添加附加参数(就是属性),通过事件传递数据,父组件中的事件方法接收这参数即可
示例:

//my-child模板中定义一个按钮,作为媒介,用来触发
<button @click="send">向上传递给父组件数据</button>
//组组件定义
methods:{
    send(){
        this.$emit(‘child-up‘,this.sex,this.height);
    }
}
//my-father组件模板中监听这个事件
<my-child :name="user.name" :age="user.age"  @child-up="getData"></my-child>
//所以你需要在my-father组件中定义这个getData方法来接收
//但你需注意,你必须提前初始化这些属性
methods:{
    getData(sex,height){
        this.sex=sex;
        this.height=height;
    }
}
//myfather模板中
<h3>访问子组件数据,{{sex}},{{height}}</h3>

这样,通过某个媒介(点击或其他方式)作为触发事件的方式,来传递数据,并在该实例处监听该事件,并接收数据。
此处将监听在my-child标签中,因my-chlid标签作为myfather标签的子组件,所以将getData方法定义在父组件methods中。


单向数据流

props 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是反过来不会。这是为了防止子组件无意间修改了父组件的状态,来避免应用的数据流变得难以理解。

另外,每次父组件更新时,子组件的所有 prop 都会更新为最新值。这意味着你不应该在子组件内部改变 prop。如果你这么做了,Vue 会在控制台给出警告。

接下来我们想试着修改父组件内属性的值,看看是不是会跟着修改,且如果修改prop中属性是否会出现错误。
示例:
代码较多,我们再新建一个html。我们只注册使用一个组件,因为Vue实例本身也是一个组件,它是根组件,所以在实例中components中注册一个组件作为子组件。

<div id="app">
    <p>父组件:{{age}}</p>
    <p><input type="text" v-model="name"></p>
    <hr/>
    <my-component :username="name" :age="age"></my-component>
</div>

<template id="templ">
    <p>子组件中父组件的数据,{{username}}</p>
</template>
var vm = new Vue({
    el:‘#app‘,
    data:{
        name:‘XiaoYao‘,
        age:19
    },
    components:{
        ‘my-component‘:{
            template:‘#templ‘,
            props:[‘username‘,‘age‘]
        }
    }
});

我们已经通过props属性进行向下传递数据了,父组件中我们把name属性设置为双向绑定的属性,以便于修改。
接下来直接在文本框中修改name的值,子组件模板中,值就跟着变了。

那么,我们开始尝试着修改它。
示例:

//在组件模板中添加如下按钮。注意模板中只有一个根元素,需要div包起来
<button @click="change">直接修改父组件传递下来的值</button>

//在子组件中定义方法,注意不要写错位置,会发生错误的
methods:{
    change(){
        this.username=‘I Love You‘;//直接修改它的值
    }
}

运行结果,浏览器控制台发生异常了。

Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop‘s value. Prop being mutated: "username"

由此可见,它是不可以更改的,因为它是自动更新值的。

如果你很需要在子组件中修改它的话

当然如果非要这么做的话,也还是有方法的,因为你很有必要用它。

  • 你可能希望把它当做局部变量处理
  • 你可能需要得到它的值显示出来,并修改它

那么你有两种选择,

  • 一种是定义局部变量,来操作它。
  • 另一种就是定义计算属性,依据原值的修改来动态的改变这个计算属性,而你使用的就是这个计算属性

接下来我们只需要这样:

//1.添加属性,并将传来的属性复制给新的局部定义属性
data:function(){
    return {
        myName:this.username
    }
}
//2.接下来要改变和使用的值就都是myName了
methods:{
    change(){
        this.myName=‘I Love you‘
    }
}
//模板中
<p>子组件中父组件的数据,{{myName}}</p>

对于使用计算属性,我们可以做:

props: [‘size‘],
computed: {
  normalizedSize: function () {
    return this.size.trim().toLowerCase()
  }
}
//接下来就是使用normalizedSize属性显示了

以上是单项数据流的问题,如果需要双向呢,看下面。


双向数据流,父子双向绑定

我们使用.sync修饰符,该修饰符在1.0中使用,在2.0中废除,后又在2.3中重新引用,只是错了稍加修改,具体情况看官网。

//父组件向下传递时,子组件标签上传递的属性后面添加.sync修饰符
<my-component :username.sync="name" :age="age"></my-component>

然后需要显式的触发一个更新事件。

methods:{
    change(){
        this.$emit(‘update:username‘, ‘I Love You‘);
        //this.username=‘I Love you‘;
    }
}

通过$emit事件方法,然后第一个参数,update:是固定写法,后面是新属性值,这样就可以双向绑定了。使用按钮触发不是必需的,只要在某处调用这个触发方法即可。

假如你向下传递的是对象,那么如果要修改的话会更方便。

我们可以直接修改对象的属性值而不需要.sync修饰符。

//为父组件定义一个对象,并且显示他
emp:{salary:6000,workingAge:2,name:‘XiaoChenchen‘}
<p>父组件emp:{{emp}}</p>

//在单击按钮方法中直接设置对象的属性值
this.emp.salary=8000;

单击按钮,发现salarys从6000变成了8000,而且不会不会发生任何错误。
这是因为对象的引用地址没有发生改变,改变的只是里面的属性,属性改变并不会影响对象地址。

所以我们建议封装成对象更方便,但有时也是需要到.sync修饰符的,主要是看情况了。

谢谢观看,下节继续讲组件,非父子间通信,以及slot插槽分发。



爱自己,更爱需要爱的人。。。

原文地址:http://blog.51cto.com/zouzhelu/2106497

时间: 2024-11-10 15:07:26

Vue2.0笔记——组件2的相关文章

Vue2.0笔记——组件

组件 (Component) 是 Vue.js 最强大的功能之一.组件可以扩展 HTML 元素,封装可重用的代码.组件是自定义元素,Vue.js 的编译器为它添加特殊功能. 使用组件 组件的注册与使用 全局注册 我们需要通过一个全局的API来构造.Vue.extend(options)用法:使用基础 Vue 构造器,创建一个"子类".参数是一个包含组件选项的对象.同时还需要一个API通过这个构造器来注册组件,之后才能使用.Vue.component(id, [definition])用

Vue2.0笔记——Vue实例

Vue实例 每个 Vue 应用都是通过用 Vue 函数创建一个新的 Vue 实例开始的: var vm = new Vue({ // 选项 }) 当创建一个 Vue 实例时,你可以传入一个选项对象,就如前面所提到的如:data,methods,computed,watch等等.一个 Vue 应用由一个通过 new Vue 创建的根 Vue 实例,以及可选的嵌套的.可复用的组件树组成.举个例子,一个 todo 应用的组件树可以是这样的: 根实例Root └─ TodoList ├─ TodoIte

vue2.0 父子组件通信 兄弟组件通信

父组件是通过props属性给子组件通信的来看下代码: 父组件: <parent> <child :child-com="content"></child> //注意这里用驼峰写法哦 </parent> data(){ return { content:'sichaoyun' }; } 子组件通过props来接受数据 第一种方法 props: ['childCom'] 第二种方法 props: { childCom: String //这里

vue2.0父子组件通信的方法

vue2.0组件通信方法:props传值和emit监听.(.sync方法已经移除.详情请点击)(dispatch-和-broadcast方法也已经废弃) props方法传值:Props 现在只能单项传递.为了对父组件产生反向影响,子组件需要显式地传递一个事件而不是依赖于隐式地双向绑定.props方法传值比较简单,缺点是属性会比较多. (1)父传子 [ props传值 ] <template>  <div> <input type="text" v-mode

vue2.0子组件修改父组件props数据的值

从vue1.0升级至2.0之后 prop的.sync被去除 因此直接在子组件修改父组件的值是会报错的如下: 目的是为了阻止子组件影响父组件的数据那么在vue2.0之后 如何在子组件修改父组件props传过来的值呢?思路是通过子组件$emit发射一个方法  如下: this.$emit('imgDataCallback', callbackUrl); 在父组件使用子组件的地方用v-on绑定这个自定义事件 如下: 然后在父组件定义这个方法 //获取imgurl        getImgData:

Vue2.0笔记——{{}}模板与自定义过滤器

模板语法 让我们回到最开始 <div id="app"> <h1>{{message}}</h1> </div> <script> var vm = new Vue({ el:'#app', data:{ message:'HelloWorld' } }) </script> 这是一个HelloWorld,简单的通过模板输出.我们称之为数据绑定,而最常见的就是"Mustache"语法 (双大括号

vue2.0 父子组件 通信

一.父组件传递数据给子组件 (  parent  ==> children  ) props 属性 >parent 组件 parent.vue <parent> <child :child-msg="msg"></child> //这里必须要用 - 代替驼峰 </parent> data(){ return { msg: [1,2,3] }; } >child 组件 child.vue 写法一 props: ['chil

vue2.0全局组件之pdf

目的:像elementUI那样注册全局组件 预览pdf文件 技术支持:使用火狐的pdf.js http://mozilla.github.io/pdf.js/ 准备:新建一个CPdf.vue文件,把火狐demo里面的build里面的pdf.js下载来,并且依赖了elementUI开发的其实就是用了<el-button> 编写: template <template> <div class="cpdf"> <div class="cen

超简单的vue2.0分页组件

1.组件代码 <template> <div class="pagination_comment_style" style="width: 100%;overflow: hidden"> <ul class="pagination"> <li @click="goPage(pageIndex-1)" v-bind:class="{ 'no-allow': 1 == pageI