Vue学习:模板语法
<!DOCTYPE html>
<html lang="zh-cn">
<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">
<script type="text/javascript" src="js/vue.js"></script>
<title>vue练习</title>
<style>
</style>
</head>
<body>
<div id="root">
<!-- 准备一个容器-->
<!-- <h1>hello,尚硅谷</h1>-->
<!-- hello是死的,但是想要'尚硅谷是活动的数据,就要借用vue了,就省去了DOM操作'-->
<h1>hello,{{name}}</h1>
<!-- {{}}是一种对象分隔符-->
<hr/>
<h1>指令语法</h1>
<a v-bind:href="url">点击我</a>
<!-- 动态变量,使用v-bind指定变量,会将引号中的变量拿出来当成JS中的使用-->
<!-- v-bind可以简写为:,就是冒号-->
单项数据绑定:<input type="text" v-bind:value="name">
双向数据绑定:<input type="text" v-model:value="name">
<!-- 单项数据就是只能通过JS传出数据,双向则是输入框也能传数据到JS中-->
<!-- 对于v-model只能给表单用,即只能给有value值的用-->
</div>
<script type="text/javascript">
Vue.config.productionTip = false //阻止vue在启动时生产提示
//创建Vue实例
new Vue({
el:'#root',
//el用于指定当前Vue实例为哪个容器服务,值通常为css选择器字符串,比如class用.root
data:{//创建一个数据对象,数据供el指定的容器所使用
name:'尚硅谷',
url:'http://www.baidu.com'
}
})
</script>
</body>
</html>
Vue——回顾Object.defineproperty方法
<!DOCTYPE html>
<html lang="zh-cn">
<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">
<script type="text/javascript" src="js/vue.js"></script>
<title>回顾Object.defineproperty方法</title>
<style>
</style>
</head>
<body>
<script type="text/javascript">
let num = 18;//再结合下面的age,就能变成动态更改的
let person = {
name:'张三',
sex:'男',
//age:18
}
Object.defineProperty(person,'age',{//这样写可以更方便的更改person对象中的age
// value:18,
// enumerable:true,//控制属性是否可以枚举,默认为false
// writable:true,//控制属性是否可以被修改
// configurable:true //控制属性是否可以被删除
//当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值
get:function (){
return num
},
//当有人修改person的age属性时,set函数(setter)就会被调用,且会收到修改的具体值
set(value){
num = value;
}
})
</script>
</body>
</html>
Vue事件处理
<!DOCTYPE html>
<html lang="zh-cn">
<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">
<script type="text/javascript" src="js/vue.js"></script>
<title>Vue事件处理</title>
<style>
</style>
</head>
<body>
<div class="root">
<h2>欢迎来到{{name}}学习</h2>
<button v-on:click="showInfo">点我显示提示</button>
<!-- 对于提示的Vue事件,事件都是v-开头,点击用v-on:click-->
<button v-on:click="showInfo2(66,$event)">点我显示提示</button>
<!-- 这样能够传参66到vue的事件中,$event是关键字,这样写可以防止event丢失-->
</div>
<script type="text/javascript">
new Vue({
el:'.root',
data:{
name:'尚硅谷',
},
methods:{ //vue绑定的事件写在Vue里面,且用methods方法来存放
showInfo(){
alert('同学你好')
},
showInfo2(num,a){//a接收event参数
console.log(num,a);//用num来接收参数
}
}
})
</script>
</body>
</html>
Vue阻止冒泡等
<div class="root">
<h2>欢迎来到{{name}}学习</h2>
<a href="http://www.baidu.com" @click.prevent = "showInfo">点我提示信息</a>
<!-- 阻止事件冒泡(常用)-->
<div class="demo1" @click="showInfo">
<a href="http://www.baidu.com" @click.stop.prevent="showInfo"></a>
<!-- 对于阻止也能连用,先停止冒泡,再阻止默认行为(比如自动跳转什么的) -->
</div>
</div>
Vue键盘事件
<!DOCTYPE html>
<html lang="zh-cn">
<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">
<script type="text/javascript" src="js/vue.js"></script>
<title>Vue键盘事件</title>
<style>
</style>
</head>
<body>
<div class="root">
<h2>欢迎来到{{name}}学习</h2>
<input type="text" placeholder="按下回车提示" @keyup.enter="showInfo">
<!-- 对于由两个单词组成的键,比如CapsLock,需要小写,且用分隔符隔开,写成caps-lock -->
<!-- 并不是所有键都能被绑定事件,可以看上图的一些常用键-->
<!-- 对于tab键盘,比较特殊,必须配合keydown使用-->
</div>
<script type="text/javascript">
new Vue({
el:'.root',
data:{
name:'尚硅谷',
},
methods:{ //vue绑定的事件写在Vue里面,且用methods方法来存放
showInfo(e){
console.log(e.target.value)
}
}
})
</script>
</body>
</html>
姓名案例-计算属性、插入语法实现、method实现
<!DOCTYPE html>
<html lang="zh-cn">
<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">
<script type="text/javascript" src="js/vue.js"></script>
<title>姓名案例</title>
<style>
</style>
</head>
<body>
<!--插值语法使用-->
<div class="root">
姓:<input type="text" v-model:value="firstname"> <br/><br/>
名:<input type="text" v-model:value="lastname"> <br/><br/>
姓名:<span>{{fullName}}</span>
</div>
<script type="text/javascript">
const vm = new Vue({
//数据代理,需要查看,可以在控制台中输入vm查看整个,查个个别属性可以输入vm._data.firstname
el:".root",
data:{
firstname:'张',
lastname:'三',
},
computed:{//对于计算属性,用新的配置方法,computed
fullName:{
//get的作用:当有人读取fullName时,get就会被调用,且返回值就会作为fullName的值
//get方法负责读取,且会留有缓存,如果想要更改数据,就要使用set()
get(){
return this.firstname + this.lastname;
},
set(value){//当fullName被修改时,使用set
const arr = value
this.firstname = arr[0]
this.firstname = arr[1]
}
}
}//计算属性中的属性不是直接在vm中可以被调到的
})
</script>
</body>
</html>
天气案例——监视属性
<!DOCTYPE html>
<html lang="zh-cn">
<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">
<script type="text/javascript" src="js/vue.js"></script>
<title>天气案例-监视属性</title>
<style>
</style>
</head>
<body>
<!--
监视属性watch:
1.当被监视的属性变化时,回调函数自动调用,进行相关操作
2.监视的属性必须存在,才能进行监视!!
3.监视的两种写法:
(1)new Vue时传入watch配置
(2)通过vm.$watch监视
-->
<div class="root">
<h2>今天天气很好</h2>
<button @click="changeWeather">切换天气</button>
</div>
<script type="text/javascript">
const vm = new Vue({
el:".root",
data:{
isHot:true
},
computed:{
info()
{
return this.isHot ? '炎热' : '凉爽'
}
},
methods:{
changeWeather(){
this.isHot = !this.isHot;
}
},
// watch:{
// immediate:true,//初始化时让handler调用一下
// isHot: {
// //handler什么时候调用?当isHot发生改变时
// handler(newValue,oldValue){
// console.log(123)
// }
// }
// }
})
vm.$watch('isHot',{ //保证vm实例对象已经被创建
isHot: {
//handler什么时候调用?当isHot发生改变时
handler(newValue,oldValue){
console.log(123)
}
}
})
</script>
</body>
</html>
监视属性扩展——深度监视
<!DOCTYPE html>
<html lang="zh-cn">
<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">
<script type="text/javascript" src="js/vue.js"></script>
<title>天气案例-监视属性</title>
<style>
</style>
</head>
<body>
<!--
-->
<div class="root">
<h2>今天天气很好</h2>
<button @click="changeWeather">切换天气</button>
<hr/>
<h3>a的值是:{{numbers.a}}</h3>
<button @click="numbers.a++">点我给a++</button>
<h3>b的值是:{{numbers.b}}</h3>
<button @click="numbers.b++">点我给b++</button>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
const vm = new Vue({
el:".root",
data:{
isHot:true,
numbers:{
a:1,
b:2
}
},
computed:{
info()
{
return this.isHot ? '炎热' : '凉爽'
}
},
methods:{
changeWeather(){
this.isHot = !this.isHot;
}
},
watch:{ //监视isHot的属性
immediate:true,//初始化时让handler调用一下
isHot: {
handler(){
console.log('isHot被改变了')
}
},
//监视多级结构中某个属性的变化
//这里就是单独检测numbers中a的变化
'numbers.a':{
handler(){
console.log('a被改变了')
}
},
//监视多级结构中所有属性的变化
numbers:{
deep:true,//开启深度默认项
handler(){
console.log('numbers改变了')
}
}
}
})
</script>
</body>
</html>
姓名案例——watch实现(侦听属性)
computed与watch对比
<!DOCTYPE html>
<html lang="zh-cn">
<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">
<script type="text/javascript" src="js/vue.js"></script>
<title>天气案例-watch实现</title>
<style>
</style>
</head>
<body>
<!--
-->
<div class="root">
姓:<input type="text" v-model="firstName">
名:<input type="text" v-model="lastName">
全名:<span>{{fullName}}</span>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
const vm = new Vue({
el:".root",
data:{
firstName:'张',
lastName:'三',
fullName:'张-三'
},
computed:{
},
//实现watch
watch: {
//watch中可以写延时,是因为watch不用返回值实现
// 对于异步计算,computed计算属性,写延时不能得到返回值,则选择watch
firstName(newValue){//监视姓
//不需要深度监视的时候,就能写成一个函数来简写
setTimeout(()=>{//设置一个延时,1s后才会同步显示
this.fullName = newValue + '-' + this.lastName
//全名=最新的姓 + 原来的名字
},1000);
},
lastName(newValue){//监视名字
//不需要深度监视的时候,就能写成一个函数来简写
this.fullName = this.firstName + '-' + newValue
//全名=原来的姓 + 最新的名字
},
}
})
</script>
</body>
</html>
使用Vue绑定class样式
<!DOCTYPE html>
<html lang="zh-cn">
<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">
<script type="text/javascript" src="js/vue.js"></script>
<title>绑定样式</title>
<style>
.basic {
width: 400px;
height: 100px;
border: 1px solid black;
}
.happy {
background-color: #da5555;
}
.normal {
background-color: #1ba1e6;
}
.sad {
background-color: #666666;
}
.atguigu1 {
background-color: #40b83f;
}
.atguigu2 {
color: #b1191a;
}
.atguigu3 {
font-size: 18px;
}
</style>
</head>
<body>
<!--
-->
<!-- 使用Vue实现样式替换的效果-->
<div class="root">
<!-- 这是正常情况下写的样式绑定<div class="basic normal" @click="changeMood">-->
<div class="basic" :class="mood" @click="changeMood">
<!-- 使用Vue写绑定的样式,需要绑定的写为 :class="xxx" -->
<!-- 这种方式适用于,样式的类名不确定,需要动态指定的情况 -->
{{name}}
</div>
<!-- 另外一种写法 -->
<!-- 绑定class样式,数组写法,适用于:要绑定的样式个数不确定,名字也不确定的情况下-->
<div class="basic" :class="arr" @click="changeMood">
{{name}}
</div>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
const vm = new Vue({
el:".root",
data:{
name:'嗨喽',
mood:'normal',
arr:['atguigu1','atguigu2','atguigu3']
},
methods:{
changeMood(){
//改变样式,有三个样式,可以写为数组
const arr = ['happy','sad','normal']
//设定随机生成0,1,2三个数组中的一个
const index = Math.floor(Math.random()*3)
//随机数函数,随机数的取值是从0到无限接近于1
//让随机数乘以3后,向下取整,就变成0到无限接近于3
this.mood = arr[index]
}
}
})
</script>
</body>
</html>
条件渲染
<!DOCTYPE html>
<html lang="zh-cn">
<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">
<script type="text/javascript" src="js/vue.js"></script>
<title>条件渲染</title>
<style>
</style>
</head>
<body>
<!--
-->
<div class="root">
<!-- 这是正常情况下写的样式绑定<div class="basic normal" @click="changeMood">-->
<!-- 使用v-show做条件渲染,页面不显示,但是结构框架还在 -->
<!-- <h2 v-show="false">欢迎来到{{name}}</h2>-->
<!-- <h2 v-show="1 === 1">欢迎来到{{name}}</h2>-->
<!-- 使用v-if做条件渲染,结构框架也会被消掉 -->
<!-- 在使用v-if时,几个标签要紧挨一起,不能在中间被其他不是if的标签打断-->
<!-- template只能与v-if配合使用,不能与show用 -->
<!-- <h2 v-if="false">欢迎来到1{{name}}</h2>-->
<!-- <h2 v-else-if="1 === 1">欢迎来到2{{name}}</h2>-->
<!-- <h2 v-else>欢迎来到3{{name}}</h2>–>-->
<h2>当前n的值是:{{n}}</h2>
<button @click="n++">点我n+1</button>
<!-- 根据n值来判断当前应该显示什么-->
<div v-show="n === 1">a</div>
<div v-show="n === 2">b</div>
<div v-show="n === 3">c</div>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
const vm = new Vue({
el:".root",
data:{
name:'嗨喽',
n:0
},
})
</script>
</body>
</html>
列表渲染
基本列表
<!DOCTYPE html>
<html lang="zh-cn">
<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">
<script type="text/javascript" src="js/vue.js"></script>
<title>列表渲染——基本列表</title>
<style>
</style>
</head>
<body>
<!--
-->
<div class="root">
<!-- v-for进行循环渲染
在不确定的情况下,可以先不写出key,先写v-for="(a,b) of car"
当运行后得到a与b是对应什么数据了,再将key写出
-->
<!-- p是一个形参,可以直接在li中使用,插值语法{{p}}可以得到persons中的所有值-->
<!-- {{p.name}}得到姓名,其他亦是如此-->
<h2>人员信息</h2>
<li v-for="p in persons" :key="p.id">
{{p.name}}-{{p.age}}
</li>
<!-- v-for还能遍历对象,写法如下-->
<h2>汽车信息</h2>
<li v-for="(value,k) of car" :key="k">
{{k}}-{{value}}
<!-- 页面中将会得到:
name-奥迪
price-70万
color-黑色
则key所对应为car中的声明,也可以对应id
-->
</li>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
const vm = new Vue({
el:".root",
data:{
persons:[
{id:'001',name:'张三',age:18},
{id:'002',name:'李四',age:19},
{id:'003',name:'王五',age:20},
],
car:{
name:'奥迪',
price:'70万',
color:'黑色'
}
},
})
</script>
</body>
</html>
key的原理
<!DOCTYPE html>
<html lang="zh-cn">
<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">
<script type="text/javascript" src="js/vue.js"></script>
<title>列表渲染——key的原理</title>
<style>
</style>
</head>
<body>
<!--
-->
<div class="root">
<h2>人员信息(遍历数组)</h2>
<button @click.once="add">添加一个老刘</button>
<li v-for="(p,index) in persons" :key="p.id">
<!-- 在此处,因为将新生成的数据放到最上面,所以key中写index会影响效率,输入的缓存会导致错乱
使用p.id则不会-->
{{p.name}}-{{p.age}}
<input type="text">
</li>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
const vm = new Vue({
el:".root",
data:{
persons:[
{id:'001',name:'张三',age:18},
{id:'002',name:'李四',age:19},
{id:'003',name:'王五',age:20},
],
},
methods:{
add(){
const p ={id:'004',name:'老刘',age:40}
this.persons.unshift(p)
}
}
})
</script>
</body>
</html>
对于第3点的详细解释,当逆序添加时,使用index,会导致顺序错乱。
如下图 ,新添加的老刘的key为0,会和初始的数据中key为0的对比后,复合到一起。
而使用id的话,key值就会是一一对应的,新生成的老刘key为4,在初始数据中并没有key为4的,则不需要对比,直接生成新的空白输入框
列表过滤
<!DOCTYPE html>
<html lang="zh-cn">
<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">
<script type="text/javascript" src="js/vue.js"></script>
<title>列表渲染——列表过滤</title>
<style>
</style>
</head>
<body>
<!--
类似于模糊搜索
-->
<div class="root">
<h2>人员信息</h2>
<input type="text" placeholder="请输入要查找的关键字" v-model="keyWord">
<ul>
<li v-for="(p,index) in filPersons" :key="index">
{{p.name}}-{{p.age}}-{{p.sex}}
</li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
//用watch监视来实现
// const vm = new Vue({
// el: ".root",
// data: {
// keyWord: '',
// persons: [//原数组
// {id: '001', name: '马冬梅', age: 18, sex: '女'},
// {id: '002', name: '周冬雨', age: 19, sex: '女'},
// {id: '003', name: '周杰伦', age: 20, sex: '男'},
// {id: '003', name: '温兆伦', age: 22, sex: '男'},
// ],
// //定义一个新数组,可以用来保存过滤的数组
// filPersons: []
// },
// // watch监视
// watch: {
// keyWord:{
// immediate:true,
// handler(val){
// //将所有名字中包含val的过滤出来显示
// this.filPersons = this.persons.filter((p) => {
// //filter会过滤掉不需要的,然后生成一个新的数组,不要用新的覆盖原数组,会导致原数组消失
// return p.name.indexOf(val) !== -1
// //indexOf包含会返回-1,不包含会返回0
// })
// }
// }
// }
// })
//用computed实现
new Vue({
el: ".root",
data: {
keyWord: '',
persons: [//原数组
{id: '001', name: '马冬梅', age: 18, sex: '女'},
{id: '002', name: '周冬雨', age: 19, sex: '女'},
{id: '003', name: '周杰伦', age: 20, sex: '男'},
{id: '003', name: '温兆伦', age: 22, sex: '男'},
],
},
computed:{//计算属性
filPersons(){
return this.persons.filter((p)=>{
return p.name.indexOf(this.keyWord) !== -1
})
}
}
})
</script>
</body>
</html>
列表排序
<!DOCTYPE html>
<html lang="zh-cn">
<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">
<script type="text/javascript" src="js/vue.js"></script>
<title>列表渲染——排序</title>
<style>
</style>
</head>
<body>
<!--
类似于模糊搜索
-->
<div class="root">
<h2>人员信息</h2>
<input type="text" placeholder="请输入要查找的关键字" v-model="keyWord">
<button @click="sortType = 2">年龄升序</button>
<button @click="sortType = 1">年龄降序</button>
<button @click="sortType = 0">原顺序</button>
<ul>
<li v-for="(p,index) in filPersons" :key="index">
{{p.name}}-{{p.age}}-{{p.sex}}
</li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el: ".root",
data: {
keyWord: '',
sortType:0,//0代表原顺序,1降序,2升序
persons: [//原数组
{id: '001', name: '马冬梅', age: 18, sex: '女'},
{id: '002', name: '周冬雨', age: 23, sex: '女'},
{id: '003', name: '周杰伦', age: 19, sex: '男'},
{id: '003', name: '温兆伦', age: 22, sex: '男'},
],
},
computed:{
//过滤与排序不分家
//这里改动了filPersons,原数组persons未被改动,所以能够回到原顺序
filPersons(){
const arr = this.persons.filter((p)=>{
return p.name.indexOf(this.keyWord) !== -1
})
//判断是否需要排序
if(this.sortType !==0 ){
arr.sort((p1,p2)=>{///拿过滤完的数组的进行排序
return this.sortType === 1 ? p2.age-p1.age : p1.age-p2.age
})
}
return arr
}
}
})
</script>
</body>
</html>
Vue.set()方法添加响应式属性
<!DOCTYPE html>
<html lang="zh-cn">
<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">
<script type="text/javascript" src="js/vue.js"></script>
<title>Vue.set()方法</title>
<style>
</style>
</head>
<body>
<!--
类似于模糊搜索
-->
<div class="root">
<h1>学校信息</h1>
<h2>学校名称:{{name}}</h2>
<h2>学校地址:{{address}}</h2>
<hr/>
<h1>学生</h1>
<button @click="addSex">添加一个性别属性,默认为男</button>
<h2>姓名:{{student.name}}</h2>
<h2>性别:</h2>
<!-- 要动态添加,通过Vue后台添加性别属性,可以使用Vue.set()方法 -->
<!-- 具体使用是,在控制台输入Vue.set(targer,key,val)-->
<!-- 此处则输入是Vue.set(vm._data.student,'sex','男'),这样插入的值就是响应式的数据,会自动生成set和get-->
<!-- 还能通过控制台添加,即vm.$set(vm._data.student,'sex','女')-->
<!-- 在数据代理中,vm._data.student === vm.student-->
<h2>年龄:真实{{student.age.rAge}},对外{{student.age.sAge}}</h2>
<h2>朋友们</h2>
<ul>
<li v-for="(f,index) in student.friends" :key="index">
{{f.name}}--{{f.name}}
</li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
const vm = new Vue({
el: ".root",
data: {
name:'尚硅谷',
address:'北京',
student:{
//set添加响应式数据,不能直接给data中添加,只能给data中的某个对象中添加
//比如这里只能给student或者age,friedns中添加,不能添加与name,address同级的
name: 'tom',
age:{
rAge:40,
sAge:29,
},
friends:[
{name:'jerry',age:35},
{name:'tony',age:36}
]
}
},
methods:{
// methods中的方法中的属性,this就等于vm,在正常写情况下
addSex(){
Vue.set(this.student,'sex','男')
// this.$set(this.student,'sex','男')
//两种都可以
}
}
})
</script>
</body>
</html>
收集表单数据
<!DOCTYPE html>
<html lang="zh-cn">
<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">
<script type="text/javascript" src="js/vue.js"></script>
<title>收集表单数据</title>
<style>
</style>
</head>
<body>
<!--
v-model.number是让收集到的信息为数字
v-model.lazy让数据不是实时收集,当用户点击输入下一条框时,才收集当前条
v-model.trim收集时,自动去掉前后的空格
-->
<div class="root">
<form @submit.prevent="demo">
<!-- 阻止表单提交默认跳转页面行为,也就是阻止刷新-->
账号:<input type="text" v-model="account"> <br/><br/>
密码:<input type="password" v-model="password"> <br/><br/>
年龄:<input type="number" v-model.number="age"> <br/><br/>
<!-- 年龄中type="number"是原生控制不能让输入框输入不是年龄的-->
<!-- v-model.number="age"能够让接收到的信息是数字-->
性别:
男<input type="radio" name="sex" v-model="sex" value="male">
<!-- 在性别中添加value,就能让选上的值传入Vue中,传入的是male或female-->
女<input type="radio" name="sex" v-model="sex" value="female"> <br/><br/>
爱好:
学习<input type="checkbox" v-model="hobby" value="study">
<!-- 不配置value值,就会默认传入全部的值checked-->
打游戏<input type="checkbox" v-model="hobby" value="game">
睡觉<input type="checkbox" v-model="hobby" value="sleep"> <br/><br/>
所属校区
<select v-model="city">
<option value="">请选择校区</option>
<option value="beijing" >北京</option>
<option value="shanghai" >上海</option>
<option value="shenzhen" >深圳</option>
</select>
<br/><br/>
其他信息:
<textarea v-model="other"></textarea>
<br/><br/>
<input type="checkbox" v-model="agree">阅读并接受<a href="#">《阅读协议》</a>
<br/><br/>
<button>提交</button>
</form>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
const vm = new Vue({
el: ".root",
data: {
// userInfo:{
account:'',
password:'',
sex:'male',//这样可以一打开就有默认选好的
hobby:[],//hobby的初始值会影响传入数据
//如果多组勾选框,应该使用数组形式
city:'',
other:'',
agree:'',
age:''
// }
},
methods:{
demo(){
// console.log(JSON.stringify(this.userInfo))
//此方法需要在上方代码的v-model前添加userInfo,变成userInfo.v-model
//使用以下方法可以不需要添加,但一般不会直接写data
console.log(JSON.stringify(this._data))
}
}
})
</script>
</body>
</html>
内置指令
对于v-text,它会解析Vue的data中传来的所有,包括标签,都会解析为字符串,同时在里面再写你好之类的,都不会显示, 会被吞掉
自定义指令
<!DOCTYPE html>
<html lang="zh-cn">
<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">
<script type="text/javascript" src="js/vue.js"></script>
<title>自定义指令</title>
<style>
</style>
</head>
<body>
<!--
-->
<div class="root">
<h2>当前的n值是:<span v-text="n"></span> </h2>
<h2>放大10倍后的n值是:<span v-big="n"></span> </h2>
<button @click="n++">点我n+1</button>
<hr/>
<input type="text" v-fbind:value="n">
<!-- 此处的fbind为自定义指令,获取焦点,即光标一进来就在输入框,或者输入框中就有值-->
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
const vm = new Vue({
el: ".root",
data: {
n:1
},
directives:{
//big函数被调用条件,1.指令与元素成功绑定时2.指令所在的模板被重新解析时
big:function (element,binding){
element.innerHTML = binding.value*10
},
fbind:{//将fbind写成一个对象
//按照该顺序来调用
bind(element,binding){//指令与元素成功绑定时调用
element.value = binding.value
},
inserted(element,binding){//指令所在元素被插入页面时
element.focus()//获取焦点
},
update(element,binding){//指令所在的模板被重新解析时
element.value = binding.value
}
}
}
})
</script>
</html>
生命周期
引出生命周期,认识什么是生命周期函数
像钩子一样,需要用什么函数的时候,就用钩子钩出什么函数
<!DOCTYPE html>
<html lang="zh-cn">
<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">
<script type="text/javascript" src="js/vue.js"></script>
<title>引出生命周期</title>
<style>
</style>
</head>
<body>
<!--
-->
<div class="root">
<h2 :style="{opacity}">欢迎</h2>
<!-- 透明度样式-->
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
const vm = new Vue({
el: ".root",
data: {
opacity:1
},
methods:{
},
//认识生命周期函数,如下mounted就是,在特殊时间点被调用的函数
//Vue完成模板的解析并把真实的DOM元素放入页面后(完成挂载)调用mounted
//挂载,是第一次就在页面显示的,后面才出现的是更新
mounted(){
setInterval(()=>{//定时器
this.opacity-=0.01
if(this.opacity<=0)this.opacity=1
},16)
}
})
</script>
</html>
组件化编程
非单文件组件
基本使用
<!DOCTYPE html>
<html lang="zh-cn">
<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">
<script type="text/javascript" src="js/vue.js"></script>
<title>非单文件组件_基本使用</title>
<style>
</style>
</head>
<body>
<!--
-->
<div class="root">
<!-- 第三步,编写组件标签-->
<!-- 这样写,组件可以复用,很方便-->
<xuexiao></xuexiao>
<hr/>
<xuesheng></xuesheng>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
//第一步,组件创建
//创建school组件,这里的school只是一个中转的变量,也可以定义为a、b啥的
const school = Vue.extend({
//el: ".root",组件定义时,不要写el,data会对应给school组件
template:`
<div>
<h2>学校名称:{{schoolName}}</h2>
<h2>学校地址:{{address}}</h2>
</div>
`,
data(){
return {
schoolName:'尚硅谷',
address:'北京'
}
},
})
//创建student组件
const student = Vue.extend({
//el: ".root",组件定义时,不要写el,data会对应给school组件
template:`
<div>
<h2>学生姓名:{{studentName}}</h2>
<h2>学生年龄:{{age}}</h2>
</div>
`,
data(){
return {
studentName:'小红',
age:18
}
},
})
//创建vm
new Vue({
el:'.root',
//第二部,注册组件
//局部注册
components:{
//这里的xuexiao这些才是组件名称
xuexiao:school,
xuesheng:student
}
})
</script>
</html>
在写子组件的时候,需要将子组件放在父组件上面
1.实例的隐式对象属性,永远指向实例缔造者的原型对象
2.vc是这里自己取的名字,它其实是一个相对于vm差一点的小型实例对象
单文件组件
需要在脚手架中运行,才能得到支持
创建文件为:
1.index.html 主要的框架文件,必须有
2.main.js 让vue组件文件与html相连接交互的文件,必须有
3.App.vue 汇总所有组件的文件,必须要有
4.school.vue 组件文件,要继续写更多,就改名,比如student.vue等
2.main.js
import App from "./App.vue";
new Vue({
el:'.root',
components:{App},
})
//还需要一个最终的容器文件,html
//在html中的最下方写,<script type="text/javascript" src="./main.js"></script>来引入文件
//然后在html的div class=root中写<App><App/>
3.App.vue
<!--在这里,需要引入别处的vue组件文件-->
<!--app.vue的作用是汇总组件-->
<!--还需要创建对应的js文件,可以命名为main.js,或者index.js-->
<template>
<div>
<school></school>
</div>
</template>
<script>
//引入组件
import school from "./school.vue";
import School from "./school.vue";
export default {//默认导出
name:'App',
components: {School},
computeds:{//注册
school
}
}
</script>
<style>
</style>
4.school.vue
<!--单文件组件-->
<!--写单文件组件时,创建完所需的xxx.vue文件后,必须要有一个文件,app.vue-->
<template>
<!-- 组件的结构-->
<!-- 这里按照原来的html写-->
</template>
<script>
//组件交互相关的代码(数据、方法等)
//在这里,其他地方,数据,方法是一样的写,但是开头需要有export引入(暴露)
export default {//默认导出
name:'school',
data(){
return {
name:'尚硅谷',
address:'北京'
}
},
methods:{
show(){
alert(this.name)
}
}
}
</script>
<style>
/*组件的样式*/
/* 此处样式也是按照原来的html写*/
</style>
<!-- .vue文件中仅支持这些标签 -->
脚手架
首先需要安装nodejs,然后将npm路径改成淘宝镜像
再安装脚手架,即vue官网中的vue CIL,文档说明中有写输入什么进行安装
在cmd中选一个文件夹路径,桌面也可以,然后输入vue create xxx(这里的xxx是项目的名称)
选择版本,创建完成后,然后在cmd的文件夹中输入npm run serve来运行
之后会显示两个地址,可以将地址给其他人一起用