Vue学习
文章目录
- Vue学习
- 一、scoped解决样式冲突
- 二、data必须是一个函数
- 三、组件通信
- 3.1、组件关系
- 3.2、组件通信解决方案
- 3.3、父传子通信
- 3.4、子传父通信
- 3.5、组件通信案例
- 四、prop语法
- 4.1、prop语法基础语法
- 4.2、 <font color = blue>prop校验
- 4.3、prop&data、单向数据流
一、scoped解决样式冲突
写在组件中的样式会 全局生效 → 因此很容易造成多个组件之间的样式冲突问题。
-
全局样式: 默认组件中的样式会作用到全局,任何一个组件中都会受到此样式的影响
-
局部样式: 可以给组件加上scoped 属性,可以 让样式只作用于当前组件
scoped原理:
- 给当前组件模版的所有元素,都会被添加上一个自定义属性 data-v-hash值 (如:data-v-5f6a9d56)
- css选择器后面,被自动处理。添加上了[data-v-hash值]的属性选择器(如:div[data-v-5f6a9d56])
最终效果:必须是当前组件的元素,才会有这个自定义属性,才会被这个样式作用到。
如图:
二、data必须是一个函数
一个组件的 data 选项必须是一个函数。目的是为了:保证每个组件实例,维护独立的一份数据对象。
每次创建新的组件实例,都会新执行一次data 函数,得到一个新对象。
BaseCount.vue
<template><div class="baseCount"><button v-on:click="count--" v-show="count >0">-</button><span>{{count}}</span><button @click="count++">+</button></div>
</template><script>
export default {//data()函数与data:达成的效果一样//data必须是一个函数 --->保证每个组件实例,维护独立的一个数据对象data(){console.log("1111")return {count:999}}
}
</script>
<style>
</style>
App.vue
<template><div class="app"><BaseCount></BaseCount><BaseCount></BaseCount><BaseCount></BaseCount></div>
</template><script>//导入相关组件import BaseCount from './components/BaseCount.vue'
export default {name: 'app',components: {BaseCount : BaseCount}
}
</script><style></style>
效果
三、组件通信
组件通信:就是指组件与组件之间的数据传递
- 组件中的数据是独立的,无法直接访问其它组件的数据
- 想用其他组件的数据-------组件通信
3.1、组件关系
3.2、组件通信解决方案
3.3、父传子通信
- 父组件通过props将数据传递给子组件
- 子组件利用$emit通知父组件修改更新
通信步骤:
- 在父组件中,给组件标签,添加属性方式,传值
- 在子组件通过props进行接收
- 在子组件中渲染使用
App.vue
<template><div class="app">myData: {{myData}}<!-- 父传子组件通信 --><!-- 1.给组件标签,添加属性方式,传指 --><BaseSon v-bind:title="myData"></BaseSon></div>
</template><script>//导入子组件
import BaseSon from './components/BaseSon.vue'
export default {name: 'app',components: {BaseSon : BaseSon},data(){return {myData : 'radan学习Vue知识'}}
}
</script><style scoped>
</style>
BaseSon.vue
<template><div class="son" ><!-- 3.在子组件中渲染使用 -->{{title}}</div>
</template><script>
export default {// 2.通过props进行接受props:['title']}
</script><style scoped>div{border: 3px solid pink;margin: 10px;width: 260px;height: 60px;}
</style>
测试
3.4、子传父通信
通信步骤:
- 通过$emit,向父组件发生消息通知(需要在方法中编写)
- 父组件要对子组件发送的消息进行监听
- 父组件提供处理函数
App.vue
<template><div class="app">myData: {{myData}}<!-- 2. 父组件要对子组件发送的消息进行监听 --><BaseSon v-bind:title="myData" @changeTitle="handleChange"></BaseSon></div>
</template><script>import BaseSon from './components/BaseSon.vue'
export default {name: 'app',components: {BaseSon : BaseSon},data(){return {myData : 'radan学习Vue知识'}},methods:{// 3. 提供处理函数handleChange(newTitle){// alert(newTitle)this.myData=newTitle}}
}
</script><style scoped>
</style>
BaseSon.vue
<template><div class="son" >我是Son组件<button @click="changeFn()">修改父组件中的数据</button></div>
</template><script>
export default {props:['title'],methods:{changeFn(){// alert("你好")// 1. 通过$emit,向父组件发生消息通知this.$emit('changeTitle','randa不想学习')}}}
</script><style scoped>div{border: 3px solid pink;margin: 10px;width: 260px;height: 60px;}
</style>
测试
3.5、组件通信案例
小黑记事本--------------组件版
需求说明:
App.vue
<template><!-- 主体区域 --><section id="app"><TodoHeader @addProject="addProject" ></TodoHeader><!-- 将list中的数据提供给todoMain组件 --><TodoMain :list="list" @changeDel="changeDel" ></TodoMain><TodoFooter :list="list" @delAll="delAll" v-show=" list.length>0"></TodoFooter></section>
</template><script>
import TodoFooter from './components/TodoFooter.vue'
import TodoHeader from './components/TodoHeader.vue'
import TodoMain from './components/TodoMain.vue'
//A:渲染功能:// 1. 提供数据-->提供在公共的父组件中// 2. 通过父传子,将数据传递给其他组件// 3. 利用 v-for 渲染 /*** B:添加功能* 1.收集表单数据 --> v-model* 2.监听事件(回车+点击 都要进行添加)* 3.子传父将任务名称传递给父组件* 4.进行添加 unshift(自己的数据自己负责)*//*** C:删除功能* 1.监听事件(监听删除的点击)携带id* 2.子传父,将删除的id传递给父组件App.vue* 3.进行删除 filter(自己的数据自己负责)*//*** D:footer功能* 1.底部合计:父传子list--->渲染* 2.清空功能:子传父,父修改* 3.持久化存储:watch深度监视list的变化-->往本地存储 --->进入页面优先读取本地信息*/
export default {components:{TodoFooter:TodoFooter,TodoHeader:TodoHeader,TodoMain:TodoMain},data(){return {//优先读取本地信息list:JSON.parse(localStorage.getItem('list')) || [{id:1,name: '打篮球'},{id:2,name: '打羽毛球'},{id:3,name: '看电影'}]}},methods:{changeDel(id){//按照id删除数组中的元素this.list = this.list.filter(item => (item.id != id))},addProject(value){//向数组添加一个元素this.list.unshift({id : +new Date(),name : value})},delAll(){//清空数组中的所有元素this.list=[]// alert(this.list)}},watch:{list:{deep: true,handler(newValue){localStorage.setItem('list',JSON.stringify(newValue))}}}}
</script><style></style>
ToDoHeader.vue
<template><!-- 输入框 --><header class="header"><h1>小黑记事本</h1><input placeholder="请输入任务" class="new-todo" v-model="inputInfo" /><button class="add" @click="addProject">添加任务</button></header>
</template><script>
export default {data(){return{inputInfo: '' //和表单的输入框进行数据绑定}},methods:{addProject(){if(this.inputInfo.trim() === ''){alert("添加的元素不能为空")return}else{this.$emit('addProject',this.inputInfo)this.inputInfo=''}}}
}
</script><style></style>
ToDOMain.vue
<template><!-- 列表区域 --><section class="main"><ul class="todo-list" v-for="(item,index) in list" :key="item.id"><li class="todo"><div class="view"><span class="index">{{index +1 }}</span> <label>{{item.name}}</label><button @click="del(item.id)" class="destroy"></button></div></li></ul></section>
</template><script>
export default {props:{list:Array},methods:{del(value){// console.log(value)this.$emit('changeDel',value)}}}
</script><style></style>
ToDoFooter.vue
<template>
<!-- 统计和清空 --><footer class="footer"><!-- 统计 --><span class="todo-count">合 计:<strong> {{list.length}} </strong></span><!-- 清空 --><button class="clear-completed" @click="delAll">清空任务</button></footer>
</template><script>
export default {props:{list:Array},methods: {delAll(){//子传父this.$emit('delAll')}}
}
</script><style></style>
四、prop语法
4.1、prop语法基础语法
- prop
定义:组件上注册的一些自定义属性
作用:向子组件传递数据
特点:
- 可以传递 任意数量 的prop
- 可以传递 任意类型 的prop
4.2、 prop校验
思考:组件的prop可以乱传?
作用:为组件的prop指定验证要求,不符合要求,控制台就会有错误提示。----->帮助开发者,快速发现错误。
校验语法:
- 类型校验
数据类型校验:将props数组的形式改为对象的形式
//数据类型校验:将props数组的形式改为对象的形式// props:['title']props:{title: String //String Boolean Array Object Function等等},
- 非空校验
- 默认值
- 自定义校验
//2.完整写法props:{title: {type: String,//类型校验required: true, //必传属性:父传子的属性没有传就会报错default: 'hello radan',//默认值属性:当父组件组没有自定义属性绑定的时候,就会按照默认值进行处理//自定义校验validator(value){console.log(value)//对当前的title对应的value是否符合一定的条件return true;}}
注意:validator(value)中的value形参就是父组件传递过来的值
4.3、prop&data、单向数据流
prop&data中谁的数据谁负责
共同点:都可以给组件提供数据。
区别:
- prop 的数据是外部的 → 不能直接改,要遵循 单向数据流
- data 的数据是自己的 → 随便改
单向数据流:父级props 的数据更新,会向下流动,影响子组件。这个数据流动是单向的
子组件修改props中的数据
App.vue
<template><div class="app"><BaseCount :title="myData" @changeCount="changeFn"></BaseCount></div>
</template><script>import BaseCount from './components/BaseCount.vue'
export default {name: 'app',components: {BaseCount : BaseCount},data(){return {myData : 1}},methods:{changeFn(value){// alert(value)this.myData=value}}
}
</script><style scoped>
</style>
BaseCount.vue
<template><div class="baseCount"><button v-on:click="countSub" v-show="title >0">-</button><span>{{title}}</span><button @click="countAdd">+</button></div>
</template><script>
export default {// 1. data中的数据可以在当前组件中随便改// data(){// return {count:999}// }// 2. props中的数据的修改办法:props:{title:Number},methods:{countAdd(){this.$emit('changeCount',this.title+1)},countSub(){this.$emit('changeCount',this.title-1)}// ,// isTrue(value){// console.log(value)// if(value>0)// {// return true// }// }}
}
</script><style>
</style>