子组件传值父组件
子组件调用父组件的方法
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>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构