快速入门
<body>
<!--老师解读
1. div元素不是必须的,也可以是其它元素,比如span,但是约定都是将vue实例挂载到div
2. 因为div更加适合做布局
3. id 不是必须为app , 是程序员指定,一般我们就使用app
-->
<div id="app">
<!--老师解读
1. {{message}} : 插值表达式
2. message 就是从model的data数据池来设置
3. 当我们的代码执行时,会到data{} 数据池中去匹配数据, 如果匹配上, 就进行替换
, 如果没有匹配上, 就是输出空
-->
<h1>欢迎你{{message}}-{{name}}</h1>
</div>
<!--引入vue.js-->
<script src="vue.js"></script>
<script>
//创建Vue对象
/**
* 老韩解读
* 1. 创建Vue对象实例
* 2. 我们在控制台输出vm对象,看看该对象的结构!(data/listeners)
*
*/
let vm = new Vue({
el: "#app", //创建的vue实例挂载到 id=app的div
data: { //data{} 表示数据池(model的有了数据), 有很多数据 ,以k-v形式设置(根据业务需要来设置)
message: "Hello-Vue!",
name: "韩顺平教育"
}
})
console.log("vm=>", vm);
console.log(vm._data.message);
console.log(vm._data.name);
console.log(vm.name);
console.log(vm.message);
</script>
</body>
</html>
_data获取
直接获取
可以在控制台改变
注意和细节
按顺序执行,div在前,script在后,否则无法绑定数据
数据单向绑定
v-bind会报红,不写也不影响,el里的namspaceURI默认引入了
<body>
<div id="app">
<h1>{{message}}</h1>
<!--老师解读
1. 使用插值表达式引用 data数据池数据是在标签体内
2. 如果是在标签/元素 的属性上去引用data数据池数据时,不能使用插值表达式
3. 需要使用v-bind, 因为v-bind是vue来解析, 默认报红,但是不影响解析
4. 如果不希望看到报红, 直接 alt+enter 引入 xmlns:v-bind
-->
<!--<img src="{{img_src}}">-->
<img v-bind:src="img_src" v-bind:width="img_width">
<img :src="img_src" :width="img_width">
</div>
<script src="vue.js"></script>
<script>
let vm = new Vue({
el: "#app", //创建的vue实例挂载到 id=app的div
data: {
message: "hello, 耗子精",
img_src: "1.jpg",
img_width: "200px"
}
})
console.log("vm=>", vm);
</script>
</body>
</html>
数据双向绑定
<body>
<div id="app">
<h1>{{message}}</h1>
<!--老韩解读
1. v-bind是数据单向渲染: data数据池绑定的数据变化,会影响view
2. v-model="hobby.val" 是数据的双向渲染,
(1)data数据池绑定的数据变化,会影响view 【底层的机制是 Data Bindings】
(2)view 关联的的元素值变化, 会影响到data数据池的数据【底层机制是Dom Listeners】
-->
<input type="text" v-model="hobby.val"><br/><br/>
<!--单向绑定v-bind:value-->
<input type="text" :value="hobby.val"><br/><br/>
<p>你输入的爱好是: {{hobby.val}}</p>
</div>
<script src="vue.js"></script>
<script>
let vm = new Vue({
el: "#app", //创建的vue实例挂载到 id=app的div
data: { //data{}
message: "hi, 输入你的爱好",
hobby: {
val: "购物"
}
}
})
console.log("vm=>", vm);
</script>
</body>
事件绑定
<body>
<!--视图-->
<div id="app">
<h1>{{message}}</h1>
<!--老韩解读
1. v-on:click 表示我们要给button元素绑定一个click的事件
2. sayHi() 表示绑定的方法, 在方法池 methods{} 定义的
3. 底层仍然是dom处理
4. 如果方法不需要传递参数,可以省略()
5. v-on:click可以简写@, 但是需要浏览器支持
-->
<button v-on:click="sayHi()">点击输出</button>
<button v-on:click="sayOk()">点击输出</button>
<button v-on:click="sayHi">点击输出</button>
<button @click="sayOk">点击输出</button>
</div>
<!--引入我们的vue.js-->
<script src="vue.js"></script>
<!--创建一个vue实例,并挂载到id=app的div-->
<script>
//老师说明:这里创建的Vue实例, 你可以不去接收, 也可以接收
//方便我们调试信息
let vm = new Vue({
el: "#app", //创建的vue实例挂载到 id=app的div, el 就是element的简写
data: { //data{} 表示数据池(model中的数据), 有很多数据 ,以k-v形式设置(根据业务需要来设置)
message: "Vue事件处理的案例",
name: "韩顺平教育"
},
//老师解读:
// 1. 是一个methods属性, 对应的值是对象{}
// 2. 在{} 中, 可以写很多的方法, 你可以这里理解是一个方法池
// 3. 这里需要小伙伴有js的基础=>java web第4章
methods: {
sayHi() {
console.log("hi, 银角大王~");
},
sayOk() {
console.log("ok, 金角大王~");
}
}
})
</script>
</body>
应用
<body>
<div id="app">
<button @click="one">点击增加+1</button>
<!-- 这里count += 2 的count数据是data数据池的count-->
<button @click="count += 2">点击增加+2</button>
<p>你的按钮被点击了{{count}}次</p>
书名:<input type="text" v-model="bookName">
<button @click="show">点击显示输入框内容</button>
</div>
<script src="vue.js"></script>
<script>
let vm = new Vue({
el: "#app",
data:{
count: 0,
bookName: ""
},
methods:{
one() {
this.count++;
},
show() {
console.log(this.bookName)
}
}
})
</script>
</body>
修饰符
https://cn.vuejs/v2/guide/events.html#事件修饰符
<body>
<div id="app">
<!-- 老韩解读
1. 修饰符用于指出一个指令应该以特殊方式绑定。
2. v-on:submit.prevent的.prevent 修饰符表示阻止表单提交的默认行为
3. 执行 程序员指定的方法
-->
<form action="http://www.baidu.com" v-on:submit.prevent="onMySubmit">
妖怪名: <input type="text" v-model="monster.name"><br/><br/>
<button type="submit">注册</button>
</form>
<p>服务返回的数据是{{count}}</p>
<h1>修饰符扩展案例</h1>
<button v-on:click.once="onMySubmit">点击一次</button><br/>
<input type="text" v-on:keyup.enter="onMySubmit">
<input type="text" v-on:keyup.down="onMySubmit">
<input type="text" v-model.trim="count">
</div>
<script src="vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {//数据池
monster: {//monster数据(对象)的属性, 可以动态生成
},
count: 0
},
methods: {//方法池
onMySubmit() {
//console.log("我们自己的表单提交处理...");
//"", null, undefined都是false
if(this.monster.name) {
console.log("提交表单 name=", this.monster.name);
//这里,程序员就可以根据自己的业务发出ajax请求到后端
//得到数据后,在进行数据更新
this.count = 666;
} else {
console.log("请输入名字..");
}
}
}
})
</script>
</body>
对象的属性可以动态生成,省略不写
条件渲染
0、null、undefined、""(空串)都认为是false
v-if
<body>
<div id="app">
<!--这里小伙伴还可以看到checkbox的 checked属性的值-->
<input type="checkbox" v-model="sel">是否同意条款[v-if实现]
<!--
老师解读 v-if/v-else 会根据 返回的值,来决定是否动态创建对应的子组件 <h1>
-->
<h1 v-if="sel">你同意条款</h1>
<h1 v-else>你不同意条款</h1>
</div>
<script src="vue.js"></script>
<script>
//为了调试方便, 使用vm接收Vue实例
let vm = new Vue({
el: '#app',
data: {//data数据池
sel: false
}
})
</script>
</body>
v-show
<body>
<div id="app">
<!--这里小伙伴还可以看到checkbox的 checked属性的值-->
<input type="checkbox" v-model="sel">是否同意条款[v-show实现]
<h1 v-show="sel">你同意条款</h1>
<h1 v-show="!sel">你不同意条款</h1>
</div>
<script src="vue.js"></script>
<script>
//为了调试方便, 使用vm接收Vue实例
let vm = new Vue({
el: '#app',
data: {//data数据池
sel: false
}
})
</script>
</body>
区别
v-if真正创建/销毁子组件
v-show会动态切换,通过display:none隐藏
应用
<body>
<div id="app">
<!--1. 当用户输出成绩后, 我们判断成绩的范围,并进行修正
2. 事件处理: onblur[失去焦点]-->
输入成绩1-100:<input v-on:blur="setScore" type="text" v-model="score">
<p>你当前的成绩是{{score}}</p>
<div v-if="score >= 90">优秀</div>
<div v-else-if="score >= 70">良好</div>
<div v-else-if="score >= 60">及格</div>
<div v-else="score">不及格</div>
</div>
<script src="vue.js"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
score: ""
},
methods: {
setScore() {
if(this.score > 100)
this.score = 100;
if(this.score < 0)
this.score = 0;
}
}
})
</script>
</body>
列表渲染
v-for
数组
对象
三个参数
应用
<body>
<div id="app">
<!--
基本语法:
<li v-for="变量 in 数字">{{ 变量 }}</li>-->
<h1>简单的列表渲染</h1>
<ul>
<li v-for="i in 3">{{i}}</li>
</ul>
<!--
基本语法:
<li v-for="(变量, 索引) in 值">{{ 变量 }} - {{ 索引 }}</li>
-->
<h1>简单的列表渲染-带索引</h1>
<ul>
<li v-for="(i,index) in 3">{{i}}-{{index}}</li>
</ul>
<h1>遍历数据列表</h1>
<!-- 语法:
<tr v-for="对象 in 对象数组">
<td>{{对象的属性}}</td>
</tr>
-->
<table width="400px" border="1px">
<tr v-for="(monster,index) in monsters">
<td>{{index}}</td>
<td>{{monster.id}}</td>
<td>{{monster.name}}</td>
<td>{{monster.age}}</td>
</tr>
</table>
</div>
<script src="vue.js"></script>
<script>
new Vue({
el: '#app',
data: { //数据池
monsters: [
{id: 1, name: '牛魔王', age: 800},
{id: 2, name: '黑山老妖', age: 900},
{id: 3, name: '红孩儿', age: 200}
]
}
})
</script>
</body>
组件化编程
组件定义需要放在new Vue()前,否则组件注册会失败
全局组件
<body>
<div id="app">
<h1>组件化编程-全局组件app</h1>
<!--使用全局组件-->
<counter></counter>
</div>
<div id="app2">
<h1>组件化编程-全局组件-app2</h1>
<!--使用全局组件-->
<counter></counter>
</div>
<script src="vue.js"></script>
<script>
//1、定义一个全局组件, 名称为 counter
//2. 把组件视为一个Vue实例,也有自己的数据池和methods
//3. 全局组件是属于所有vue实例,因此,可以在所有的vue实例使用
Vue.component("counter", {
template: `<button v-on:click="click()">点击次数= {{count}} 次【全局组件化】</button>`,
data() {//这里需要注意,和原来的方式不一样!!!!
return {
count: 10
}
},
methods: {
click() {
this.count++;
}
}
})
//创建Vue实例,必须有
let vm = new Vue({
el: "#app"//Vue实例的挂载点
})
let vm2 = new Vue({
el: "#app2"//Vue实例的挂载点
})
</script>
</body>
局部组件
<body>
<div id="app">
<h1>组件化编程-局部组件</h1>
<!--使用局部组件 ,该组件是从挂载到app的vue中的-->
<my_counter></my_counter><br/>
</div>
<script src="vue.js"></script>
<script>
//定义一个组件, 组件的名称为 buttonCounter
//1. 可以把常用的组件,定义在某个commons.js中 export
//2. 如果某个页面需要使用, 直接import
const buttonCounter = {
template: `<button v-on:click="click()">点击次数= {{count}} 次【局部组件化】</button>`,
data() {//这里需要注意,和原来的方式不一样!!!!
return {
count: 10
}
},
methods: {
click() {
this.count++;
}
}
}
//创建Vue实例,必须有
let vm = new Vue({
el: "#app",//Vue实例的挂载点
components: { //引入/注册某个组件, 此时my_counter就是一个组件, 是一个局部组件,他的使用范围在当前vue
'my_counter': buttonCounter
}
})
生命周期和监听函数(钩子函数)
<body>
<!--这里可以视为用户看到的页面-对应前面讲解的页面dom-->
<div id="app">
<span id="num">{{num}}</span>
<button @click="num++">赞!</button>
<h2>{{name}},有{{num}}次点赞</h2>
</div>
<script src="vue.js"></script>
<script>
let vm = new Vue({
el: "#app",
data: {//数据池
name: "kristina",
num: 0
},
methods: {
show() {
return this.name;
},
add() {
this.num++;
}
},
beforeCreate() {//生命周期函数-创建vue实例前
console.log("=============beforeCreate==========");
console.log("数据模型/数据池的数据是否加载/使用?[no]", this.name, " ", this.num);
//console.log("自定义方法是否加载/使用?[no]", this.show());
console.log("用户页面dom是否加载/使用?[yes]", document.getElementById("num"));
console.log("用户页面dom是否被渲染?[no]", document.getElementById("num").innerText);
},
created() {//生命周期函数-创建vue实例
console.log("=============created==========");
console.log("数据模型/数据池的数据是否加载/使用?[yes]", this.name, " ", this.num);
console.log("自定义方法是否加载/使用?[yes]", this.show());
console.log("用户页面dom是否加载/使用?[yes]", document.getElementById("num"));
console.log("用户页面dom是否被渲染?[no]", document.getElementById("num").innerText);
//可以发出Ajax
//接收返回的数据
//再次去更新data数据池的数据
//编译内存模板结构
//.....
},
beforeMount() {//生命周期函数-挂载前
console.log("=============beforeMount==========");
console.log("数据模型/数据池的数据是否加载/使用?[yes]", this.name, " ", this.num);
console.log("自定义方法是否加载/使用?[yes]", this.show());
console.log("用户页面dom是否加载/使用?[yes]", document.getElementById("num"));
console.log("用户页面dom是否被渲染?[no]", document.getElementById("num").innerText);
},
mounted() {//生命周期函数-挂载后
console.log("=============mounted==========");
console.log("数据模型/数据池的数据是否加载/使用?[yes]", this.name, " ", this.num);
console.log("自定义方法是否加载/使用?[yes]", this.show());
console.log("用户页面dom是否加载/使用?[yes]", document.getElementById("num"));
console.log("用户页面dom是否被渲染?[yes]", document.getElementById("num").innerText);
},
beforeUpdate() {//生命周期函数-数据池数据更新前
console.log("=============beforeUpdate==========");
console.log("数据模型/数据池的数据是否加载/使用?[yes]", this.name, " ", this.num);
console.log("自定义方法是否加载/使用?[yes]", this.show());
console.log("用户页面dom是否加载/使用?[yes]", document.getElementById("num"));
console.log("用户页面dom数据是否被更新?[no]", document.getElementById("num").innerText);
//验证数据==>修正
// if(this.num < 10 ) {
// this.num = 8;
// }
},
updated() {//生命周期函数-数据池数据更新后
console.log("=============updated==========");
console.log("数据模型/数据池的数据是否加载/使用?[yes]", this.name, " ", this.num);
console.log("自定义方法是否加载/使用?[yes]", this.show());
console.log("用户页面dom是否加载/使用?[yes]", document.getElementById("num"));
console.log("用户页面dom数据是否被更新?[yes]", document.getElementById("num").innerText);
}
})
</script>
</body>
Vue项目结构分析
ElementUI
vue2 -> ElementUI vue3 -> ElementPlus
Axious
库文件
response.data.json
{
"success": true,
"message": "成功",
"data": {
"items": [
{
"name": "牛魔王",
"age": 800
},
{
"name": "红孩儿",
"age": 500
},
{
"name": "蜈蚣精",
"age": 200
}
]
}
}
<body>
<!--页面视图-->
<div id="app">
<h1>{{msg}}</h1>
<table border="1" width="200">
<tr>
<td>名字</td>
<td>年龄</td>
</tr>
<tr v-for="monster in monsterList">
<td>{{monster.name}}</td>
<td>{{monster.age}}</td>
</tr>
</table>
</div>
<script src="vue.js"></script>
<script src="axios.min.js"></script>
<script>
new Vue({
el: "#app",
data: {
msg: "妖怪信息列表",
monsterList: [] //表示妖怪的信息数组
},
methods: {//自定义方法
list() {//发送ajax请求,获取数据 axios
/*
老韩解读
1. axios.get() 表示发出ajax请求
2. http://localhost:63342/axios/data/response.data.json 表示请求的url
要根据实际情况来填写
3. axios发出ajax请求的基本语法
axios.get(url).then(箭头函数).then(箭头函数)...catch(箭头函数)
(1) 如果get请求成功就进入到第一个then()
(2) 可以再 第一个then()中继续发出axios的ajax请求
(3) 如果有异常, 会进入到 catch(箭头函数)
4. list在生命周期函数created() 中调用-自己去回顾vue的生命周期函数
*/
axios.get("http://localhost:63342/axios/data/response.data.json")
.then(responseData => {
console.log("responseData= ", responseData)
//使用JSON.stringify(json) 把json对象转成一个字符串,方便观察
console.log("responseData= ", JSON.stringify(responseData));
// console.log("responseData.data= ", responseData.data)
// console.log("responseData.data.data= ", responseData.data.data)
console.log("responseData.data.data.item= ", responseData.data.data.items)
//将妖怪列表数组信息, 绑定到 data数据池的 monsterList
//老师小技巧,一定要学会看返回的数据格式!!!
this.monsterList = responseData.data.data.items;
//可以再次发出ajax请求, 老师故意发出了第二次ajax请求, 回顾老师讲过的promise发出多次请求
// return axios.get("http://localhost:63342/axios/data/response.data.json")
})
// .then(responseData => {
// console.log("第二次axios发出 ajax请求responseData= ", responseData)
// })
.catch(err => {
console.log("异常=", err)
})
}
},
created() {
this.list();
}
})
</script>
</body>
www.json.cn