Vue-day05

一、 子组件传值父组件

子组件调用父组件的方法

  1. 在父组件中给引用的子组件注册一个事件(这个事件的名字是自定义的)
  2. 子组件可以触发这个事件$emit('事件名字',传递的参数)
<!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>组件自定义事件</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>

<body>
    <!-- 1.给组件添加事件 -->
    <div id="app">
        <son v-on:click-son='clickParent($event,"自定义参数")' v-on:click-son2='clickParent2'></son>
    </div>

    <template id='sonTemp'>
        <div>
            <button @click='clickSon'>点击事件</button>
            <button @click='clickSon2'>点击事件2</button>
            <h3>这是子组件的内容</h3>
        </div>
    </template>

    <script>
        var son = {
            template: '#sonTemp',
            methods: {
                clickSon() {
                    console.log('子组件的方法');
                    // 2. 在子组件中触发这个事件
                    // 发射,触发
                    // 通过这种方式,子组件也可以给父组件传值
                    this.$emit('click-son', {
                        name: '张三'
                    })
                },
                clickSon2(){
                    console.log('子组件的方法2');
                    this.$emit('click-son2', 'nihao')
                }
            },
        }

        var vm = new Vue({
            el: '#app',
            data: {},
            methods: {
                // e是接受子组件传过来的参数,msg是这个方法自己参数
                clickParent(e, msg) {
                    console.log(e);
                    console.log('父组件的方法,数据为:' + msg);
                },
                clickParent2(e) {
                    console.log(e);
                }
            },
            components: {
                son
            }
        })
    </script>
</body>
</html>

二、 评论列表案例

  1. 将评论发表做成一个组件,发表后保存到localStorage中
  1. 获取用户输入的值
  2. 构造一个对象
  3. 把数据存起来(localStorage)

3.1 首先获取已经保存的数据(localStorage.getItem('key')).

3.2 把数据添加进去

3.3 在把数据保存到localStorage中(localStorage.setItem('key','value'))

  1. 子组件更新后父组件同步更新
  1. 子组件更新数据后,通知父组件

1.1 父组件引用子组件的时候注册一个事件

1.2子组件更新完数据之后调用$emit方法通知父组件

<!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>评论发表</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"
        integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    <style>
        .container {
            padding-top: 30px
        }

        .list {
            margin-top: 30px
        }
    </style>
</head>

<body>
    <div id="app">
        <div class='container'>
            <add-comp @refresh-list='initList'></add-comp>
            <ul class="list-group list">
                <li v-for='item in list' :key='item.id' class="list-group-item">
                    <span class="badge">评论人:{{item.name}}</span>
                    {{item.content}}
                </li>
            </ul>

        </div>
    </div>

    <template id='addTemp'>
        <div>
            <form>
                <legend>表单提交</legend>

                <div class="form-group">
                    <label for="">评论人</label>
                    <input type="text" class="form-control" v-model='name' placeholder="输入评论人">
                </div>

                <div class="form-group">
                    <label for="">评论内容</label>
                    <textarea class='form-control' v-model='content' placeholder="输入评论内容"></textarea>
                </div>

                <button type="submit" class="btn btn-primary" @click.prevent='add'>提交</button>
            </form>
        </div>
    </template>

    <script>
        var addComp = {
            template: '#addTemp',
            data() {
                return {
                    name: '',
                    content: ''
                }
            },
            methods: {
                add() {
                    // 1、获取用户输入的值
                    // 2、构造一个对象
                    // 3、把数据存起来(localStorage)
                    //      3.1 首先获取已经保存的数据
                    //      3.2 把数据添加进去
                    //      3.3 在把数据保存到localStorage中
                    console.log(this.name + this.content);
                    let obj = {
                        id: Date.now(),
                        name: this.name,
                        content: this.content
                    }
                    // 定义一个key,localStorage的key(这个key是我们自定义的)
                    // 假定这个key是commentList
                    // localStorage里存的都是字符串类型
                    // sessionStorage 
                    // 如果localStorage内容为空说明我们没有任何数据,这个时候创建一个新的数组就行了
                   
                    let commentList = JSON.parse(localStorage.getItem('commentList') || '[]');
                    commentList.unshift(obj);
                    // commentList只在这个作用域里生效
                    // 我们需要把它保存到localStorage中,在别的地方也可以使用
                    localStorage.setItem('commentList', JSON.stringify(commentList));

                    // 提醒父组件该更新数据
                    this.$emit('refresh-list')
                }
            },
        }

        var vm = new Vue({
            el: '#app',
            data: {
                list: []
            },
            methods: {
                initList() {
                    this.list = JSON.parse(localStorage.getItem('commentList') || '[]');
                }
            },
            components: {
                addComp
            },
            created() {
                this.initList();
            },
        })
        // 1. 先画了页面
        // 2. 把表单提交抽象成了一个组件
        // 3. 组件定义add方法,把数据保存到localStrorage中
        // 4. 子组件通知父组件修改列表
    </script>
