10天从入门到精通Vue(三)v-if、v-else、父子组件传值

举报
共饮一杯无 发表于 2022/08/20 12:03:42 2022/08/20
【摘要】 使用flag标识符结合v-if和v-else切换组件页面结构:<div id="app"> <input type="button" value="toggle" @click="flag=!flag"> <my-com1 v-if="flag"></my-com1> <my-com2 v-else="flag"></my-com2> </div>Vue实例定义:<script> ...

使用flag标识符结合v-ifv-else切换组件

  1. 页面结构:
<div id="app">
  <input type="button" value="toggle" @click="flag=!flag">
  <my-com1 v-if="flag"></my-com1>
  <my-com2 v-else="flag"></my-com2>
  </div>
  1. Vue实例定义:
<script>
  Vue.component('myCom1', {
    template: '<h3>奔波霸</h3>'
  })
  
  Vue.component('myCom2', {
    template: '<h3>霸波奔</h3>'
  })
  
  // 创建 Vue 实例,得到 ViewModel
  var vm = new Vue({
    el: '#app',
    data: {
      flag: true
    },
    methods: {}
  });
  </script>

使用:is属性来切换不同的子组件,并添加切换动画

  1. 组件实例定义方式:
// 登录组件
const login = Vue.extend({
template: `<div>
  <h3>登录组件</h3>
</div>`
});
Vue.component('login', login);

// 注册组件
const register = Vue.extend({
template: `<div>
  <h3>注册组件</h3>
</div>`
});
Vue.component('register', register);

// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: { comName: 'login' },
methods: {}
    });
  1. 使用component标签,来引用组件,并通过:is属性来指定要加载的组件:
<div id="app">
  <a href="#" @click.prevent="comName='login'">登录</a>
  <a href="#" @click.prevent="comName='register'">注册</a>
  <hr>
  <transition mode="out-in">
    <component :is="comName"></component>
  </transition>
  </div>
  1. 添加切换样式:
<style>
  .v-enter,
  .v-leave-to {
    opacity: 0;
    transform: translateX(30px);
  }
  
  .v-enter-active,
  .v-leave-active {
    position: absolute;
    transition: all 0.3s ease;
  }
  
  h3{
    margin: 0;
  }
  </style>

父组件向子组件传值

  1. 组件实例定义方式,注意:一定要使用props属性来定义父组件传递过来的数据
<script>
  // 创建 Vue 实例,得到 ViewModel
  var vm = new Vue({
    el: '#app',
    data: {
      msg: '这是父组件中的消息'
    },
    components: {
      son: {
        template: '<h1>这是子组件 --- {{finfo}}</h1>',
        props: ['finfo']
      }
    }
  });
  </script>
  1. 使用v-bind或简化指令,将数据传递到子组件中:
<div id="app">
  <son :finfo="msg"></son>
  </div>

子组件向父组件传值

  1. 原理:父组件将方法的引用,传递到子组件内部,子组件在内部调用父组件传递过来的方法,同时把要发送给父组件的数据,在调用方法的时候当作参数传递进去;
  2. 父组件将方法的引用传递给子组件,其中,getMsg是父组件中methods中定义的方法名称,func是子组件调用传递过来方法时候的方法名称
<son @func="getMsg"></son>
  1. 子组件内部通过this.$emit('方法名', 要传递的数据)方式,来调用父组件中的方法,同时把数据传递给父组件使用
<div id="app">
  <!-- 引用父组件 -->
  <son @func="getMsg"></son>
  
  <!-- 组件模板定义 -->
  <script type="x-template" id="son">
  <div>
  <input type="button" value="向父组件传值" @click="sendMsg" />
    </div>
  </script>
</div>

<script>
  // 子组件的定义方式
  Vue.component('son', {
    template: '#son', // 组件模板Id
    methods: {
      sendMsg() { // 按钮的点击事件
        this.$emit('func', 'OK'); // 调用父组件传递过来的方法,同时把数据传递出去
      }
    }
  });
  
  // 创建 Vue 实例,得到 ViewModel
  var vm = new Vue({
    el: '#app',
    data: {},
    methods: {
      getMsg(val){ // 子组件中,通过 this.$emit() 实际调用的方法,在此进行定义
        alert(val);
      }
    }
  });
  </script>

