目录
案例
VUE简单的表单操作
VUE留言板效果
VUE两种常见的tab切换实现方式
VUE简易购物车
VUE计划清单
一Vue基础
什么是Vue?
补充:mvvm框架
mvvm的组成
详解
举例来说,使用Vue.js的MVVM框架的代码可能如下所示:
<template>
<div>
<h1>{{ message }}</h1>
<input v-model="message">
</div>
</template>
<script>
export default {
data() {
return {
message: 'Hello, MVVM!'
};
}
};
</script>
在这个例子中,{{ message }}
是Vue.js中的模板语法,它会自动将message
数据绑定到对应的DOM元素上。当用户在输入框中输入时,数据会自动更新,反之亦然。这种双向数据绑定的机制是MVVM框架的核心概念之一。
Vue的使用方法
1.直接下载并引入
<script src="./js/vue.global.js"></script>
<script>
//解构出一个创建应用的方法
const {createApp} = Vue;
//创建应用
createApp({
//设置数据
data(){
return{
str:'wbg加油'
}
}
}).mount('#app');
</script>
2.通过 CDN 使用 Vue
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
3.通过npm安装
使用npm(Node Package Manager)可以将Vue.js安装为项目的依赖项。首先,在项目目录下运行以下命令安装Vue.js:
npm install vue
然后,在JavaScript文件中通过import
语句引入Vue:
import Vue from 'vue';
4.使用Vue CLI创建项目
Vue CLI(命令行界面)是一个官方提供的工具,用于快速搭建Vue项目。首先,全局安装Vue CLI:
npm install -g @vue/cli
然后,通过以下命令创建新项目:
vue create my-vue-project
进入项目目录,运行以下命令启动开发服务器:
cd my-vue-project
npm run serve
在这种方式下,Vue.js会被自动安装并作为项目的依赖项。
二插值表达式
什么是插值表达式?
插值表达式的缺点
解决方法
相关代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>插值表达式</title>
<style>
*{
margin: 0;
padding: 0;
}
/* //使用属性选择器,绑定v-cloak 属性的内容 */
[v-cloak]{
display: none;
}
</style>
</head>
<body>
<div id="app">
<p v-cloak>{{ str }}</p>
<p v-cloak>{{ 1+1 }}</p>
<p v-cloak>{{ 3>4?'wbg':'vue'}}</p>
<p v-text="str"></p>
<div v-html="str1"></div>
<p>{{obj.name+'演唱'+obj.song}}</p>
</div>
</body>
</html>
<script src="./js/vue.global.js"></script>
<script>
const {createApp}=Vue;
let app = createApp({
/*
data函数中存放当前页面中所有的数据,如果需要声明数据,必须声明在data中
data是一个方法,发的返回值是一个对象,data必须有返回值,否则报错
*/
data(){
return{
str:'伤不起,香水有毒',
str1:'<h2>老鼠爱大米</h2>',
obj:{
name:'伍佰',
song:'挪威的森林',
}
}
}
})
app.mount('#app')
</script>
三 属性绑定
简写方式 :属性名 = '属性名/变量名'
<body>
<!--
属性绑定
在vue中,{{}}插值表达式不能直接绑定属性的值
可以使用 v-bind来绑定属性
语法是
v-bind:属性名 = '属性值/变量名'
简写方式
:属性名 = '属性名/变量名'
-->
<div id="app">
<a v-bind:href="'http://jd.com'">微博</a>
<a v-bind:href="url">微博</a>
<a :href="url">微博简写</a>
</div>
</body>
</html>
<script src="./js/vue.global.js"></script>
<script>
const { createApp } = Vue;
createApp({
data(){
return{
url:'https://www.sina.com.cn'
}
}
}).mount('#app')
</script>
绑定style
<!-- 绑定style -->
<h2 :style="{ color:'#04be02',fontSize:'30px' }">{{ str }}</h2>
<div :style="style"></div>
<div :style="'font-size:20px;color:#f00;'">多行不义必自毙</div>
<div :style="[ {color:'#04be02'},{ fontSize:'30px' } ]">多行不义必自毙</div>
<div class="abc">柳宗元</div>
<div :class="'abc aa'">曾巩</div>
数组形式绑定class
<div :class="[ 'abc','aa' ]">韩愈</div>
对象形式绑定class
<div :class="{'abc':3>4,'aa':3<4}">苏轼</div>
相关代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>绑定style和class</title>
<style>
* {
margin:0;
padding:0;
}
.abc {
width:200px;
height: 200px;
background:#f60;
margin:30px auto;
}
.aa {
background:#f0f;
}
</style>
</head>
<body>
<div id="app">
<!-- 绑定style -->
<h2 :style="{ color:'#04be02',fontSize:'30px' }">{{ str }}</h2>
<div :style="style"></div>
<div :style="'font-size:20px;color:#f00;'">多行不义必自毙</div>
<div :style="[ {color:'#04be02'},{ fontSize:'30px' } ]">多行不义必自毙</div>
<div class="abc">柳宗元</div>
<div :class="'abc aa'">曾巩</div>
<!-- 使用 数组形式绑定class -->
<div :class="[ 'abc','aa' ]">韩愈</div>
<!-- 使用对象形式绑定class,属性名为class名,属性的值是一个boolean值,如果布尔值为true,则绑定该class名,否则不绑定 -->
<div :class="{'abc':3>4,'aa':3<4}">苏轼</div>
<!-- 总结:style和class的绑定都支持 数组形式和对象形式 -->
<div :class="3<4?className:''">欧阳修</div>
<div :class="3<4&&className">欧阳封</div>
</div>
</body>
</html>
<script type="module">
import { createApp } from './js/vue.esm-browser.js';
createApp({
data(){
return {
str:'从此君王不早朝',
style:{
height:'200px',
width:'200px',
background:'#04be02'
},
className:'abc'
}
}
}).mount('#app');
</script>
四事件绑定
<button v-on:click="num++">点击++</button>
<button v-on:click="show('天涯何处有房产')">点击显示</button>
<button @click="show('天涯何处没有草')">点击显示</button>
<button @click="()=>show('天涯何处没有草')">点击显示</button>
<hr>
<button @click="num++">点击显示或者隐藏元素</button>
<div class="wp" :style="{display:num%2==0?'block':'none'}"></div>
</div>
</body>
</html>
<script type="module">
import {createApp} from './js/vue.esm-browser.js';
createApp({
data() {
return {
num:100
}
}
//methods中存放了组件所有的方法,方法只能存储在 methods中
,methods: {
show(str){
alert('东边日出西边雨'+str)
}
},
}).mount('#app')
事件的修饰符
相关代码
<body>
<div id="app">
<p>{{num}}</p>
<button @click="add">点击添加</button>
<div class="wp" @click="showInfo">
<div class="cont" @click.stop.once="showMsg" @contextmenu.prevent="showMsg" > </div>
</div>
</div>
</body>
</html>
<script type="module">
import {createApp} from './js/vue.esm-browser.js';
createApp({
data() {
return {
num:100
}
},
methods: {
add(){
//在vue实例中获取data中的数据,直接
this.num++
},
showInfo(){
console.log('外层触发');
},
showMsg(){
console.log('内层触发');
}
}
}).mount('#app')
</script>
按键修饰符
相关代码
<body>
<div id="app">
<input type="text" value="" @keyup.enter="show"> <br>
<textarea cols="30" rows="10" @keyup.up="show"></textarea>
<!-- 非系统键 -->
<input type="text" value="" @keyup.exact="show">
</div>
</body>
</html>
<script type="module">
/*
按键修饰符,当按下或者抬起对应对应修饰符的按键时触发事件
.enter
.tab
.delete (捕获“Delete”和“Backspace”两个按键)
.esc
.space
.up
.down
.left
.right
.ctrl
.alt
.shift
.meta
.exact 非系统键
*/
import {createApp} from './js/vue.esm-browser.js';
createApp({
data() {
return {}
},
methods: {
show(e){
console.log(e.target.value);
}
},
}).mount('#app')
五数据双向绑定
设置单选框的 v-model
<!-- 设置单选框的 v-model -->
<label>性别</label>
<label><input type="radio" name="sex" v-model="sex" value="男">男</label>
<label><input type="radio" name="sex" v-model="sex" value="女">女</label>
<button @click="showSex">点击显示选择的性别</button>
<br>
<script type="module">
import {createApp} from './js/vue.esm-browser.js';
createApp({
data() {
return {
val:'货卖堆山',
val2:'男要俏一身皂',
sex:'男',
hero:['张居正','海瑞','王阳明','朱熹'],
num:'100',
str:'玩物丧志'
}
}
,methods: {
show(){
alert(this.val2)
},
showSex(){
alert(this.sex)
},
showHero(){
console.log(this.hero);
},
showNum(){
console.log(this.num);
}
},
}).mount('#app')
</script>
设置复选框的 v-model
<label for="">英雄</label>
<label for=""><input type="checkbox" v-model="hero" value="张居正">张居正</label>
<label for=""><input type="checkbox" v-model="hero" value="海瑞">海瑞</label>
<label for=""><input type="checkbox" v-model="hero" value="王阳明">王阳明</label>
<label for=""><input type="checkbox" v-model="hero" value="朱熹">朱熹</label>
<label for=""><input type="checkbox" v-model="hero" value="张载">张载</label>
<label for=""><input type="checkbox" v-model="hero" value="程颐">程颐</label>
<br>
<button @click="showHero">选中的值</button>
<script type="module">
import {createApp} from './js/vue.esm-browser.js';
createApp({
data() {
return {
val:'货卖堆山',
val2:'男要俏一身皂',
sex:'男',
hero:['张居正','海瑞','王阳明','朱熹'],
num:'100',
str:'玩物丧志'
}
}
,methods: {
show(){
alert(this.val2)
},
showSex(){
alert(this.sex)
},
showHero(){
console.log(this.hero);
},
showNum(){
console.log(this.num);
}
},
}).mount('#app')
</script>
修饰符
<input type="number" v-model.number="num">
<p>{{num}}</p>
<button @click="showNum">点击显示数字</button>
<hr>
<input type="text" v-model.lazy="str">
<p style="border: 1px #f00 solid;">{{str}}</p>
相关代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>数据双向绑定</title>
</head>
<body>
<div id="app">
<input type="text" :value="val" @input="e=>val=e.target.value">
<p>{{val}}</p>
<!-- 在表单元素中使用v-model 实现数据的双向绑定
双向绑定:简言之就是数据在视图层的更改会立即体现在model层,反之在model层的改变
也会立即体现在视图层
-->
<input type="text" v-model="val2">
<p>{{val2}}</p>
<button @click="show">点击显示</button>
<hr>
<!-- 设置单选框的 v-model -->
<label>性别</label>
<label><input type="radio" name="sex" v-model="sex" value="男">男</label>
<label><input type="radio" name="sex" v-model="sex" value="女">女</label>
<button @click="showSex">点击显示选择的性别</button>
<br>
<!-- 设置复选框的 v-model
设置复选框的 v-model的值是一个数组,该数组存储复选框选中的内容
-->
<label for="">英雄</label>
<label for=""><input type="checkbox" v-model="hero" value="张居正">张居正</label>
<label for=""><input type="checkbox" v-model="hero" value="海瑞">海瑞</label>
<label for=""><input type="checkbox" v-model="hero" value="王阳明">王阳明</label>
<label for=""><input type="checkbox" v-model="hero" value="朱熹">朱熹</label>
<label for=""><input type="checkbox" v-model="hero" value="张载">张载</label>
<label for=""><input type="checkbox" v-model="hero" value="程颐">程颐</label>
<br>
<button @click="showHero">选中的值</button>
<hr>
<!-- 修饰符
number 修饰符,把输入框中的内容转化为数字
trim 修饰符,去掉输入内容左右两变的空格
lazy 修饰符,把input事件改为change事件 (可以优化性能)
-->
<input type="number" v-model.number="num">
<p>{{num}}</p>
<button @click="showNum">点击显示数字</button>
<hr>
<input type="text" v-model.lazy="str">
<p style="border: 1px #f00 solid;">{{str}}</p>
</div>
</body>
</html>
<script type="module">
import {createApp} from './js/vue.esm-browser.js';
createApp({
data() {
return {
val:'货卖堆山',
val2:'男要俏一身皂',
sex:'男',
hero:['张居正','海瑞','王阳明','朱熹'],
num:'100',
str:'玩物丧志'
}
}
,methods: {
show(){
alert(this.val2)
},
showSex(){
alert(this.sex)
},
showHero(){
console.log(this.hero);
},
showNum(){
console.log(this.num);
}
},
}).mount('#app')
</script>
六常用指令
v-if和v-show
相关代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>v-if和v-show</title>
<style>
*{
margin: 0;
padding: 0;
}
.wp{
width: 200px;
height: 200px;
background: #04be02;
}
</style>
</head>
<body>
<div id="app">
<div class="wp" v-show="bol">show</div>
<div class="wp" v-if="bol">if</div>
<button @click="show">点击显示或者隐藏</button>
<hr>
<div v-if="num%2==0">晚上吃啥{{num}}</div>
<div v-else-if="num%3==0">螺蛳粉{{num}}</div>
<div v-else>麻辣烫{{num}}</div>
<button @click="num++">点击++</button>
<ul>
<li v-for="(item,index) in arr">
{{item+index}}
<button @click="arr.splice(index,1)">删除</button>
</li>
</ul>
<button @click="add">添加数组</button>
</div>
</body>
</html>
<script type="module">
import {createApp} from './js/vue.esm-browser.js';
createApp({
data() {
return {
bol:true,
num:1,
arr:['晚上吃啥','螺蛳粉','麻辣烫']
}
}
,methods: {
show(){
this.bol = !this.bol
},
add(){
this.num+=1;
this.arr.push('老母鸡汤'+this.num)
}
},
}).mount('#app')
</script>
v-for循环
注意
相关代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>v-for</title>
</head>
<body>
<div id="app">
<ul>
<li v-for="(item,index) in arr" :key="index" @click="showAlert(item.name)">
<span>{{index}}-{{item.name}}:{{item.nickname}}</span>
</li>
</ul>
<hr>
<ul v-for="aa in arr">
<li>{{aa.name}}:{{aa.nickname}}</li>
</ul>
<p v-for="(item,key) in obj">{{key}}:{{item}}</p>
<hr>
<!--
v-for 结合 template 标签(组件)循环数据
template 标签 不会被渲染到页面上,一般用来实现数据绑定的功能
-->
<template v-for="item in arr" :key="item.name">
<p>{{item.name}}</p>
</template>
<hr>
<!-- 循环数字,一般是整数,每一个整体是一个循环的项 -->
<p v-for="n in 10">{{n}}</p>
<!-- 循环字符串 -->
<p v-for="t in set">{{t}}</p>
</div>
</body>
</html>
<script type="module">
import {createApp} from './js/vue.esm-browser.js'
createApp({
data() {
return {
arr:[
{
name:'吕布',
nickname:'奉先'
},
{
name:'马岱',
nickname:'丁玲'
},
{
name:'马超',
nickname:'孟起'
},
{
name:'文鸳',
nickname:'文鸳'
},
],
obj:{
name:'孙尚香',
age:20,
job:'射手'
},
str:'念天地之悠悠,独怆然而涕下'
}
},
methods: {
showAlert(str){
alert(str)
}
},
}).mount('#app')
</script>
其他内置指令
v-pre
v-once
相关代码
<body>
<div id="app">
<!-- v-pre 他所绑定的元素不进行vue的编译,原样输出 -->
<p>{{str}}</p>
<!-- v-once 他所绑定的元素只渲染一次,忽略之后所有的更新 -->
<p v-once>{{num}}</p>
<button @click="num++">点击++</button>
<hr>
<!-- <div v-for="(item,index) in arr" v-memo="arr">{{item}}</div>
<button @click="change">点击改变数据</button> -->
<!-- 实现组件内容的缓存,如果他的值不发生改变,那么他绑定的元素内部不会各跟
据数据的改变而重新渲染 -->
<div v-memo="arr">
<h1>{{str}}</h1>
</div>
<button @click="change1">点击改变数据</button>
</div>
</body>
</html>
<script type="module" >
import {createApp} from './js/vue.esm-browser.js'
createApp({
data() {
return {
str:'诸葛亮',
num:100,
arr:['诸葛亮','诸葛瑾']
}
},
methods: {
change(){
this.arr.push('诸葛均')
},
change1(){
this.arr.push('诸葛均')
this.str = '司马光'
}
},
}).mount('#app')
</script>
七计算属性
注意
计算属性的优点
相关代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>计算属性</title>
</head>
<body>
<div id="app">
<h2>{{num}}</h2>
<p>{{str.split('').reverse().join('')}}</p>
<p>{{changeStr}}</p>
<template v-for="item in arr">
<p v-if="item%2==0">{{item}}</p>
</template>
<p v-for="item in numArr">{{item}}</p>
<h1>{{aa}}</h1>
<button @click="setVal('零陵上将邢道荣')">点击设置</button>
</div>
</body>
</html>
<script type="module">
import { createApp } from './js/vue.esm-browser.js';
let app = createApp({
data() {
return {
num:100,
str:'相见时难别亦难东风无力百花残',
arr:[1,2,3,4,5,6,7,8,9],
txt:'尔今死去'
}
},
methods: {
setVal(str){
//设置计算属性的值
this.aa = str;
}
},
//设置计算属性
computed:{
changeStr(){
return this.str.split('').reverse().join('')
},
numArr(){
return this.arr.filter(item=>{
return item%2 == 0;
})
} ,
aa:{
get(){
return this.txt +'-林黛玉'
},
set(val){
console.log(val);
this.txt = val;
}
} ,
}
})
app.mount('#app')
</script>
八侦听器
什么场景下需要侦听器
书写方法
//数据侦听
watch:{
num(newVal,oldVal){
let r = this.rand(0,255);
let g = this.rand(0,255);
let b = this.rand(0,255);
console.log(newVal,oldVal);
if (newVal%10==0) {
this.col =`rgb(${r},${g},${b})`
}
},
val(newVal,oldVal){
console.log(newVal,oldVal);
},
//设置侦听器的深度监听
obj:{
//设置监听的回调方法
handler(newVal,oldVal){
console.log(newVal,oldVal);
},
//设置深度监听
deep:true,
//设置加载立即监听
immediate:true
},
//监听对象中某一个属性的变化
//可通过此方法,直接监听路由对象的变化
'obj.name':{
//设置监听的回调方法
handler(newVal,oldVal){
console.log('监听名字的变化');
console.log(newVal,oldVal);
},
}
}
设置外部的侦听器
app.$watch('name',(newVal,oldVal)=>{
console.log(newVal,oldVal);
})
九生命周期
生命周期常用函数
相关代码
<body>
<div id="app">
<h1 id="abc">{{num}}</h1>
<button @click="num++">点击++</button>
<ul id="list">
<li v-for="(item,index) in arr" :key="index">{{item}}</li>
</ul>
<button @click="add">点击添加高端学府</button>
<button @click="die">销毁组件实例</button>
</div>
</body>
</html>
<script type="module">
import {createApp} from './js/vue.esm-browser.js';
let app=createApp({
data(){
return{
str:'中午吃啥',
num:100,
arr:['郑州大学','西亚斯学院','郑州科技学院']
}
},
//在组件实例初始化完成之后立即调用。此刻其他的属性和方法均没有执行或者编译
beforeCreate(){
console.log(this.str);
},
/*
在组件实例处理完所有与状态相关的选项后调用。当这个钩子被调用时,以下内容已经设置完成:响应式数据、计算属性、方法和侦听器。然而,此时挂载阶段还未开始,因此 $el 属性仍不可用。此时不能操作dom
*/
created(){
console.log('created',this.str);
let abc=document.querySelector('#abc');
console.log(abc);
this.num+=100;
},
/*
vue的组件模板,如果在实例中设置的有组件的模板,则会替换掉挂载的dom元素
模板的第一层需要是一个完整的dom元素(vue2版本)
*/
// template:`
// <h3>{{num}}</h3>
// <h2>{{str}}</h2>
// `
/*
在组件被挂载之前调用。此刻还没有挂载任何模板,因此还无法操作dom
*/
beforeMount(){
console.log('beforeMount');
},
/*
组件被挂之后调用。此时,所有的模板内容都已经被挂载,可以操作组件中所有的dom
常用此钩子函数来进行,加载立即执行的操作
*/
mounted(){
console.log('mounted');
this.show()
},
methods:{
show(){
let abc=document.querySelector('#abc');
console.log(abc);
abc.style.border='1px #f00 solid ';
},
add(){
this.arr.push('河南建筑职业技术学院');
},
die(){
//销毁vue实例
// this.$destroy();
//解绑/卸载vue实例
console.log(app);
app.unmount();
}
},
/*
beforeUpdate 钩子 数据更新前触发,显示的数据是更新后的数据
但是如果改变了dom结构,那么改函数中的dom结构是更新前的内容
*/
beforeUpdate(){
let list=document.querySelector('#list');
console.log('beforeUpdate',this.num,list.innerHTML);
},
/*
Update 钩子 数据更新后触发,显示的数据是更新后的数据
但是如果改变了dom结构,那么该函数中的dom结构是更新后的内容
*/
updated(){
console.log('updated',this.num,list.innerHTML);
},
/*
在一个组件实例被卸载之前调用。
*/
beforeUnmount(){
console.log('beforeUnmount');
},
/*
在一个组件实例被卸载之后调用。
*/
unmounted(){
log('unmounted');
},
});
//挂载
app.mount('#app');
</script>
十自定义属性
<body>
<div id="app">
<div v-aa="'#f0f'" class="wp"></div>
<div v-abc="col" class="wp">
<button @click="col='#000'">点击更新</button>
</div>
</div>
</body>
</html>
<script type="module">
import {createApp} from './js/vue.esm-browser.js'
createApp({
data() {
return {
col:'#0ff'
}
},
methods: {
},
//自定义指令
directives:{
/*
aa是指令名,
参数
el表示的是自定义指令绑定的元素
binding 是一个对象 包含是属性是
value 传递给指令的值。
oldValue 指令绑定的数据或者元素内部发生改变的值,
仅在beforeUpdate 和 updated中有值
*/
aa(el,binding){
console.log(el,binding);
el.onmouseenter=()=>{
el.style.background = '#f00'
}
el.onmouseleave=()=>{
el.style.background = binding.value
}
},
//配置指令
abc:{
created(el,binding) {
console.log('created',el,binding);
},
mounted(el,binding) {
el.onmouseenter=()=>{
el.style.background = '#f00'
}
el.onmouseleave=()=>{
el.style.background = binding.value
}
},
updated(el,binding) {
console.log('更新了',binding.oldValue);
el.onmouseleave=()=>{
el.style.background = binding.value
}
},
}
}
}).mount('#app')
十一组件
组件基础
注册组件
组件的命名
相关代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>组件基础</title>
<style>
*{
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div id="app">
<h1>{{name}}</h1>
<abc></abc>
<my-show></my-show>
<my-run></my-run>
</div>
</body>
</html>
<template id="run">
<h1>辛弃疾</h1>
<h2>柳永</h2>
<h2>{{name}}</h2>
</template>
<script type="module">
import {createApp} from './js/vue.esm-browser.js'
let app = createApp({
data() {
return {
name:'袁世凯'
}
},
//实例的内部注册组件
components:{
'myShow':{
template:'<p class="abc">最喜小儿无赖</p>',
data(){
return {
nme:'孙终末'
}
}
},
//w3c 推荐
'my-run':{
template:'#run',
data() {
return {
name:'原神启动'
}
},
}
}
})
//外部注册
app.component('abc',{
template:`
<h1>相顾无言,惟有泪千行</h1>
<h1>相顾无言,惟有泪千行</h1>
<h1>相顾无言,惟有泪千行</h1>
<h1>相顾无言,惟有泪千行</h1>
`
})
app.mount('#app')
</script>
外部组件配置
<body>
<div id="app">
<abc></abc>
<abc></abc>
</div>
</body>
</html>
<template id="abc">
<h1>郑州科技学院-郑科公园</h1>
<h1>我在郑科很想你{{num}}</h1>
<button @click="add">点击++</button>
</template>
<script type="module">
import { createApp } from './js/vue.esm-browser.js';
let abc = {
template:'#abc',
data(){
return {
num:100,
}
},
methods: {
add(){
this.num++;
},
mounted(){
this.add();
},
components:{
aa:{
template:'<h4>组件内部的</h4>'
}
}
},
}
createApp({
data() {
return {
};
},
components:{
abc:abc
}
}).mount('#app');
</script>
组件的属性
设置属性的具体类型,设置属性的多样性
props:{
abc:{
//设置属性abc的值,必须是一个字符串
type:String
},
设置默认属性
obj:{
type:Object,
//设置默认值,对象类型的默认值是一个函数,返回一个默认对象
default(){
return {
name:'燕青',
age:20
}
}
},
设置必读属性
aa:{
type:String,
//设置为必写属性
required:true,
//设置属性的默认值,当属性没有值的时候,默认显示的内容
default:'中午吃啥子'
}
十二组件传值
父传子
methods:{
change(){
//获取组件实例
console.log(this.$refs.son);
//执行组件实例中的方法
this.$refs.son.add();
this.$refs.wp.innerHTML=this.$refs.son.num;
}
}
完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ref</title>
<style>
*{
margin: 0;
padding: 0;
}
.wp{
width: 200px;
height: 200px;
background: #04be02;
}
</style>
</head>
<body>
<div id="app">
<show ref="son"></show>
<button @click="change">点击++</button>
<div class="wp" ref="wp"></div>
</div>
</body>
</html>
<template id="show">
<h2>{{num}}</h2>
</template>
<script type="module">
import { createApp } from './js/vue.esm-browser.js';
/*
组件中通过this.$refs 获取所有携带ref属性的子组件实例
this.$refs 是一个集合,this.$refs.aa 就可以获取 ref="aa" 的组件实例
*/
let show = {
data() {
return {
num:1,
}
},
template:'#show',
methods: {
add(){
this.num++;
}
},
}
createApp({
data() {
return {
}
},
components:{
show:show
},
methods:{
change(){
//获取组件实例
console.log(this.$refs.son);
//执行组件实例中的方法
this.$refs.son.add()
this.$refs.wp.innerHTML = this.$refs.son.num;
}
}
}).mount('#app')
</script>
子传父
解析
相关代码
<body>
<div id="app">
<h1>{{info}}</h1>
<button @click="">点击++</button>
<son @abc="changeInfo"></son>
</div>
</body>
</html>
<template id="son">
<div class="wp">
<h1>{{msg}}</h1>
<button @click="pass">点击传递给父组件</button>
<button @click="getFu">点击获取父组件</button>
</div>
</template>
<script type="module">
import {createApp} from './js/vue.esm-browser.js';
let son={
data(){
return{
msg:'道不轻传'
}
},
template:'#son',
methods:{
pass(){
// $emit 在当前组件触发一个自定义事件。任何额外的参数都会传递给事件监听器的回调函数。
this.$emit('abc',this.msg);
},
//通过获取父组件的实例传递数据
getFu(){
// this.$parent.changeInfo(this.msg);
this.$root.changeInfo(this.msg);
}
}
};
createApp({
data(){
return{
info:'稻香'
}
},
components:{
son
},
methods:{
changeInfo(data){
console.log('触发方法',data);
this.info=data;
}
}
}).mount('#app');
</script>
非父子传值
<body>
<div id="app">
<h1>摇滚不死</h1>
<son1></son1>
<son2></son2>
</div>
</body>
</html>
<template id="son1">
<div class="son1">
<h2>子组件1</h2>
<h4>{{msg}}</h4>
<button @click="pass">点击传递给子组件2</button>
</div>
</template>
<template id="son2">
<div class="son2">
<h2>子组件2</h2>
<h4>{{info}}</h4>
</div>
</template>
<!-- 引入 mitt 插件 的js -->
<script src="https://unpkg.com/mitt/dist/mitt.umd.js"></script>
<script type="module">
import { createApp } from './js/vue.esm-browser.js';
//引入mitt实例
let bus = mitt();
console.log( bus );
//声明两个组件
let son1 = {
template:'#son1',
data(){
return {
msg:'假行僧'
}
},
methods: {
pass(){
//执行 mitt 实例中的 emit() 方法,来触发自定义事件 并且 传递参数
bus.emit('abc', this.msg);
}
},
};
let son2 = {
template:'#son2',
data(){
return {
info:'一块红布'
}
},
mounted() {
//执行 mitt 实例中的 on() 方法,来监听 自定义事件是否被触发,如果被触发,则执行回调函数
//回调函数默认传入一个参数,该参数的值即为 通过 emit 触发事件传递的数据
bus.on('abc',data=>{
this.info = data;
});
},
};
createApp({
data(){
return {
}
},
components:{
son1:son1,
son2:son2
}
}).mount('#app');
</script>
provide和inject
</head>
<body>
<div id="app">
<h1>{{str}}</h1>
<zi />
</div>
</body>
</html>
<template id="zi">
<div class="wp">
<h1>子组件</h1>
<p>{{msg}}</p>
<sun></sun>
</div>
</template>
<template id="sun">
<div class="wp">
<h1>孙组件</h1>
<p>{{msg}}</p>
</div>
</template>
<script type="module">
import { createApp } from './js/vue.esm-browser.js';
let sun = {
template:'#sun',
//通过inject 直接接收 provide 传递的数据
inject:['msg']
}
let zi = {
template:'#zi',
components:{
sun
},
inject:['msg']
};
createApp({
data() {
return {
str:'却惹六千烦恼丝'
}
},
//配置直接传入后代的值
// provide:{
// msg:'却惹三千烦恼丝',
// },
//如果直接获取 data 中的数据作为传递到后代组件的数据,则使用函数的形式返回数据
provide(){
return{
msg:this.str
}
},
components:{
zi
}
}).mount('#app')
</script>
十三动态组件
<body>
<div id="app">
<div class="wp">
<span :class="num==1&&'on'" @click="num=1">水浒传</span>
<span :class="num==2&&'on'" @click="num=2">红楼梦</span>
<span :class="num==3&&'on'" @click="num=3">西游记</span>
<span :class="num==4&&'on'" @click="num=4">三国演义</span>
</div>
<!-- <comp1 v-if="num==1"></comp1>
<comp2 v-if="num==2"></comp2>
<comp3 v-if="num==3"></comp3>
<comp4 v-if="num==4"></comp4> -->
<!--
动态组件 使用标签 component
该组件具有一个is属性,is属性的值 是 要渲染组件的名字,即为is属性的值是哪一个组件名,
component 标签就会渲染哪一个组件
缺点:component 可以动态渲染组件的内容,但是每一个切换,都会重新渲染组件内容,降低渲染效率
使用keep-alive 标签(组件),可以缓存曾经渲染过的组件,从而提高渲染效率
-->
<keep-alive>
<component :is="'comp'+num"></component>
</keep-alive>
</div>
</body>
</html>
<script type="module">
import { createApp } from './js/vue.esm-browser.js';
let comp1={
template:'<h1>水浒传</h1>'
}
let comp2={
template:'<h1>红楼梦</h1>'
}
let comp3={
template:`
<h1>西游记</h1>
<p>{{n}}</p>
<button @click = "n++">点击++</button>
`,
data() {
return {
n:100,
}
},
}
let comp4={
template:'<h1>三国演义</h1>'
}
let aa = {
template:'<h1>金瓶梅</h1>'
}
createApp({
data() {
return {
num:1,
}
},
components:{
comp1,comp2,comp3,comp4,aa
}
}).mount('#app')
</script>
十四插槽
<body>
<div id="app">
<son1>
<h2>一夫当关,鸡犬升天</h2>
<p>我爱云和</p>
</son1>
<son2>
<template v-slot:header>
<h3 slot="header">一人得道鸡犬升天</h3>
</template>
<p>芶使郑州</p>
<p>鸡你太美</p>
<p>鸡你太美</p>
<p>鸡你</p>
<template #footer>
<h3>风吹草低见牛羊</h3>
</template>
<hr>
<son3>
<template #[dog]>
<h3>一人得道鸡犬升天</h3>
</template>
<button @lick="dog='footer'">点击修改插槽的值</button>
</son3>
</son2>
</div>
</body>
</html>
<template id="son1">
<slot></slot>
<h1>一眼碗面</h1>
</template>
<template id="son2">
<slot></slot>
<h1>方便面</h1>
<slot></slot>
<slot name="footer"></slot>
</template>
<template id="son3">
<slot name="footer">
<h1>中午吃啥</h1>
</slot>
</template>
<script type="module">
import { createApp } from './js/vue.esm-browser.js';
let son1 ={
template:'#son1'
}
let son2={
template:'#son2'
}
let son3={
template:'#son3'
}
createApp({
data() {
return {
dog:'header'
}
},
components:{
son1,son2,son3
}
}).mount('#app')
</script>
十五过渡动画
设置过渡的流程
过度动画的应用场景
相关代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>过度动画</title>
<style>
*{
margin: 0;
padding: 0;
}
.wp{
width: 200px;
height: 200px;
background: pink;
}
.aa-enter-active,
.aa-leave-active {
transition: opacity 1s ease;
}
.aa-enter-from,
.aa-leave-to {
opacity: 0;
}
.list-enter-active,
.list-leave-active {
transition: all 0.5s ease;
}
.list-enter-from,
.list-leave-to {
opacity: 0;
transform: translateX(30px);
}
</style>
</head>
<body>
<div id="app">
<transition name="aa">
<div class="wp" v-show="bol"></div>
</transition>
<button @click="bol=!bol">点击</button>
<hr>
<!--
设置动画组
-->
<transition-group name="list" tag="ul">
<li v-for="(n,index) in arr" :key="index">{{n}}</li>
</transition-group>
<button @click="arr.push('前端开发')">点击添加</button>
</div>
</body>
</html>
<script type="module">
/*
设置过渡的流程
1,把需要使用过渡的动画的元素使用 transition 组件包裹起来
2.给transition 组件设置一个name属性
3.给name属性的值,设置过渡动画
4.控制元素或者组件的显示或者隐藏
transition-group 组件,常用来操作一系列数据,他具有一个tag属性,可以把当前的transition-group组件
渲染为tag属性设置的html标签
过度动画的应用场景
1.结合 v-if 使用
2.结合 v-show 使用
3.结合 路由切换 使用
*/
import { createApp } from './js/vue.esm-browser.js';
createApp({
data() {
return {
bol:true,
arr:['java','c++','ui设计','php']
}
},
}).mount('#app')
</script>