</body>

</html>

三、 ref的使用

  1. 获取dom节点
  1. 给dom节点记上ref属性,可以理解为给dom节点起了个名字。
  2. 加上ref之后,在$refs属性中多了这个元素的引用。
  3. 通过vue实例的$refs属性拿到这个dom元素。

  1. 获取组件
  1. 给组件记上ref属性,可以理解为给组件起了个名字。
  2. 加上ref之后,在$refs属性中多了这个组件的引用。
  3. 通过vue实例的$refs属性拿到这个组件的引用,之后可以通过这个引用调用子组件的方法,或者获取子组件的数据。
<!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>

</head>



<body>

  <div id="app">

    <input type="button" value="获取元素" @click="getElement" ref="mybtn">

    <h3 id="myh3" ref="myh3">哈哈哈, 今天天气太好了!!!</h3>

    <hr>

    <login ref="mylogin"></login>

  </div>

  <script>



    var login = {

      template: '<h1>登录组件</h1>',

      data() {

        return {

          msg: 'son msg'

        }

      },

      methods: {

        show() {

          console.log('调用了子组件的方法')

        }

      }

    }



    // 创建 Vue 实例,得到 ViewModel

    var vm = new Vue({

      el: '#app',

      data: {},

      methods: {

        getElement() {

          // console.log(document.getElementById('myh3').innerText)

          // console.log(this.$refs.myh3.innerText)



          // console.log(this.$refs.mylogin.msg)

          // this.$refs.mylogin.show()

        }

      },

      components: {

        login

      }

    });

  </script>

</body>



</html>

四、 Vue中路由的使用

