从 TodoList 中学父子组件通信

栏目: JavaScript · 发布时间: 5年前

内容简介:实现一个简单的 todolist,当我输入内容后,点击提交自动添加在下面,如下图所示:用代码实现这个效果:

简单的 TodoList

实现一个简单的 todolist,当我输入内容后,点击提交自动添加在下面,如下图所示:

从 TodoList 中学父子组件通信

用代码实现这个效果:

<div id="app">
    <input type="text" v-model="inputVal">
    <button v-on:click="clickBtn">提交</button>
    <ul>
        <li v-for="item in list">{{item}}</li>
    </ul>
</div>
<script>
    let vm = new Vue({
        el:'#app',
        data:{
            list:[],
            inputVal:''
        },
        methods:{
            clickBtn(){
                this.list.push(this.inputVal)
                inputVal = ''
            }
        }
    })
</script>

当我在 input 框中输入内容后,点击提交,Vue 会自动将内容渲染在页面中,具体是怎么实现的呢?

我们都知道 Vue 是一个 MVVM 框架,让开发者专注于数据变更,无需关注 Dom,所以它的核心是 VM 层,也就是说渲染这部分不需要开发者考虑了。

循环 v-for

v-for 指令是 Vue 提供的 api ,可以实现循环添加

v-for="item in list"

list 中数据循环添加到页面中,值为 item

所以当我点击提交时,只需要获取到输入框中的值,然后 pushlist 中,我们看到的效果就是一个个添加。

绑定 v-model

如何获取输入框中的值变成了一个问题,没用 Vue 之前,获取输入框中的值,非常简单,用 $(input).val() 就能轻松获取。

用了 Vue 之后,不应该操作 Dom 来获取值,Vue 肯定也考虑到这点了,提供了一个 api

v-model="inputVal"

第一次用这个指令时,踩了一个坑,我在 inputVal 两边加上了双括号,从而导致页面中没任何反应,这边是不需要加双括号的。渲染模版时才需要用 Vue 提供的模版字符串

一个简单的 TodoList 就已经实现了。

组件化

每个 li 其实都是一个组件,我们可以用组件的形式来开发

全局组件:

<div id="app">
    <input type="text" v-model="inputVal">
    <button v-on:click="clickBtn">提交</button>
    <ul>
        <todo-list v-for="item in list"
                    v-bind:content="index"
        ></todo-list>
    </ul>
</div>
<script>
    Vue.component('TodoLsit',{
        props:['content'],
        template:`<li>{{content}}</li>`,
    })
    let vm = new Vue({
        el: '#app',
        data: {
            list: [],
            inputVal: ''
        },
        methods: {
            clickBtn() {
                this.list.push(this.inputVal)
                this.inputVal = ''
            }
        }
    })
</script>

用 Vue 提供的 component 创建组件可创建一个全局组件,组件的名字 TodoList 在模版中需要用 todo-list 来实现,大小变小写,中间用 - 连接。

局部组件:

<div id="app">
    <input type="text" v-model="inputVal">
    <button v-on:click="clickBtn">提交</button>
    <ul>
        <todo-list v-for="item in list"
                  v-bind:content="item"
        ></todo-list>
    </ul>
</div>
<script>
    let TodoList = {
        props:['content'],
        template: `<li>{{content}}</li>`,
    }
    let vm = new Vue({
        el: '#app',
        data: {
            list: [],
            inputVal: ''
        },
        component:{     //注册组件
          TodoList  
        },
        methods: {
            clickBtn() {
                this.list.push(this.inputVal)
                this.inputVal = ''
            }
        }
    })
</script>

使用局部组件,声明一个对象,内容和全局组件一样,不过需要再 Vue 中注册一下,使用 component 属性注册

component:{
    TodoList
}

用了组件后之后,就会涉及到数据通信,一般有两种:

  1. 组件中如何才能拿到外面的数据
  2. 组件中数据变化,外面如何知道

父 -> 子组件通信

现在已经用组件实现上面的功能了,但是组件中还没有数据,如果将我输入框中的数据传递给子组件。

子组件中获取数据,还是用 v-for 循环,用 v-bind 绑定需要的数据,组件中用 props 获取绑定的数据

<todo-list v-for="(item,index) in list"
           v-bind:content="item"
           v-bind:index="index"
           v-on:delete="handleItemDelete"
></todo-list>

let TodoList = {
    props:['content'],
    template: `<li>{{content}}</li>`,           // content 就是相关数据
}

父 -> 子组件通信实现了往组件里面添加数据,如果子组件中要删除一项,应该怎么操作呢?

子 -> 父组件通信

子 -> 父组件通信,Vue 提供了一个 $emit() 方法,组件中使用 v-on 指令可绑定事件

<div id="app">
    <input type="text" v-model="inputVal">
    <button v-on:click="clickBtn">提交</button>
    <ul>
        <todo-list v-for="(item,index) in list"
                  v-bind:item="item"
                  v-bind:index="index"
                  v-on:delete="handleItemDelete"
        ></todo-list>
    </ul>
</div>
<script>
    Vue.component('TodoList',{
      props:['item', 'index'],
      template: `<li v-on:click="handleItemClick">{{item}}</li>`,
      methods: {
          handleItemClick() {
              this.$emit('delete', this.index)
          }
      }
    })
    let vm = new Vue({
        el: '#app',
        data: {
            list: [],
            inputVal: ''
        },
        methods: {
            clickBtn() {
                this.list.push(this.inputVal)
                this.inputVal = ''
            },
            handleItemDelete(index) {
                this.list.splice(index, 1)
            }
        }
    })
</script>

组件中绑定事件,第一个参数是事件名,第二个参数是要传递给父元素的参数

template: '<li v-on:click="handleItemClick">{{item}}</li>'' //绑定事件为 click,需要执行的函数是 handleItemClick

methods: {                                  //写在组件里面
    handleItemClick() {
        this.$emit('delete', this.index)  
    }
}

父元素监听事件

<todo-list v-for="(item,index) in list"
           v-bind:item="item"
           v-bind:index="index"
           v-on:delete="handleItemDelete"   //监听 delete 事件, 执行函数是 handleItemDelete
></todo-list>

handleItemDelete(index) {                   //写在 Vue 实例中
    this.list.splice(index, 1)
}

通过父子组件之间的通信,就可以实现 父->子 子->父 之间数据传输问题。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

小程序大能量

小程序大能量

肖月 / 人民邮电出版社 / 2018-11 / 49.80元

本书主要针对零基础的读者,详细讲解小程序的搭建以及小程序的运营等知识。全书共有6章。第 1章重点介绍了小程序诞生的原因以及小程序的发展历史;第 2章详细讲解了快速搭建小程序的方法;第3章向读者阐述了小程序和互联网运营的关系;第4章主要介绍了小程序运营的意义;第5章全面分析了打造爆款小程序的策略;第6章重点总结了小程序的营销推广策略。 本书可以作为对小程序感兴趣的个人以及企业的学习用书,帮助读者快速......一起来看看 《小程序大能量》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具