评论列表案例

目标:主要练习父子组件之间传值

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="../lib/vue-2.4.0.js"></script>
    <link rel="stylesheet" href="../lib/bootstrap-3.3.7.css">
</head>

<body>
<div id="app">


    <cmt-box @func="loadComments"></cmt-box>


    <ul class="list-group">
        <li class="list-group-item" v-for="item in list" :key="item.id">
            <span class="badge">评论人: {{ item.user }}</span>
            {{ item.content }}
        </li>
    </ul>


</div>


<template id="tmpl">
    <div>

        <div class="form-group">
            <label>评论人:</label>
            <input type="text" class="form-control" v-model="user">
        </div>

        <div class="form-group">
            <label>评论内容:</label>
            <textarea class="form-control" v-model="content"></textarea>
        </div>

        <div class="form-group">
            <input type="button" value="发表评论" class="btn btn-primary" @click="postComment">
        </div>

    </div>
</template>

<script>

    var commentBox = {
        data() {
            return {
                user: '',
                content: ''
            }
        },
        template: '#tmpl',
        methods: {
            postComment() { // 发表评论的方法
                // 分析:发表评论的业务逻辑
                // 1. 评论数据存到哪里去???   存放到了 localStorage 中  localStorage.setItem('cmts', '')
                // 2. 先组织出一个最新的评论数据对象
                // 3. 想办法,把 第二步中,得到的评论对象,保存到 localStorage 中:
                //  3.1 localStorage 只支持存放字符串数据, 要先调用 JSON.stringify
                //  3.2 在保存 最新的 评论数据之前,要先从 localStorage 获取到之前的评论数据(string), 转换为 一个  数组对象, 然后,把最新的评论, push 到这个数组
                //  3.3 如果获取到的 localStorage 中的 评论字符串,为空不存在, 则  可以 返回一个 '[]'  让 JSON.parse 去转换
                //  3.4  把 最新的  评论列表数组,再次调用 JSON.stringify 转为  数组字符串,然后调用 localStorage.setItem()

                var comment = {id: Date.now(), user: this.user, content: this.content}

                // 从 localStorage 中获取所有的评论
                var list = JSON.parse(localStorage.getItem('cmts') || '[]')
                list.unshift(comment)
                // 重新保存最新的 评论数据
                localStorage.setItem('cmts', JSON.stringify(list))

                this.user = this.content = ''

                // this.loadComments() // ?????
                this.$emit('func')
            }
        }
    }

    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
        el: '#app',
        data: {
            list: [
                {id: Date.now(), user: '李白', content: '天生我材必有用'},
                {id: Date.now(), user: '杜甫', content: '劝君更尽一杯酒'},
                {id: Date.now(), user: '鲁迅', content: '嗯,这句话我说过'}
            ]
        },
        beforeCreate() { // 注意:这里不能调用 loadComments 方法,因为在执行这个钩子函数的时候,data 和 methods 都还没有被初始化好

        },
        created() {
            this.loadComments()
        },
        methods: {
            loadComments() { // 从本地的 localStorage 中,加载评论列表
                //var list = JSON.parse(localStorage.getItem('cmts') || '[]')
                this.list = list
            }
        },
        components: {
            'cmt-box': commentBox
        }
    });
</script>
</body>

</html>

效果如下:
image.png

使用 this.$refs 来获取元素和组件

<div id="app">
  <div>
    <input type="button" value="获取元素内容" @click="getElement" />
    <!-- 使用 ref 获取元素 -->
    <h1 ref="myh1">这是一个大大的H1</h1>
    
    <hr>
    <!-- 使用 ref 获取子组件 -->
    <my-com ref="mycom"></my-com>
  </div>
</div>

<script>
  Vue.component('my-com', {
    template: '<h5>这是一个子组件</h5>',
    data() {
      return {
        name: '子组件'
      }
    }
  });
  
  // 创建 Vue 实例,得到 ViewModel
  var vm = new Vue({
    el: '#app',
    data: {},
    methods: {
      getElement() {
        // 通过 this.$refs 来获取元素
        console.log(this.$refs.myh1.innerText);
        // 通过 this.$refs 来获取组件
        console.log(this.$refs.mycom.name);
      }
    }
  });
  </script>
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。