随笔 - 17,  文章 - 0,  评论 - 0,  阅读 - 2674

子组件传值父组件

子组件调用父组件的方法

1.在父组件中给引用的子组件注册一个事件(这个事件的名字是自定义的)

2.子组件可以触发这个事件$emit('事件名字')

子组件给父组件传递数据

1.$emit方法第二个参数可以定义子组件给父组件传递的内容

2.在父组件中怎么拿到这内容

2.1父组件这个方法没有自定参数,在父组件的方法直接加这个参数就可以拿到

2.2父组件有自定义参数,可以传入$event也可以拿到子组件传递的数据。通过$event只能传递第一个参数。

复制代码
<!DOCTYPE html>
<html>

<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="./vue-2.4.0.js"></script>
    <script src="./axios.js"></script>
</head>

<body>
    <div id='app'>
        <father></father>
    </div>

    <template id="father">
        <div>
            <!-- 子组件调用父组件的方法
1.    在父组件中给引用的子组件注册一个事件(这个事件的名字是自定义的)
2.    子组件可以触发这个事件$emit('事件名字',传递数据) -->


             father
             <br>
             子传父:{{fromsondata}}
             <br>
            <son @myson="fromson"></son>
        </div>
    </template>

    <template id="son">
        <div>
            son
            <button @click="tofather"> 点我传参</button>
        </div>
    </template>


    <script>
        Vue.component("father", {
            template: "#father",
            data() {
                return {
                    msg: 'hello',
                    fromsondata: ""
                }
            },
            methods: {
                // data就是子组件传的值
                fromson(data) {
                    console.log(data);
                    this.fromsondata = data

                }
            }

        })
        Vue.component("son", {
            template: "#son",
            data() {
                return {

                }
            },

            created() {
                // 触发子传父  this.$emit( ‘自定义事件’,传递参数)
                // this.$emit('myson','这是来自子组件的参数')
            },
            methods: {
                tofather() {
                    // 子传父
                    this.$emit('myson', '这是来自子组件的参数')
                }
            },
        })


        const vm = new Vue({
            el: '#app',
            data: {},
            methods: {},
        })
    </script>
</body>

</html>
复制代码

使用组件写评论列表案例

将评论发表做成一个组件,发表后保存到localStorage

1.获取用户输入的值

2.构造一个对象

3..把数据存起来(localStorage)

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

  3.2 把数据添加进去

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

子组件更新后父组件同步更新

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

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

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

复制代码
<!DOCTYPE html>
<html>

<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>
    <link rel="stylesheet" href="./bootstrap-3.4.1-dist/css/bootstrap.min.css">
    <script src="./vue-2.4.0.js"></script>
</head>

<body>
    <div id='app'>

        <div class="container">

            <son @getlist="fromson"></son>


            <ul class="list-group">
                <li class="list-group-item" v-for="(item,index) in list" :key="index">
                    {{item.comment}}
                    <span class="badge">评论人:{{item.name}}--{{item.ctime}}</span>
                </li>

            </ul>

        </div>



    </div>


    <template id="son">
<div>
    <div class="panel panel-info">
        <div class="panel-heading">
            <h3 class="panel-title">留言板</h3>
        </div>
        <div class="panel-body">

            <form action="" method="POST" role="form">

                <div class="form-group">
                    <label for="">姓名</label>
                    <input type="text" v-model="name" class="form-control" id="" placeholder="Input field">
                </div>
                <div class="form-group">
                    <label for="">留言</label>
                    <input type="text" v-model="comment" class="form-control" id="" placeholder="Input field">
                </div>


                <button @click.prevent="addComment" class="btn btn-primary">发布评论</button>
            </form>



        </div>
    </div>

</div>
    </template>

    <script>
        Vue.component("son", {
            template: "#son",
            data() {
                return {
                    name: "",
                    comment: ""
                }
            },
            methods: {
                addComment() {
                    this.$emit("getlist", {
                        name: this.name,
                        comment: this.comment,
                        ctime: new Date().toDateString(),
                    })


                }
            },

        })
        const vm = new Vue({
            el: '#app',
            data: {

                list: [],
            },
            methods: {
                fromson(data) {
                    console.log(data.name);
                    console.log(data.comment);
                    console.log(data);
                    if (data.name && data.comment) {

                        this.list.unshift(data)

                        localStorage.setItem("list", JSON.stringify(this.list))
                    }

                }
            },
            created() {
                // this.list = localStorage.list;
                if (localStorage.list) {

                    this.list = JSON.parse(localStorage.list)
                }
                console.log(localStorage);
                /*  if (localStorage.list) {
                     this.list = JSON.parse(localStorage.list).map((item) => {
                         // console.log(item);
                         return {
                             ...item,

                         }
                     })
                 } */
            }
        })
    </script>
