vue第五天
1、子组件传值父组件
子组件调用父组件的方法
1.在父组件中给引用的子组件注册一个事件(这个事件的名字是自定义的)
2.子组件可以触发这个事件$emit('事件名字')
子组件给父组件传递数据
1.$emit方法第二个参数可以定义子组件给父组件传递的内容
2.在父组件中怎么拿到这内容
3.父组件这个方法没有自定参数,在父组件的方法直接加这个参数就可以拿到
4.父组件有自定义参数,可以传入$event也可以拿到子组件传递的数据。通过$event只能传递第一个参数。
<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>
2.ref的使用
获取dom节点
1.给dom节点记上ref属性,可以理解为给dom节点起了个名字。
2.加上ref之后,在$refs属性中多了这个元素的引用。
3.通过vue实例的$refs属性拿到这个dom元素。
获取组件
1.给组件记上ref属性,可以理解为给组件起了个名字。
2.加上ref之后,在$refs属性中多了这个组件的引用。
3.通过vue实例的$refs属性拿到这个组件的引用,之后可以通过这个引用调用子组件的方法,或者获取子组件的数据。
<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>
3.Vue中路由的使用
什么是路由
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>
<body>
<div id="app">
<!-- 通过路由切换的组件会被放在这里 -->
<router-view></router-view>
</div>
<script>
const login = {
template: '<h2>登录</h2>'
}
// 这里实例化了一个路由
const router = new VueRouter({
routes: [{
path: '/login',
//这里需要注意的是我们直接组件的对象放在这里
component: login
}]
});
var vm = new Vue({
el: '#app',
// 把路由挂在到实例上
router: router
})
</script>
</body>
路由的跳转
1.router-link标签可以设置to属性
2.默认是a标签,可以通过tag设置包裹标签
<router-link to='/login'>登录</router-link> <router-link to='/registry'>注册</router-link>
路由重定向
redirect可以进行路由的重定向
定义参数
通过query的方式在url后加?参数名=参数的值
获取参数:$route.query.参数名
<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>
使用浏览器参数的方式传递参数
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对应组件可以设置名字也可以访问
<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>
4.计算属性和监听器
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>
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>
method、computed和watch的区别
computed属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算。主要当作属性来使用,使用的时候不加();
methods方法表示一个具体的操作,主要书写业务逻辑;
watch一个对象,键是需要观察的表达式,值是对应回调函数。主要用来监听某些特定数据的变化,从而进行某些具体的业务逻辑操作;可以看作是computed和methods的结合体
浙公网安备 33010602011771号