一、父组件传值子组件
<!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>
<!-- <script src="https://unpkg.com/axios/dist/axios.min.js"></script> -->
<script src="https://cdn.staticfile.org/axios/0.18.0/axios.min.js"></script>
<style>
ul {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
li {
list-style: none;
width: 18%;
}
li img {
width: 100%;
}
</style>
</head>
<body>
<div id='app'>
<h2>免费课程</h2>
<course :type="type" page-size="10"></course>
<!-- <course type="boutique" size="5"></course> -->
<h2>免费课程</h2>
<course type="boutique"></course>
<h2>免费课程</h2>
<course type="discount"></course>
</div>
<template id="course">
<div>
<ul>
<li v-for="item in courselist">
<img :src="item.coverFileUrl" alt="">
<div>{{item.courseTitle}} </div>
<div> {{item.learningNum}}</div>
<div>免费 </div>
</li>
</ul>
</div>
</template>
<script>
Vue.component('course', {
template: "#course",
data() {
return {
courselist: []
}
},
// 接受传值
props: {
// 自己定义接受
type: String,
size: Number,
// pageSize:Number,
// 定义多个数据类型
// pageSize:[Number,String],
// 设置默认值
pageSize: {
type: [Number, String],
// default:5
default() {
return 5
}
}
},
methods: {
getCourseList(type = 'free', pageSize = 5, pageNum = 1) {
let formurl = new URLSearchParams()
formurl.append('type', type)
formurl.append('pageSize', pageSize)
formurl.append('pageNum', pageNum)
return axios.post('http://1.117.81.216:8086/weChat/applet/course/list/type', formurl)
}
},
created() {
console.log(this.pageSize);
this.getCourseList(this.type, this.pageSize, 1).then(res => {
this.courselist = res.data.rows
})
},
})
const vm = new Vue({
el: '#app',
data: {
type: 'free'
},
methods: {
},
beforeCreate() { },
created() { },
beforeMount() { },
mounted() { },
beforeUpdate() { },
updated() { },
beforeDestroy() { },
destroyed() { },
})
</script>
</body>
</html>
二、子组件传值父组件
1、子组件调用父组件的方法
(1)在父组件中给引用的子组件注册一个事件(这个事件的名字是自定义的)
(2)子组件可以触发这个事件$emit('事件名字') 在子组件方法中: this.$emit()
2、子组件给父组件传递数据
(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="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<link rel="stylesheet" href="./lib/bootstrap-3.3.7.css">
</head>
<body>
<div id='app'>
<div class="container">
<son @get="get"></son>
<ul class="list-group">
<li class="list-group-item" v-for="(item,index) in list" :key="index">{{item.content}}<span class="badge">评论人:{{item.name}}</span></li>
</ul>
</div>
</div>
<template id="son">
<div>
<div class="form-group">
<label class="" for="">姓名:</label>
<input type="text" v-model="name" class="form-control" id="" placeholder="Input field">
</div>
<div class="form-group">
<label class="" for="">品论内容:</label>
<input type="text" v-model="content" class="form-control" id="" placeholder="Input field">
</div>
<button type="submit" class="btn btn-primary" @click="btn">发布评论</button>
</div>
</template>
<script>
Vue.component('son', {
template: '#son',
data() {
return {
name: '',
content: "",
}
},
methods: {
btn() {
if (!this.name == '' && !this.content == '') {
this.$emit('get', { name: this.name, content: this.content })
this.name = ''
this.content = ''
} else {
alert('请输入名字或评价内容!')
}
}
}
})
const vm = new Vue({
el: '#app',
data: {
list: []
},
methods: {
get(data) {
console.log(data);
this.list.push(data)
if (localStorage.length == 0) {
localStorage.setItem('list', JSON.stringify(this.list))
} else {
this.list = JSON.parse(localStorage.getItem('list'));
localStorage.setItem('list', JSON.stringify(this.list));
}
console.log(this.list);
}
},
beforeCreate() { },
created() { },
beforeMount() { },
mounted() {
if (localStorage.getItem('list')) {
this.list = JSON.parse(localStorage.getItem('list'));
}
},
beforeUpdate() { },
updated() { },
beforeDestroy() { },
destroyed() { },
})
</script>
</body>
</html>
三、ref的使用
1、获取dom节点
(1).给dom节点记上ref属性,可以理解为给dom节点起了个名字。
<div ref="good">今天一点也没有学会啊</div>
<son ref="myson"></son>
(2).加上ref之后,在$refs属性中多了这个元素的引用。
(3).通过vue实例的$refs属性拿到这个dom元素。
2、获取组件
(4).给组件记上ref属性,可以理解为给组件起了个名字。
(5).加上ref之后,在$refs属性中多了这个组件的引用。
(6).通过vue实例的$refs属性拿到这个组件的引用,之后可以通过这个引用调用子组件的方法,或者获取子组件的数据。
<!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>
</head>
<body>
<div id='app'>
<div ref="good">今天一点也没有学会啊</div>
<son ref="myson"></son>
<button @click="btn">点击我</button>
</div>
<template id="son">
<div>
son-->{{msg}}
</div>
</template>
<script>
Vue.component('son',{
template:'#son',
data(){
return{
msg:'快速加入'
}
}
})
const vm = new Vue({
el: '#app',
data: {
},
methods: {
btn(){
this.$refs.myson.msg = '加入中.....'
}
},
beforeCreate(){},
created(){},
beforeMount(){},
mounted(){
console.log(this.$refs.good);
this.$refs
},
beforeUpdate(){},
updated(){},
beforeDestroy(){},
destroyed(){},
})
</script>
</body>
</html>
四、Vue中路由的使用
1、什么是路由:
后端路由:对于普通的网站,所有的超链接都是URL地址,所有的URL地址都对应服务器上对应的资源
前端路由:对于单页面应用程序来说,主要通过URL中的hash(#号)来实现不同页面之间的切换,同时,hash有一个特点:HTTP请求中不会包含hash相关的内容;所以,单页面程序中的页面跳转主要用hash实现;
区别:在单页面应用程序中,这种通过hash改变来切换页面的方式,称作前端路由
2、路由的基本使用
(1)引入js文件,这个js需要放在vue的js后面,自动安装(提供了一个VueRouter的构造方法)
(2)创建路由new VueRouter(),接受的参数是一个对象 route[](创建路由实例对象)
(3)在实例化的对象里配置属性routes:[],这个数组里的对象包含path属性和component属性(创建映射关系)
(4)path属性是url的地址,component属性就是显示的组件(传组件的对象)(将路由挂载在vue上)
(5)创建的路由需要和vue实例关联一下
(6)路由到的组件显示在哪个位置<router-view></router-view>
路由重定位:redirect可以进行路由的重定向 { path:'/',redirect:'/index'}
路由的跳转
(1)、router-link标签可以设置to属性 <router-link to="/detail">去第二页</router-link>
常用:<router-link :to="{path:'/detail',query:{id:103,name:'zs'}}">去详情 </router-link>
(2)、默认是a标签,可以通过tag设置包裹标签
选中路由高亮
(1).使用默认的样式(官方规定) 直接设置.router-link-active 在style中设置
(2).自定义样式 配置 linkActiveClass:'自定义的类名' 写在 创建映射关系下面 linkActiveClass:'myactive' .myactive 写在style中
通过query的方式在url后加?参数名=参数的值(query传参 ?后可写可不写) 例:<router-link to="/detail?id=105&name=zs">去第二页111</router-link>
使用浏览器参数的方式传递参数(params传参 params后面必须写)
五、组件的嵌套
1.声明路由的时候设置children,这是children是一个数组,数组里是路由对象(写在映射对象下面)children:[ { path:'play', component:play, }, { path:'course', component:course, } ] (地址不可以加/ 加/成为同一级的了)
2.这个children的组件就会渲染在它父组件的<router-view>中 (写在父组件的template中,使用to可以跳转到该子页面)
六、命名视图
1.我们之前只能一个地址对应一个组件,现在可以一个地址对应多个组件
2.components属性设置的
3.给router-view设置名字,这个名字和components组件名字是对应的
4.设置默认值default对应组件可以设置名字也可以访问
七、计算属性和监听
1.watch:和methods平级 在同一级 watch:{ value1:function(){this.value3 = this.value1 + '-' + this.value2 }, value2:function(){ this.value3 = this.value1 + '-' + this.value2 },},
2.computed : 与methods同一级 属性不能和daya中相同
computed: {
value3(){
return this.value1 + '-' + this.value2
}
}
computed: {
value3: {
get: function () {
return this.value1 + '-' + this.value2
},
// 只有当自身发生改变时候才触发
set(value) {
console.log(value);
if (value.split('-' == 2)) {
this.value1 = value.split('-')[0]
this.value2 = value.split('-')[1]
}
},
}
},
3. method、computed和watch的区别
(1).computed属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算。主要当作属性来使用,使用的时候不加();
(2).methods方法表示一个具体的操作,主要书写业务逻辑;
(3).watch一个对象,键是需要观察的表达式,值是对应回调函数。主要用来监听某些特定数据的变化,从而进行某些具体的业务逻辑操作;可以看作是computed和methods的结合体