目录
41.ref属性:
ref属性:
1.被用来给元素或子组件注册引用信息(id的代替者)
2.应用在HTML标签上获取的时真实dom元素,应用在组件标签上时组件的实例对象(vc)
3.使用方法:
打标识:<h1 ref="xxxx"></h1>或<school ref="xxx"></school>
获取:this.$refs.xxx
<template>
<div id="app">
<h1 v-text="msg" ref="title"></h1>
<button @click="showDom">点我输出上方的Dom元素</button>
<school ref="sch"></school>
<student></student>
</div>
</template>
<script>
//引入组件
import school from "./components/schoolName.vue";
import student from "./components/studentName.vue";
export default {
name: "app",
data(){
return {
msg:'学习Vue!启动!'
}
},
components: {
school,
student,
},
methods:{
showDom(){
console.log(this.$refs.title)//真实dom对象
console.log(this.$refs.sch)//school组件的实例对象
}
}
};
</script>
42.props配置
配置项props:
功能:让组件接受外部传入过来的数据
(1)传递数据:
<demo name='xxx' >
(2)接收数据:
第一种方式(只接收)——————props['name']
第二种方式(限制类型)
props: {
name:String
}
第三种方式: (限制类型,限制必要性,指定默认值)
props:{
name :{
type:String,//类型
required:true, //必要性
default:'张三' //默认值
}
}
备注:props是只读的,Vue底层会监测你对props的修改,如果进行了修改,就会发出警告,若业务需求确实需要修改,那么请复制props的内容到data中一份,然后去修改data中的数据
<div>
<student name="LYX" :age="18" sex="男"></student>
<student name="XYL" :age="88" sex="未知"></student>
</div>
StudentName.vue页面
<template>
<!--组建的结构-->
<div class="demo">
<h1>{{ msg }}</h1>
<h2>学生姓名:{{ name }}</h2>
<h2>学生年龄:{{ myAge+1 }}</h2>
<button @click="updateAge">尝试修改收到的年龄</button>
<h2>性别:{{ sex }}</h2>
</div>
</template>
<script>
//组件交互相关的代码(数据,方法等)
export default {
data() {
return {
name: "我是打工仔",
myAge: this.age,
}
},
//简单声明接收
//props:['name','age','sex']
//接受的同时对数据进行类型限制
/* props:{
name:String,
age:Number,
sex:String
}
*/
// 接收的同时对数据进行类型限制+默认值的指定+必要性的限制
props:{
name:{
type:String, //name的类型是字符串
required:true, //name是必要的
},
age:{
type:Number,
default:99 //默认值
},
sex:{
type:String,
required:true
}
},
methods:{
updateAge(){
this.myAge++
},
}
};
</script>
43.mixin混入
mixin混入
功能:可以把多个组件共有的配置提取成一个混入对象
使用方法:
第一步:定义混入,例如
{
data(){.....},
method(){......}
}
第二步:使用混入,例如:
(1) 全局混入:Vue.mixin(xxx)
(2)局部混入:mixins:[xxx]
备注:使用混入加入数据时,原有的数据不会改变
mais.js文件:
import Vue from 'vue'
import App from './app.vue'
import {hunhe2,mixin} from './components/mixin'
// 关闭Vue的生产提示
Vue.config.productionTip = false
// 全局混合
Vue.mixin(hunhe2)
Vue.mixin(mixin)
new Vue({
render: h => h(App),
// template:{App}
}).$mount('#app')
混合函数mixin.js文件
export const mixin = {
methods: {
showName(){
alert(this.name)
}
},
}
export const hunhe2={
data() {
return {
x:100,
y:200
}
},
}
student.vue文件
<template>
<!--组建的结构-->
<div class="demo">
<h2 @click="showName">学生姓名:{{ name }}</h2>
<h2>性别:{{ sex }}</h2>
</div>
</template>
<script>
//局部混入
import {hunhe2,mixin} from './mixin'
export default{
data(){
return{
name:'LYX',
sex:'男',
x:666
}
},
mixins:[mixin,hunhe2]
}
</script>
school.vue文件
<template>
<!-- 组件的结构 -->
<div class="demo">
<h2 @click="showName">学校名称:{{name}}</h2>
<h2>学校地址:{{address}}</h2>
</div>
</template>
<script>
// 局部混合
// import {mixin,hunhe2} from './mixin'
export default {
data(){
return{
name:'尚硅谷',
address:'上海',
}
},
// mixins:[mixin,hunhe2]
}
</script>
44.插件
插件:
功能:用于增强Vue
本质:包含install方法的一个对象,install的第一个参数是Vue,第二个以后的参数是插件使用者传递的值
定义插件:
对象.install = function(Vue,options){
//1.添加全局过滤器
Vue.filter(.......)
//2.添加全局指令
Vue.directive(......)
//3.配置全局混入
Vue.mixin(.....)
//4.添加实例方法
Vue.prototype.$mymethod = function(){.....}
Vue.protoype.$myProperty=xxxx
}
使用插件:Vue.use(插件文件名)
45.scoped
scoped样式
作用:让同名样式在局部生效,防止冲突
写法:<style scoped>
app.vue页面
<template>
<div class="demo">
<student></student>
<school></school>
</div>
</template>
<script>
//引入组件
import school from "./components/schoolName.vue";
import student from "./components/studentName.vue";
export default {
name: "app",
data() {
return {};
},
components: {
school,
student,
},
};
</script>
<style lang="less">
// 使用less语法
.demo {
background-color: greenyellow;
#forId {
font-size: 30px;
}
}
</style>
student.vue页面
<template>
<!--组建的结构-->
<div class="demo">
<h2 >学生姓名:{{ name }}</h2>
<h2>性别:{{ sex }}</h2>
</div>
</template>
<script>
export default{
data(){
return{
name:'LYX',
sex:'男',
}
}
}
</script>
<style scoped>
.demo{
background-color: red;
}
</style>
school.vue页面
<template>
<!--组件的结构-->
<div class="demo">
<h2 >学校名称:{{ name }}</h2>
<h2 id="forId">学校地址:{{ address }}</h2>
</div>
</template>
<script>
export default {
data(){
return{
name :'河北大学',
address:'保定',
}
}
}
</script>
<style scoped>
.demo{
background-color:mediumpurple;
}
</style>
46.todolist案例
1.组件化编码流程:
(1)拆分静态组件:组件要按照功能点拆分,命名不与HTML元素冲突
(2)实现动态组件:考虑好数据的存放位置,数据是一个组件在用,还是一些组件在用
1.一个组件在用:放在组件自身即可
2.一些组件在用:放在他门共同的父组件上(状态提升)
3.实现交互:从绑定事件开始
2.props适用于
(1)父组件===》子组件 通信
(2)子组件===》父组件 (要求父先给予一个函数)
3.使用v-model时要切记:v-model绑定的值不能是props传过来的值,因为props是不可修改的
4.props传过来的若是对象的值,修改对象中的属性时Vue不会报错,但不推荐
app.vue页面代码逻辑:
<template>
<div class="todo-container">
<Header :addTodo="addTodo"></Header>
<List :todos="todos" :checkTodo="checkTodo" :deleteTodo="deleteTodo"></List>
<Footer
:todos="todos"
:checkAllTodo="checkAllTodo"
:clearAllTodo="clearAllTodo"
></Footer>
</div>
</template>
<script>
import Header from "./components/testHeader.vue";
import Footer from "./components/testFooter.vue";
import List from "./components/testList.vue";
export default {
name: "app",
components: { Header, Footer, List },
data() {
return {
todos: [
{ id: "001", title: "java", done: true },
{ id: "002", title: "C++", done: false },
{ id: "003", title: "Git", done: false },
],
};
},
methods: {
//添加一个todo
addTodo(todoObj) {
this.todos.unshift(todoObj);
},
//勾选或者取消一个todo
checkTodo(id) {
this.todos.forEach((todo) => {
if (todo.id == id) todo.done = !todo.done;
});
},
//删除一个todo
deleteTodo(id) {
console.log(id);
this.todos = this.todos.filter((todo) => {
return todo.id !== id;
});
},
//全选or取消全选
checkAllTodo(done) {
this.todos.forEach((todo) => {
todo.done = done;
});
},
//清除所有已完成的todo
clearAllTodo() {
this.todos = this.todos.filter((todo) => {
return !todo.done
})
}
}
};
</script>
<style>
body {
background: #fff;
}
.btn {
display: inline-block;
padding: 4px 12px;
margin-bottom: 0;
font-size: 14px;
line-height: 20px;
text-align: center;
vertical-align: middle;
cursor: pointer;
box-shadow: insert 0 1px 0 rgba(255, 255, 255, 0.2),
1px 2px rgba(0, 0, 0, 0.2);
border-radius: 4px;
}
.btn-danger {
color: #fff;
background-color: rgb(226, 122, 122);
border: 1px solid pink;
}
.btn-danger:hover {
color: #fff;
background-color: red;
}
.btn:focus {
outline: none;
}
.todo-container {
width: 600px;
margin: 0 auto;
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
}
</style>
Header.vue页面代码逻辑
<template>
<div class="todo-header">
<input type="text" placeholder="请输入你的任务,按下回车确定" v-model="title" @keyup.enter="add">
</div>
</template>
<script>
import {nanoid} from 'nanoid'
export default {
name:'testHeader',
props:['addTodo'],
data(){
return{
title:''
}
},
methods:{
add(event){
//校验数据
if(!this.title.trim())return alert("输入不能为空")
//将用户输入包装成一个todo对象
const todoObj = {id:nanoid(),title:event.target.value,done:false}
//通知app组件去添加一个todo对象
this.addTodo(todoObj)
//清空输入
this.title=''
}
}
}
</script>
<style scoped>
.todo-header{
width: 560px;
height: 28px;
font-size: 14px;
border-radius: 4px;
padding: 4px 7px;
}
.todo-header input:focus{
outline: none;
border-color: rgb(96, 139, 219);
box-shadow: 5px 10px black 0.3;
}
</style>
List.vue页面代码逻辑
<template>
<ul class="todo-main">
<myItem
v-for="todoObj in todos"
:key="todoObj.id"
:todo="todoObj"
:checkTodo="checkTodo"
:deleteTodo="deleteTodo"
>
</myItem>
</ul>
</template>
<script>
import myItem from "./testItem.vue";
export default {
name: "testList",
components: { myItem },
props: ["todos", "checkTodo", "deleteTodo"],
};
</script>
<style scoped>
.todo-main {
margin-left: 0px;
border: 1px solid #ddd;
border-radius: 2px;
padding: 0px;
}
.todo-empty {
height: 40px;
line-height: 40xp;
border: 1px solid #ddd;
border-radius: 2px;
padding-left: 5px;
margin-top: 10px;
}
</style>
item.vue页面代码逻辑
<template>
<li>
<label>
<!-- 如下代码也可以实现功能,但是不太推荐,因为有点违反原则,因为 修改了props-->
<!-- <input type="check" v-model="todo.done"> -->
<input
type="checkbox"
:checked="todo.done"
@change="handCheck(todo.id)"
/>
<span>{{ todo.title }}</span>
</label>
<button class="btn btn-danger" @click="handleDelete(todo.id)">删除</button>
</li>
</template>
<script>
export default {
name: "MyItem",
// 声明接收todo对象
props: ["todo", "checkTodo", "deleteTodo"],
methods: {
handCheck(id) {
// 通知app组件将对应的todo对象的done值取反
this.checkTodo(id);
},
handleDelete(id) {
if (confirm("确定要删除吗?")) {
this.deleteTodo(id);
}
},
},
};
</script>
<style scoped>
li {
list-style: none;
height: 36px;
line-height: 36px;
padding: 0 5px;
border-bottom: 1px solid #ddd;
}
li label {
float: left;
cursor: pointer;
}
li label li input {
vertical-align: middle;
margin-right: 6px;
position: relative;
top: -1px;
}
li button {
float: right;
display: none;
margin-top: 3px;
}
li:before {
content: initial;
}
li:last-child {
border-bottom: none;
}
li:hover {
background-color: #ddd;
}
li:hover button {
display: block;
}
</style>
Footer.vue页面代码逻辑
<template>
<div class="todo-footer" v-show="total">
<label>
<input type="checkbox" :checked="isAll" @change="checkAll" />
</label>
<span>
<span>已完成{{ doneTotal }}</span
>/全部{{ total }}
</span>
<button class="btn btn-danger" @click="clearAll">清除已完成任务</button>
</div>
</template>
<script>
export default {
name: "testFooter",
props: ["todos", "checkAllTodo", "clearAllTodo"],
computed: {
total() {
return this.todos.length;
},
doneTotal() {
let i = 0;
this.todos.forEach((todo) => {
if (todo.done) i++;
});
return i;
},
isAll() {
return this.doneTotal == this.total && this.total > 0;
},
},
methods: {
checkAll(e) {
this.checkAllTodo(e.target.checked);
},
clearAll() {
this.clearAllTodo();
},
},
};
</script>
<style scoped>
.todo-footer {
height: 40px;
line-height: 40px;
padding-left: 6px;
margin-top: 5px;
}
.todo-footer label {
display: inline-block;
margin-right: 20px;
cursor: pointer;
}
.todo-footer label input {
position: relative;
top: -1px;
vertical-align: middle;
}
.todo-footer button {
float: right;
margin-top: 5px;
}
</style>
47.浏览器本地存储
1.存储内容大小一般支持5MB左右
2.浏览器端通过Window.sessionStorage和Window.localStorage属性来实现本地存储机制
3.相关api:
(1)xxxxxxStorage.setItem('key','value');该方法接受一个建和值作为参数,会把键值对添加到存储中,如果键名存在,则更新其对应的值
(2)xxxxxStorage.getItem('key','value');该方法接收一个键名作为参数,返回键名对应的值
(3)xxxxStroage.removeItem(‘key’,‘value’);该方法接收一个键名作为参数,并把该键名从存储中删除
(4)xxxxStorage.clear();该方法会清空存储中所有的数据
4.备注
(1)sessionStorage存储的内容会随着浏览器窗口关闭而消失
(2)LocalStorage存储的内容,需要手动清除才会消失
(3)xxxxStroage.getItem(xx)如果xxx对应的value获取不到,那么getItem的返回值时null
(4)JSON.parse(null)的结果依然是null
<body>
<h2>localStorage</h2>
<button onclick="saveDate()">点我保存一个数据</button>
<button onclick="readDate()">点我读取一个数据</button>
<button onclick="deleteDate()">点我删除一个数据</button>
<button onclick="deleteAllDate()">点我清空数据</button>
<script>
let p = { name: "LYX", age: 18 };
let msg;
function saveDate() {
window.localStorage.setItem("msg", 666);
localStorage.setItem("person", JSON.stringify(p));
}
function readDate() {
alert(window.localStorage.getItem("msg", 666));
const result = localStorage.getItem("person");
console.log(JSON.parse(result));
}
function deleteDate() {
window.localStorage.removeItem("msg");
}
function deleteAllDate() {
localStorage.clear();
}
</script>
</body>
48. todolist本地存储
<template>
<div class="todo-container">
<Header :addTodo="addTodo"></Header>
<List :todos="todos" :checkTodo="checkTodo" :deleteTodo="deleteTodo"></List>
<Footer
:todos="todos"
:checkAllTodo="checkAllTodo"
:clearAllTodo="clearAllTodo"
></Footer>
</div>
</template>
<script>
import Header from "./components/testHeader.vue";
import Footer from "./components/testFooter.vue";
import List from "./components/testList.vue";
export default {
name: "app",
components: { Header, Footer, List },
data() {
return {
todos: JSON.parse(localStorage.getItem('todos'))||[]
};
},
methods: {
//添加一个todo
addTodo(todoObj) {
this.todos.unshift(todoObj);
},
//勾选或者取消一个todo
checkTodo(id) {
this.todos.forEach((todo) => {
if (todo.id == id) todo.done = !todo.done;
});
},
//删除一个todo
deleteTodo(id) {
console.log(id);
this.todos = this.todos.filter((todo) => {
return todo.id !== id;
});
},
//全选or取消全选
checkAllTodo(done) {
this.todos.forEach((todo) => {
todo.done = done;
});
},
//清除所有已完成的todo
clearAllTodo() {
this.todos = this.todos.filter((todo) => {
return !todo.done
})
}
},
watch:{
todos:{
deep:true,
handler(value){
localStorage.setItem('todos',JSON.stringify(value))
}
}
}
};
</script>
49.组件自定义事件——绑定和解绑
1.一种组件间通信的方式,适用于:子组件==》父组件
2.使用场景:A是父组件,B是子组件,B想给A传数据,那么就要在A中给B绑定自定义事件(事件的回调在A中)
3.绑定自定义事件:
(1)第一种方式,在父组件中:或
(2)第二种方法,在父组件中:
...........
mounted(){
this.$ref.xxx.$on('atuguigu,thiss.test)
}
(3)若想让自定义事件只能触发一次,可以使用once修饰符,或$once方法
4.触发自定义事件:this.$emit('atguigu',数据)
5.解绑自定义事件:this.$off('atguigu')
6.组件上也可以绑定原生dom事件,需要使用native修饰符
7.注意:通过this.$ref.组件名.$on('atguigu',回调)绑定自定义事件时,回调要么配置在methods中,要么用箭头函数,否则this指向vc而不是vm
50.全局事件总线
1.一种组件间通信的方式,适用于任意组件间通信
2.安装全局事件总线:
new vue({
......
beforeCreate(){
Vue.prototype.$bus=this//安装全局事件总线,$bus就是当前应用的vm
},
})
3.使用事件总线:
(1).接收数据:A组件想接收B组件的数据,则在A组件中$bus绑定自定义事件,事件的回调留在A组自身。
method(){
demo(data){.........}
}
mounted(){
this.$bus.$on('xxx',this.demo)
}
(2).B组件提供数据:
this.$bus.$emit('xxx',数据)、
4.最好在beforeDestroy钩子中,用$off去绑定当前组件所用到的事件
main.js文件:
import Vue from 'vue'
import App from './App.vue'
// 关闭Vue的生产提
Vue.config.productionTip = false
new Vue({
render: h => h(App),
// 安装全局事件总线,$bus就是当前应用的vm
beforeCreate(){
Vue.prototype.$bus=this
}
}).$mount('#app')
app.vue文件:
<template>
<div>
<h1>{{msg}}</h1>
<school/>
<student/>
</div>
</template>
<script>
import student from './components/student.vue'
import school from './components/school.vue'
export default({
name:'App',
components:{school,student},
data(){
return{
msg:'早上好!打工仔'
}
},
})
</script>
school.vue文件:
<template>
<!-- 组件的结构 -->
<div class="demo">
<h2>学校名称:{{ name }}</h2>
<h2>学校地址:{{ address }}</h2>
</div>
</template>
<script>
export default {
name: "mySchool",
data() {
return {
name: "河北大学",
address: "保定",
};
},
mounted() {
this.$bus.$on("hello", (data) => {
console.log("我是学校组件,收到了student的数据:", data);
});
},
beforeDestroy() {
// 给总线上的hello事件解绑
this.$bus.$off("hello");
},
};
</script>
<style scoped>
.demo {
background-color: red;
}
</style>
student.vue文件
<template>
<!-- 组件的结构 -->
<div class="demo">
<h2 >学生姓名:{{name}}</h2>
<h2>性别:{{sex}}</h2>
<button @click="sendStudentName">把学生名给school组件</button>
</div>
</template>
<script>
export default {
name:'myStudent',
data(){
return{
name:'LYX',
sex:'未知'
}
},
methods: {
sendStudentName(){
this.$bus.$emit('hello',this.name)
}
},
}
</script>
<style scoped>
.demo{
background-color: aqua;
}
</style>
下一篇:持续更新~