4.1 什么是路由

  1. 后端路由:对于普通的网站,所有的超链接都是URL地址,所有的URL地址都对应服务器上对应的资源
  2. 前端路由:对于单页面应用程序来说,主要通过URL中的hash(#号)来实现不同页面之间的切换,同时,hash有一个特点:HTTP请求中不会包含hash相关的内容;所以,单页面程序中的页面跳转主要用hash实现;
  3. 在单页面应用程序中,这种通过hash改变来切换页面的方式,称作前端路由(区别于后端路由)

     路由的基本使用

  1. 引入js文件,这个js需要放在vue的js后面,自动安装(提供了一个VueRouter的构造方法)
  2. 创建路由new VueRouter(),接受的参数是一个对象
  3. 在实例化的对象里配置属性routes:[],这个数组里的对象包含path属性和component属性
  4. path属性是url的地址,component属性就是显示的组件(传组件的对象)
  5. 创建的路由需要和vue实例关联一下
  6. 路由到的组件显示在哪个位置<router-view></router-view>

     路由的跳转

  1. router-link标签可以设置to属性
  2. 默认是a标签,可以通过tag设置包裹标签

     路由重定向

     edirect可以进行路由的重定向

     选中路由高亮

  1. 使用默认的样式

直接设置router-link-active

  1. 自定义样式

配置 linkActiveClass:'自定义的类名'

     组件的嵌套

  1. 声明路由的时候设置children,这是children是一个数组,数组里是路由对象
  2. 这个children的组件就会渲染在它父组件的<router-view>中

     命名视图

  1. 我们之前只能一个地址对应一个组件,现在可以一个地址对应多个组件
  2. components属性设置的
  3. 给router-view设置名字,这个名字和components组件名字是对应的
  4. 设置默认值default对应组件可以设置名字也可以访问

计算属性和监听器

名称案例

  1. 获取完整的名字,需要把姓和名字拼接在一起
  2. 什么时候去拼接在一起(input值改变的时候)
  3. 监听keyup知道input什么时候改变了,在这里就可以获取完整的名字

3.1 Method实现

3.2 Watch用法

监听data中属性的改变:

<div id="app">

  <input type="text" v-model="firstName"> +
  <input type="text" v-model="lastName"> =
  <span>{{fullName}}</span>
</div>

<script>
  // 创建 Vue 实例,得到 ViewModel
  var vm = new Vue({
    el: '#app',
    data: {
      firstName: 'jack',
      lastName: 'chen',
      fullName: 'jack - chen'
    },
    methods: {},
    watch: {
      'firstName': function (newVal, oldVal) { // 第一个参数是新数据,第二个参数是旧数据
        this.fullName = newVal + ' - ' + this.lastName;
      },
      'lastName': function (newVal, oldVal) {
        this.fullName = this.firstName + ' - ' + newVal;
      }
    }
  });
</script>

监听路由对象的改变:

<div id="app">

  <router-link to="/login">登录</router-link>
  <router-link to="/register">注册</router-link>

  <router-view></router-view>
</div>
​<script>
  var login = Vue.extend({
    template: '<h1>登录组件</h1>'
  });

  var register = Vue.extend({
    template: '<h1>注册组件</h1>'
  });

  var router = new VueRouter({
    routes: [
      { path: "/login", component: login },
      { path: "/register", component: register }
    ]
  });

  // 创建 Vue 实例,得到 ViewModel
  var vm = new Vue({
    el: '#app',
    data: {},
    methods: {},
    router: router,
    watch: {
      '$route': function (newVal, oldVal) {
        if (newVal.path === '/login') {
          console.log('这是登录组件');
        }
      }
    }
  });
</script>

3.3 Computed用法

默认只有getter的计算属性:

<div id="app">

  <input type="text" v-model="firstName"> +
  <input type="text" v-model="lastName"> =
  <span>{{fullName}}</span>
</div>

<script>
  // 创建 Vue 实例,得到 ViewModel
  var vm = new Vue({
    el: '#app',
    data: {
      firstName: 'jack',
      lastName: 'chen'
    },
    methods: {},
    computed: { // 计算属性; 特点:当计算属性中所以来的任何一个 data 属性改变之后,都会重新触发 本计算属性 的重新计算,从而更新 fullName 的值
      fullName() {
        return this.firstName + ' - ' + this.lastName;
      }
    }
  });
</script>

定义有getter和setter的计算属性:

<div id="app">

  <input type="text" v-model="firstName">
  <input type="text" v-model="lastName">
  <!-- 点击按钮重新为 计算属性 fullName 赋值 -->
  <input type="button" value="修改fullName" @click="changeName">

  <span>{{fullName}}</span>
</div>

<script>
  // 创建 Vue 实例,得到 ViewModel
  var vm = new Vue({
    el: '#app',
    data: {
      firstName: 'jack',
      lastName: 'chen'
    },
    methods: {
      changeName() {
        this.fullName = 'TOM - chen2';
      }
    },
    computed: {
      fullName: {
        get: function () {
          return this.firstName + ' - ' + this.lastName;
        },
        set: function (newVal) {
          var parts = newVal.split(' - ');
          this.firstName = parts[0];
          this.lastName = parts[1];
        }
      }
    }
  });
</script>

3.4 method、computed和watch的区别

  1. computed属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算。主要当作属性来使用,使用的时候不加();
  2. methods方法表示一个具体的操作,主要书写业务逻辑;
  3. watch一个对象,键是需要观察的表达式,值是对应回调函数。主要用来监听某些特定数据的变化,从而进行某些具体的业务逻辑操作;可以看作是computedmethods的结合体
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值