Vue学习总结-组件
组件化和模块化的区别
模块化:从代码逻辑角度划分,方便代码分层开发,保证每个功能模块的职能单一
组件化:从UI界面角度划分
组件-组件的创建方式1
组件-组件的创建方式2
组件-组件的创建方式3
组件-组件中的data
组件切换-使用v-if和v-else结合flag进行切换
组件切换-使用Vue提供的component元素实现组件切换
<template>
<div id="app">
<!-- <img src="./assets/logo.png">-->
<!-- <router-link to="/About">Go to About</router-link>-->
<!-- <router-link to="/helloWorld">Go to HelloWorld</router-link>-->
<a href="" @click.prevent="comNAme='About'">关于</a>
<a href="" @click.prevent="comNAme='HelloWorld'">你好</a>
<component :is="comNAme"> </component>
</div>
</template>
<script>
import About from "./components/About.vue"
import HelloWorld from "./components/HelloWorld.vue";
export default {
components:{
About,
HelloWorld
},
name: 'App',
data:function () {
return{
comNAme:'About',
}
}
}
</script>
组件切换-应用切换动画和mode方式
<template>
<div id="app">
<!-- <img src="./assets/logo.png">-->
<!-- <router-link to="/About">Go to About</router-link>-->
<!-- <router-link to="/helloWorld">Go to HelloWorld</router-link>-->
<a href="" @click.prevent="comNAme='About'">关于</a>
<a href="" @click.prevent="comNAme='HelloWorld'">你好</a>
<!-- 通过mode属性,设置组件切换时候的 模式-->
<transition mode="out-in">
<component :is="comNAme"> </component>
</transition>
</div>
</template>
<script>
import About from "./components/About.vue"
import HelloWorld from "./components/HelloWorld.vue";
export default {
components:{
About,
HelloWorld
},
name: 'App',
data:function () {
return{
comNAme:About,
}
}
}
</script>
<style>
.v-enter,
.v-leave-to{
opacity: 0;
transform: translateX(150px);
}
v-enter-active,
v-leave-active{
transition: all 0.5s ease;
}
</style>
动画-小球动画flag标识符的作用分析
<template>
<div>
<!-- 需求:点击h3显示,再点击h3消失-->
<input type="button" value="加入购物车" @click="flag=!flag">
<!-- <input type="text" :value="msg">-->
<transition
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter">
<div class="ball" v-show="flag"></div>
</transition>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data() {
return {
flag: false,
}
},
methods: {
//注意:动画钩子函数第一个参数:el要执行动画的那个DOM元素,是原生的JS DOM对象
beforeEnter(el) {
//表示动画入场前,此时动画尚未开始,可以在beforeEnter中设置开始动画之前的起始样式
// 设置小球开始动画的起始位置
el.style.transform = 'translate(0px,0px)'
},
enter(el, done) {
//没有实际作用,不写动画效果出不来,可认为会强制动画刷新
el.offsetWidth
// 动画开始之后的样式,可设置小球完成动画后的结束状态
el.style.transform = 'translate(150px, 450px)'
el.style.transition = 'all 1s ease'
//done其实就是afterEnter这个函数,也就是说done是afterEnter的引用
//动画完成后立即消失
done()
},
afterEnter(el) {
// 动画完成后调用
//第一个功能:控制小球的显示与隐藏
//第2个功能:直接跳过后半场动画,让flag=false
//当第二次点击按钮时候,flag false->true
this.flag = !this.flag
// el.style.opacity = 0.5
//vue把一个完整的动画,使用钩子函数拆分为2部分
// 我们使用flag标识符表示动画的切换
// 刚一开始flag=fase,->true ->false
}
}
}
</script>
<style>
.ball {
width: 15px;
height: 15px;
border-radius: 50%;
background-color: #42b983;
}
</style>
组件传值-父组件向子组件传值和data与props的区别
父组件
<template>
<div id="app">
<!-- 父组件,可以在引用子组件的时候,通过属性绑定(v-bind:)形式
把需要传递给子组件的数据,以属性绑定形式传到子组件内部,供子组件使用-->
<HelloWorld v-bind:parentmsg="appmsg"></HelloWorld>
</div>
</template>
<script>
import About from "./components/About.vue"
import HelloWorld from "./components/HelloWorld.vue";
export default {
//包含的子组件如下
components:{
About,
HelloWorld
},
name: 'App',
data:function () {
return{
appmsg:"APP 父组件中的变量",
comNAme:About,
}
}
}
</script>
子组件
<template>
<!-- 子组件中,默认无法访问到父组件中的data上的数据和methods中的方法-->
<div>
<h3>{{parentmsg}}</h3>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
//注意:组件中所有props中的数据,都是通过父组件传递给子组件的
//把父组件传递过来的parentmsg属性,西安在props数组中定义一下,这样才能使用该数据
//props只读的,data中数据可读可写
props:['parentmsg'],
data() {//这些子组件中的data数据,是子组件私有的,通过Ajax请求回来的数据,都可以放到data上
return {
}
},
methods: {
}
}
</script>
<style>
</style>
组件传值-子组件通过事件调用向父组件传值
父组件
<template>
<div id="app">
<!-- <img src="./assets/logo.png">-->
<!-- <router-link to="/About">Go to About</router-link>-->
<!-- <router-link to="/helloWorld">Go to HelloWorld</router-link>-->
<!-- <router-view></router-view>-->
<!-- 父组件,可以在引用子组件的时候,通过属性绑定(v-bind:)形式
把需要传递给子组件的数据,以属性绑定形式传到子组件内部,供子组件使用-->
<!-- 父组件向子组件传递方法,使用事件绑定机制:v-on-->
<HelloWorld v-bind:parentmsg="appmsg" @func="show"></HelloWorld>
<!-- <a href="" @click.prevent="comNAme='About'">关于</a>-->
<!-- <a href="" @click.prevent="comNAme='HelloWorld'">你好</a>-->
<!--<!– 通过mode属性,设置组件切换时候的 模式–>-->
<!-- <transition mode="out-in">-->
<!-- <component :is="comNAme"> </component>-->
<!-- </transition>-->
</div>
</template>
<script>
import About from "./components/About.vue"
import HelloWorld from "./components/HelloWorld.vue";
export default {
//包含的子组件如下
components:{
About,
HelloWorld
},
name: 'App',
data:function () {
return{
appmsg:"APP 父组件中的变量",
comNAme:About,
dataformson:null
}
},
methods:{
show(data1){
console.log('调用了父组件身上的show方法:---'+data1)
this.dataformson = data1
}
}
}
</script>
<style scoped>
</style>
子组件
<template>
<!-- 子组件中,默认无法访问到父组件中的data上的数据和methods中的方法-->
<div>
<h1>这是子组件</h1>
<h3>{{parentmsg}}</h3>
<input type="button" value="这是子组件的按钮,点击触发父组件传过来的fun方法" @click="myclick">
</div>
</template>
<script>
export default {
name: 'HelloWorld',
//注意:组件中所有props中的数据,都是通过父组件传递给子组件的
//把父组件传递过来的parentmsg属性,西安在props数组中定义一下,这样才能使用该数据
//props只读的,data中数据可读可写
props: ['parentmsg'],
data() {//这些子组件中的data数据,是子组件私有的,通过Ajax请求回来的数据,都可以放到data上
return {
sonmsg:{name:'小头儿子',age:4}
}
},
methods: {
myclick() {
// 当碘酒子组件按钮时,如何拿到父组件传递过来的方法,拿到并调用
// emit:触发,调用,发射的意思
this.$emit('func', this.sonmsg)
}
}
}
</script>
<style>
</style>
组件案例-发表评论功能的实现,自动刷新列表
效果图
父组件
<template>
<div id="app">
<HelloWorld @func="loadComments"></HelloWorld>
<ul class="list-group">
<li class="list-group-item" v-for="(item,i) in list" :key="i">
<span class="badge">评论人:{{item.user}}-----</span>
{{item.content}}
</li>
</ul>
</div>
</template>
<script>
import About from "./components/About.vue"
import HelloWorld from "./components/HelloWorld.vue";
export default {
//包含的子组件如下
components:{
About,
HelloWorld
},
name: 'App',
data:function () {
return{
list:[
{id:Date.now(),user:'李白',content:'天生我才必有用'},
{id:Date.now(),user:'江白',content:'你好你hi你hii'},
{id:Date.now(),user:'双方都',content:'撒地方东风风光'}
]
}
},
beforeCreate(){
//这里不能调用loadComments方法,因为在执行这个钩子函数时候,因为data和methods还没初始化完成
},
created(){
this.loadComments()
},
methods:{
loadComments() {
var list = JSON.parse(localStorage.getItem('cmts') || '[]')
this.list = list
}
}
}
</script>
<style scoped>
</style>
子组件
<template>
<!-- 子组件中,默认无法访问到父组件中的data上的数据和methods中的方法-->
<div>
<div class="form-group">
<label>评论人:</label>
<input type="text" class="form-control" v-model="user">
</div>
<div class="form-group">
<label>评论内容:</label>
<textarea class="form-control" v-model="content"></textarea>
</div>
<div class="form-group">
<label></label>
<input type="button" value="发表评论" class="btn btn-primary" @click="postComment">
</div>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data() {
return {
user: '',
content: '',
}
},
methods: {
postComment() {
//1评论数据存放到了localStroage中,localStroage.setItem('cmts','')
// 2先组织出一个最新的评论数据对象
// 3想办法把第二步中得到的对象保存到localStroage
// 3.1localStroage只支持存放字符串数据,要先调用JSON.stringify
// 3.2在保存最新的评论数据之前,
// 要先从localStroage获取到之前的评论数据,转换为一个数组对象,然后把最新的评论push到这个数组
// 3.3如果获取到的localStroage中的字符串为空,则返回'[]',让JSON.parse转换
// 3.4把最新的评论列表数组,再次调用JSON.stringify转为数组字符串,然后调用localStroage.setItem
var comment ={id:Date.now(),user:this.user,content:this.content}
//localStorage从获取所有评论
var list = JSON.parse(localStorage.getItem('cmts')|| '[]')
list.unshift(comment)
//保存最新的评论
localStorage.setItem('cmts',JSON.stringify(list))
this.user=''
this.content=''
this.$emit('func')
}
}
}
</script>
<style>
</style>
使用ref获取DOM元素和组件引用
效果
父组件
<template>
<div id="app">
<input type="button" value="获取元素" @click="getElement" ref="mybtn">
<h3 id="myh3" ref="myh3">哈哈哈哈胜多负少的</h3>
<hr>
<HelloWorld ref="myLogin"></HelloWorld>
</div>
</template>
<script>
import About from "./components/About.vue"
import HelloWorld from "./components/HelloWorld.vue";
export default {
//包含的子组件如下
components:{
About,
HelloWorld
},
name: 'App',
data:function () {
return {
}
},
methods:{
getElement(){
// console.log(document.getElementById('myh3').innerText)
console.log(this.$refs.myh3.innerText)
console.log(this.$refs.myLogin.msg)
this.$refs.myLogin.show()
}
}
}
</script>
<style scoped>
</style>
子组件
<template>
<div>
<h1>登录组件</h1>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data() {
return {
msg:'son msg'
}
},
methods: {
show(){
console.log('调用了子组件')
}
}
}
</script>
<style>
</style>