</body>

</html>
复制代码

ref的使用

获取dom节点

1.给dom节点记上ref属性,可以理解为给dom节点起了个名字。

2.加上ref之后,在$refs属性中多了这个元素的引用。

3.通过vue实例的$refs属性拿到这个dom元素。

获取组件

4.给组件记上ref属性,可以理解为给组件起了个名字。

5.加上ref之后,在$refs属性中多了这个组件的引用。

6.通过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中路由的使用

什么是路由

1.后端路由:对于普通的网站,所有的超链接都是URL地址,所有的URL地址都对应服务器上对应的资源

2.前端路由:对于单页面应用程序来说,主要通过URL中的hash(#号)来实现不同页面之间的切换,同时,hash有一个特点:HTTP请求中不会包含hash相关的内容;所以,单页面程序中的页面跳转主要用hash实现;

3.在单页面应用程序中,这种通过hash改变来切换页面的方式,称作前端路由(区别于后端路由)

如何使用路由

路由的安装

直接引用官网提供的cdn

 

路由的基本使用

1.引入js文件,这个js需要放在vue的js后面,自动安装(提供了一个VueRouter的构造方法)

2.创建路由new VueRouter(),接受的参数是一个对象

3.在实例化的对象里配置属性routes:[],这个数组里的对象包含path属性和component属性

4.path属性是url的地址,component属性就是显示的组件(传组件的对象)

5.创建的路由需要和vue实例关联一下

6.路由到的组件显示在哪个位置<router-view></router-view>

复制代码
<!DOCTYPE html>
<html>
<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>
    <!-- 1.引入 放在vue后面 -->
    <script src="https://unpkg.com/vue-router@3.0.0/dist/vue-router.js"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
    <div id='app'>
        <!-- 1    引入js文件,这个js需要放在vue的js后面,自动安装(提供了一个VueRouter的构造方法)
2    创建路由new VueRouter(),接受的参数是一个对象
3    在实例化的对象里配置属性routes:[],这个数组里的对象包含path属性和component属性
4    path属性是url的地址,component属性就是显示的组件(传组件的对象)
5    创建的路由需要和vue实例关联一下
6    路由到的组件显示在哪个位置<router-view></router-view> -->

<!-- 5/展示区域 -->
            <router-view></router-view>

    </div>


    <template id="index">
        <div>
            index首页
        </div>
    </template>

    <template id="detail">
        <div>
            详情页
        </div>
    </template>

    <script>

        let index =  {
            template:"#index"
        }
        let detail =  {
            template:"#detail"
        }



        // 2.创建vuerouter实例
         const router = new VueRouter({
            //  3.创建映射关系
            routes:[
                {
                    // 路径
                    path:'/',
                    // 对应组件
                    component:index
                },
                {
                    path:"/detail",
                    component:detail
                }
            ]
            
        })


    const vm = new Vue({
        el: '#app',
        data: {
        },
        methods: {
        },
        // 4.将路由挂载在vue实例上
        // router:router,
        router
    })
    </script>
</body>
</html>
复制代码

路由的跳转

1 router-link标签可以设置to属性

2默认是a标签,可以通过tag设置包裹标签

<router-link to='/login'>登录</router-link>
<router-link to='/registry'>注册</router-link>

路由重定向

redirect可以进行路由的重定向

                 {
                    path: '/',
                    redirect: "/index"
                },            

选中路由高亮

1.使用默认的样式

直接设置router-link-active

 .router-link-active {
            font-size: 40px;
            color: hotpink;
        }

2.自定义样式

配置 linkActiveClass:'自定义的类名

复制代码
.myactive {
            font-size: 30px;
            color: yellowgreen;
        }


const router = new VueRouter({
            //自定义路由高亮 
            linkActiveClass: "myactive",
)}
复制代码

定义参数

通过query的方式在url后加?参数名=参数的值

获取参数:$route.query.参数名

复制代码
<!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>
    <!-- 引入这个路由组件之后提供了一个VueRouter的构造方法 -->
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
    <style>
        .router-link-active {
            background-color: aquamarine;
            font-size: 20px;
        }
        .my-active {
            background-color: aquamarine;
            font-size: 20px;
        }
    </style>
</head>

<body>
    <div id="app">
        <!-- 通过路由切换的组件会被放在这里 -->
        <!-- <a href="#/login">登录</a> -->
        <!-- <a href="#/registry">注册</a> -->
        <!-- 通过router-link 进行路由的跳转 -->
        <!-- 通过tag可以指定router-link渲染的界面元素 -->
        <!-- <router-link to='/login' tag='div'>登录</router-link> -->
        <router-link to='/login?id=123&name=张三'>登录</router-link>
        <router-link to='/registry'>注册</router-link>
        <router-link to='/detail?id=999'>某一篇新闻</router-link>
        <router-view></router-view>
    </div>

    <script>
        // 实现简单路由功能的步骤
        // 1. 引入js文件,这个js需要放在vue的js后面,自动安装(提供了一个VueRouter的构造方法)
           // 2. 创建路由new VueRouter(),接受的参数是一个对象
           // 3. 在实例化的对象里配置属性 routes :[],这个数组里的对象包含path属性和component属性
           // 4. path属性是url的地址,component属性就是显示的组件(传组件的对象)
           // 5. 创建的路由需要和vue实例关联一下
           // 6. 路由到的组件显示在哪个位置<router-view></router-view>
        const login = {
            template: '<h2>登录,父组件传递过来的id{{$route.query.id}},name:{{$route.query.name}}</h2>'
        }

        const registry = {
            template: '<h2>注册</h2>'
        }

        const newsDetail = {
            template: '<h2>文章的详情</h2>',
            created() {
                console.log(this.$route.query.id);
                // 根据这个id去请求后台数据,获取完整的新闻内容,之后进行展示
            },
        }

        // 这里实例化了一个路由
        const router = new VueRouter({
            linkActiveClass: 'my-active',
            routes: [{
                path: '/',
                // 通过这种方式,在访问/路径的时候会重定向到/login路径
                redirect: '/login'
            }, {
                path: '/login',
                //这里需要注意的是我们直接组件的对象放在这里
                component: login
            }, {
                path: '/registry',
                component: registry
            }, {
                path: '/detail',
                component: newsDetail
            }]
        });

        var vm = new Vue({
            el: '#app',
            // 把路由挂在到实例上
            router: router
        })
    </script>
</body>
</html>
复制代码

使用浏览器参数的方式传递参数

1.设置路由的时候/路由地址/:参数名

2.获取参数$route.params.参数名

复制代码
<body>
    <div id="app">
        <!-- 通过路由切换的组件会被放在这里 -->
        <!-- <a href="#/login">登录</a> -->
        <!-- <a href="#/registry">注册</a> -->
        <!-- 通过router-link 进行路由的跳转 -->
        <!-- 通过tag可以指定router-link渲染的界面元素 -->
        <!-- <router-link to='/login' tag='div'>登录</router-link> -->
        <router-link to='/login?id=123&name=张三'>登录</router-link>
        <router-link to='/registry'>注册</router-link>
        <router-link to='/detail/1000'>某一篇新闻</router-link>
        <router-view></router-view>
    </div>

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

        const login = {
            template: '<h2>登录,父组件传递过来的id{{$route.query.id}},name:{{$route.query.name}}</h2>'
        }

        const registry = {
            template: '<h2>注册</h2>'
        }

        const newsDetail = {
            template: '<h2>文章的详情</h2>',
            created() {
                console.log(this.$route.params.id);
                // 根据这个id去请求后台数据,获取完整的新闻内容,之后进行展示
            },
        }

        // 这里实例化了一个路由
        const router = new VueRouter({
            linkActiveClass: 'my-active',
            routes: [{
                path: '/',
                // 通过这种方式,在访问/路径的时候会重定向到/login路径
                redirect: '/login'
            }, {
                path: '/login',
                //这里需要注意的是我们直接组件的对象放在这里
                component: login
            }, {
                path: '/registry',
                component: registry
            }, {
                path: '/detail/:id/:name',
                component: newsDetail
            }]
        });

        var vm = new Vue({
            el: '#app',
            // 把路由挂在到实例上
            router: router
        })
    </script>
</body>
复制代码

组件的嵌套

1.声明路由的时候设置children,这是children是一个数组,数组里是路由对象

2.这个children的组件就会渲染在它父组件的<router-view>中

复制代码
<body>
    <!-- 通过这个路由的嵌套,我们可以实现一些布局 -->
    <div id="app">
        <router-view></router-view>
    </div>
    <template id="parentCompTemp">
        <div>
            <h1>登录注册页面</h1>
            <router-link to='/parent/login'>登录</router-link>
            <router-link to='/parent/registry'>注册</router-link>
            <router-view></router-view>
        </div>
    </template>

    <script>
        const parentComp = {
            template: '#parentCompTemp'
        }
        const login = {
            template: '<h2>登录</h2>'
        }

        const registry = {
            template: '<h2>注册</h2>'
        }

        const newsDetail = {
            template: '<h2>文章的详情</h2>',
            created() {
                console.log(this.$route.query.id);
                // 根据这个id去请求后台数据,获取完整的新闻内容,之后进行展示
            },
        }

        // 这里实例化了一个路由
        const router = new VueRouter({
            linkActiveClass: 'my-active',
            routes: [{
                path: '/',
                // 通过这种方式,在访问/路径的时候会重定向到/login路径
                redirect: '/parent'
            }, {
                path: '/parent',
                component: parentComp,
                // 涉及到了子路由的内容
                children: [{
                        // 这就是用相对路径,相对于父组件的,这个实际路径就是/parent/login
                        path: 'login',
                        component: login
                    }, {
                        // 这就是用相对路径,相对于父组件的,这个实际路径就是/parent/login
                        path: 'registry',
                        component: registry
                    },
                ]
            }]
        });

        var vm = new Vue({
            el: '#app',
            // 把路由挂在到实例上
            router: router
        })
    </script>
</body>
复制代码

命名视图

1.我们之前只能一个地址对应一个组件,现在可以一个地址对应多个组件

2.components属性设置的

3.给router-view设置名字,这个名字和components组件名字是对应的

4设置默认值default对应组件可以设置名字也可以访问

复制代码
<!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>
    <!-- 引入这个路由组件之后提供了一个VueRouter的构造方法 -->
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
    <style>
        .router-link-active {
            background-color: aquamarine;
            font-size: 20px;
        }
        .my-active {
            background-color: aquamarine;
            font-size: 20px;
        }
        .header {
            width: 100%;
            height: 80px;
            background-color: red;
        }
        .my-container {
            height: calc(100vh - 80px);
        }
        .sidebar {
            height: 100%;
            float: left;
            width: 200px;
            background-color: gray;
        }
        .main {
            height: 100%;
            margin-left: 200px;
            background-color: khaki;
        }
        body {
            margin: 0
        }
    </style>
</head>

<body>
    <!-- 通过这个路由的嵌套,我们可以实现一些布局 -->
    <div id="app">
        <!-- router-view可以设置名字,指定渲染的组件 -->
        <router-view></router-view>
        <div class='my-container'>
            <router-view name='sidebar'></router-view>
            <router-view name='main'></router-view>
        </div>
    </div>

    <script>
        // 头部
        const header = {
            template: '<div class="header">头部内容</div>'
        }
        // 侧边栏
        const sidebar = {
            template: '<div class="sidebar">侧边栏</div>'
        }
        // 主体
        const main = {
            template: '<div  class="main"> <router-view></router-view>内容</div>'
        }
        const test={
            template: '<div >测试</div>'
        }
        // 这里实例化了一个路由
        const router = new VueRouter({
            linkActiveClass: 'my-active',
            routes: [{
                path: '/',
                // 使用compones可以定义多个组件
                components: {
                // 通过default属性可以设置默认的组件,默认组件只有一个,不写名字也可以渲染
                    default: header,
                    sidebar: sidebar,
                    main
                },
                children:[
                    {path:'/test',component:test}
                ]
            }]
        });
        var vm = new Vue({
            el: '#app',
            // 把路由挂在到实例上
            router: router
        })
    </script>
</body>
复制代码

计算属性和监听器

名称案例

1.获取完整的名字,需要把姓和名字拼接在一起

2.什么时候去拼接在一起(input值改变的时候)

3.监听keyup知道input什么时候改变了,在这里就可以获取完整的名字

复制代码
<!DOCTYPE html>
<html>

<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="./vue-2.4.0.js"></script>
</head>

<body>
    <div id='app'>
        <input type="text" v-model='firstname'>+
        <input type="text" v-model="lastname"> <button @click="getname">=</button>
        <input type="text" v-model="name">
    </div>


    <script>
        const vm = new Vue({
            el: '#app',
            data: {
                firstname: "",
                lastname: "",
                // name: ''
            },
            methods: {
                getname() {
                    this.name = this.firstname + this.lastname
                }
            },
            //属性监听
            // watch: {
            //     "firstname": function (newvalue,oldvalue) {
            //         // console.log(newvalue);
            //         // console.log(oldvalue);
            //         this.name = this.firstname + this.lastname
            //     },
            //     "lastname": function (newvalue,oldvalue) {
            //         this.name = this.firstname + this.lastname
            //     }
            // },
            // 属性计算 不能和data里面数据冲突
            // 计算属性中所依赖的任何一个 data 属性改变之后,都会重新触发 本计算属性 的重新计算,从而更新 fullName 的值
            computed:{
                // name:function(){
                //     return this.firstname + '-' + this.lastname
                // }
                // 2
                name:{
                    get:function(){
                        return this.firstname + '-' + this.lastname
                    },
                    // 只有修改自身时会触发
                    set:function(value){
                        console.log(value);

                       this.firstname =  value.split("-")[0]
                       this.lastname =  value.split("-")[1]
                    }
                }
            }

        })
    </script>
</body>

</html>
复制代码

 

posted on   白夜皇帝  阅读(28)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示