Vue
前端目前形势
前端发展史
1.HTML
(5)、CSS
(3)、JavaScript
(ES5、ES6):编写一个个的页面 -> 给后端(PHP、Python、Go、Java) -> 后端嵌入模板语法 -> 后端渲染完数据 -> 返回数据给前端 -> 在浏览器中查看
2.Ajax的出现 -> 后台发送异步请求,Render
+Ajax
混合
3.单用Ajax(加载数据,DOM渲染页面):前后端分离的雏形
4.Angular框架的出现(1个JS框架):出现了“前端工程化
”的概念(前端也是1个工程、1个项目)
5.React、Vue框架:当下最火的2个前端框架(Vue
:国人喜欢用,React
:外国人喜欢用)
6.移动开发(Android+IOS) + Web(Web+微信小程序+支付宝小程序) + 桌面开发(Windows桌面):前端 -> 大前端
7.一套代码在各个平台运行(大前端):谷歌Flutter(Dart语言:和Java很像)
可以运行在IOS、Android、PC端
8.在Vue框架的基础性上 uni-app:一套编码 编到10个平台
9.在不久的将来 ,前端框架可能会一统天下
介绍
Vue (读音 /vjuː/
,类似于 view) 是一套用于构建用户界面的渐进式框架
与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用
Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合
渐进式框架
可以一点一点地使用它,只用一部分,也可以整个工程都使用它
网站
特点
- 易用
- 通过HTML、CSS、JavaScript构建应用
- 灵活
- 不断繁荣的生态系统,可以在一个库和一套完整框架之间自如伸缩
- 高效
- 20kB min+gzip 运行大小
- 超快虚拟DOM
- 最省心的优化
M-V-VM思想
介绍
MVVM 是Model-View-ViewModel
的缩写,它是一种基于前端开发的架构模式,是一种事件驱动编程方式
Model
:vue对象的data属性里面的数据,这里的数据要显示到页面中View
:vue中数据要显示的HTML页面,在vue中,也称之为“视图模板” (HTML+CSS)ViewModel
:vue中编写代码时的vm对象,它是vue.js的核心,负责连接 View 和 Model数据的中转,保证视图和数据的一致性,所以前面代码中,data里面的数据被显示中p标签中就是vm对象自动完成的(双向数据绑定:JS中变量变了,HTML中数据也跟着改变)
特性
- 低耦合:
视图
(View)可以独立于Model变化和修改
,1个ViewModel可以绑定到不同的View上,当View变化的时候 Model可以不变,当Model变化的时候 View也可以不变 - 可复用:可以把一些视图逻辑放在1个ViewModel中,让很多View
重用这端视图的逻辑
(以此减少代码冗余) - 独立开发:
开发
人员可以专注于业务逻辑
和数据的开发
(ViewModel),设计
人员可以专注于页面设计
- 可测试:界面元素是比较难以测试的,而现在的测试可以
针对ViewModel
来编写
MVVM的逻辑
组件化开发、单页面开发
类似于DTL中的include,每一个组件的内容都可以被替换和复用
单页面开发
- 只需要一个页面,结合组件化开发来替换页面中的内容
- 页面的切换只是组件的替换,页面还是只有一个index.html
版本
- 1.X:使用得较少
- 2.X:普遍使用
- 3.X:刚出没多久,只有Beta版
引入方式
-
CDN的方式引入
-
下载后导入
补充
- 解释型的语言是需要解释器的
- nodejs:一门后端语言
使用
模板语法
{{变量、js语法}}
指令之文本指令
v-html # 让HTML字符串渲染成标题
v-text # 标签内容显示js变量对应的值
v-show # 放一个布尔值:为真 标签就显示;为假,标签就隐藏
v-if # 放一个布尔值:为真 标签就显示;为假,标签就隐藏(删除)
指令之事件指令
v-on:事件 # 触发事件(不推荐)
@事件 # 触发事件(推荐)
@[event] # 触发event事件(可以是其他任意事件)
Style与Class
数据的绑定
:属性名 = js变量/js语法
class: 字符串、三目运算符、数组、对象{red:true}
:class='js变量、字符串、js数组'
style: 字符串、三目运算符、数组[{backgreound:'red'}]、对象{red:true}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<style>
.cls_obj_red{
background-color: red;
}
</style>
</head>
<body>
<div id="app">
<!-- <p :class="cls_obj">阿巴阿巴</p>-->
<!-- <p :style="style_obj">滴滴答答</p>-->
</div>
<script>
var vm = new Vue({
el:'#app',
data:{
// cls_obj:{cls_obj_red:true}
// cls_obj:['cls_obj_red']
// cls_obj:'cls_obj_red'
// style_obj:'background-color:red'
// style_obj:[{backgroundColor:'red'},]
// style_obj:{backgroundColor:'red'}
}
})
</script>
</body>
</html>
条件渲染
指令 | 释义 |
---|---|
v-if | 相当于: if |
v-else | 相当于:else |
v-else-if | 相当于:else if |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<style>
.cls_obj_red{
background-color: red;
}
</style>
</head>
<body>
<div id="app">
<p v-if="show">嘀哩嘀哩</p>
<p v-if="type==1">1</p>
<p v-else-if="type==2">2</p>
<p v-else-if="type==3">3</p>
<p v-else="">Boom!</p>
</div>
<script>
var vm = new Vue({
el:'#app',
data:{
show:true,
type:1
}
})
</script>
</body>
</html>
列表渲染
v-if + v-for
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<link rel="stylesheet" href="bootstrap.min.css">
</head>
<body>
<div id="app">
<button @click="shopping_click" class="btn btn-primary">哔哩哔哩</button>
<table class="table table-hover table-striped">
<thead>
<tr>
<th>编号</th>
<th>商品名</th>
<th>单价</th>
</tr>
</thead>
<tbody>
<tr v-if="shopping.length==0">
<td>售罄</td>
<td>售罄</td>
<td>售罄</td>
</tr>
<tr v-else v-for="value,key in shopping">
<td>{{key+1}}</td>
<td>{{value.name}}</td>
<td>{{value.price}}</td>
</tr>
</tbody>
</table>
</div>
<script>
var vm = new Vue({
el:'#app',
data:{
shopping:[]
},
methods:{
shopping_click(){
this.shopping=[
{id:1,name:'小包子', price:188},
{id:2,name:'包子', price:288},
{id:3,name:'大包子', price:388}
]
}
}
})
</script>
</body>
</html>
v-for
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<link rel="stylesheet" href="bootstrap.min.css">
<style>
.cls_obj_red{
background-color: red;
}
</style>
</head>
<body>
<div id="app">
<p v-for="name in names">id:{{name.cid}} name: {{name.name}} age: {{name.age}}</p>
</div>
<script>
var vm = new Vue({
el:'#app',
data:{
names:[
{cid:1, name:'jerry', age:18},
{cid:2, name:'tom', age:19},
{cid:3, name:'哔哩哔哩', age:20}
]
}
})
</script>
</body>
</html>
数组更新与检测
<!--vue中使用的是虚拟DOM, 会和原生的DOM进行比较, 然后进行数据的更新,提高数据的刷新速度(虚拟DOM用了diff算法)-->
一定会触发DOM的比较,如果有数据变了,页面没变,使用该方法赋值 ↓
Vue.set(vm.class_obj, 'background', true)
过滤
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<link rel="stylesheet" href="bootstrap.min.css">
</head>
<body>
<div id="app">
<input type="text" @input="changeData" v-model="search" >
<p v-for="value in new_list">{{value}}</p>
</div>
<script>
var vm = new Vue({
el:'#app',
data:{
search:'',
list:['a', 'ab', 'b', 'bs'],
new_list:['a', 'ab', 'b', 'bs']
},
methods: {
changeData(){
this.new_list = this.list.filter(item=>{
return item.indexOf(this.search)>-1
})
}
}
})
</script>
</body>
</html>
事件修饰符
事件修饰符 | 释义 |
---|---|
.stop | 只处理自己的事件,父控件冒泡的事件不处理(阻止事件冒泡) |
.self | 只处理自己的事件,子控件冒泡的事件不处理 |
.prevent | 阻止a链接的跳转 |
.once | 事件只会触发一次(适用于抽奖页面) |
使用修饰符时,顺序很重要,相应的代码会以同样的顺序产生
@click.prevent.self :会阻止所有的点击
@click.self.prevent :只会阻止对元素自身的点击
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>事件修饰符</title>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>
<div id="box">
<!-- <ul @click="handleUl">-->
<ul @click.self="handleUl">
<!-- <li v-for="data in dataList" @click="handleLi">{{data}}</li>-->
<li v-for="data in dataList" @click.stop="handleLi">{{data}}</li>
<li><a href="http://www.baidu.com">不拦截</a></li>
<li><a href="http://www.baidu.com" @click="handleLink($event)">点击拦截</a></li>
<li><a href="https://www.baidu.com" @click.prevent="handleLink">点击拦截</a></li>
<li><button @click.once="test">只执行一次</button></li>
</ul>
</div>
</body>
<script>
var vm = new Vue({
el: '#box',
data: {
dataList: ['1','22','333','4444']
},
methods: {
handleUl(ev){
console.log('ul被点击了')
},
handleLi(){
console.log('li被点击了')
ev.stopPropagation() // 点击事件停止 冒泡(向父组件传递时间)
},
handleLink(ev){
ev.preventDefault()
},
test(){
alert('只触发1次')
}
}
})
</script>
</html>
数据的双向绑定(v-model的使用)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<link rel="stylesheet" href="bootstrap.min.css">
</head>
<body>
<div id="app">
<input type="text" v-model="test">{{test}}
</div>
<script>
var vm = new Vue({
el:'#app',
data:{
test:'',
}
})
</script>
</body>
</html>
按键修饰符
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>按键修饰符</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
<input type="text" v-model="name" @keyup="handelKey1">
<input type="text" v-model="name" @keyup.enter="handelKey2">
<!-- <button @click="handelClick">点我</button>-->
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
name: ''
},
methods: {
handelKey1(ev) {
console.log(ev)
if (ev.keyCode == 13) {
console.log('按下了回车')
}
},
handelKey2() {
console.log('回车键按下了')
},
handelClick(ev) {
console.log(ev)
}
}
})
</script>
</html>
表单控制
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>表单控制</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
<h1>checkbox的选中与不选中</h1>
<p>用户名: <input type="text" v-model="name"></p>
<p>密码: <input type="password" v-model="password"></p>
<p><input type="checkbox" v-model="isRem">记住密码</p>
<button @click="submit">登录</button>
<hr>
<h1>性别单选:radio</h1>
<input type="radio" v-model="gender" value="1">男
<input type="radio" v-model="gender" value="2">女
<input type="radio" v-model="gender" value="3">其他
<br>
您选择的性别是:{{gender}}
<hr>
<h1>爱好多选:checkbox</h1>
<input type="checkbox" v-model="hobby" value="1">篮球
<br>
<input type="checkbox" v-model="hobby" value="2">足球
<br>
<input type="checkbox" v-model="hobby" value="3">美女
<br>
您的爱好是:{{hobby}}
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
name: '',
password: '',
isRem: false,
gender: '',
hobby:[],
},
methods: {
submit() {
console.log(this.name)
console.log(this.password)
console.log(this.isRem)
}
}
})
</script>
</html>
购物车案例(全选、数量加减)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<link rel="stylesheet" href="bootstrap.min.css">
</head>
<body>
<div id="app">
<table class="table-hover table table-striped">
<thead>
<tr>
<th>商品名</th>
<th>单价</th>
<th>数量</th>
<th>选择 <input type="checkbox" v-model="allCheck" @change="allChange"></th>
</tr>
</thead>
<tbody>
<tr v-for="shop in shop_list">
<td>{{shop.name}}</td>
<td>{{shop.price}}</td>
<td><button class="btn btn-primary" @click="click_down(shop)">-</button>{{shop.num}}<button class="btn btn-primary" @click="shop.num++">+</button></td>
<td><input type="checkbox" :value="shop" v-model="check_list" @change="oneChange"></td>
</tr>
</tbody>
</table>
总价为: {{get_price()}}
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
shop_list:[
{name:'哔哩', price:123, num:2},
{name:'书', price:323, num:3},
{name:'滴滴', price:223, num:4},
],
check_list:[],
allCheck:false
},
methods:{
get_price(){
let total = 0
if (this.check_list.length > 0){
for (i in this.check_list){
total += this.check_list[i].num * this.check_list[i].price
}
}
return total
},
allChange(){
if (this.allCheck){
this.check_list = this.shop_list
}else {
this.check_list=[]
}
},
oneChange(){
if (this.check_list.length === this.shop_list.length){
this.allCheck = true
}else {
this.allCheck = false
}
},
click_down(shop){
if (shop.num >1){
shop.num --
}else {
shop.num = 1
}
}
}
})
</script>
</body>
</html>
v-model进阶
- .lazy :并不是实时改变,而是在失去焦点或者按回车时才会更新
- .number :将输入转换成Number类型
- .trim :可以自动过滤输入首尾的空格
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>v-model进阶</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
<!-- <input type="text" v-model.lazy="name"> 输入内容是:{{name}}-->
<!-- <input type="text" v-model.number="name"> 输入内容是:{{name}}-->
<input type="text" v-model.trim="name"> 输入内容是:{{name}}
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
name: ''
},
})
</script>
</html>
Vue生命周期钩子
钩子函数 | 描述 |
---|---|
beforeCreate | 创建Vue实例之前调用 |
created | 创建Vue实例成功后调用(可以在此处发送异步请求后端数据) |
beforeMount | 渲染DOM之前调用 |
mounted | 渲染DOM之后调用 |
beforeUpdate | 重新渲染之前调用(数据更新等操作时,控制DOM重新渲染) |
updated | 重新渲染完成之后调用 |
beforeDestroy | 销毁之前调用 |
destroyed | 销毁之后调用 |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>v-model进阶</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
<!-- <child v-if="isShow"></child>-->
</div>
</body>
<script>
//定义一个组件
Vue.component('child', {
template: `
<div>
{{name}}
<br>
{{age}}
<button @click="name='Darker1'">更新数据1</button>
<button @click="name='Darker2'">更新数据2</button>
</div>`,
data() {
return {
name: 'Darker1',
age: 19
}
},
beforeCreate() {
console.group('当前状态:beforeCreate')
console.log('当前el状态:', this.$el)
console.log('当前data状态:', this.$data)
console.log('当前name状态:', this.name)
},
created() {
console.group('当前状态:created')
console.log('当前el状态:', this.$el)
console.log('当前data状态:', this.$data)
console.log('当前name状态:', this.name)
},
beforeMount() {
console.group('当前状态:beforeMount')
console.log('当前el状态:', this.$el)
console.log('当前data状态:', this.$data)
console.log('当前name状态:', this.name)
},
mounted() {
console.group('当前状态:mounted')
console.log('当前el状态:', this.$el)
console.log('当前data状态:', this.$data)
console.log('当前name状态:', this.name)
//用的最多,向后端加载数据,创建定时器等
console.log("页面已被vue实例渲染, data, methods已更新");
console.log('mounted')
this.t = setInterval(function () {
console.log('daada')
}, 3000)
clearInterval(this.t)
},
beforeUpdate() {
console.group('当前状态:beforeUpdate')
console.log('当前el状态:', this.$el)
console.log('当前data状态:', this.$data)
console.log('当前name状态:', this.name)
},
updated() {
console.group('当前状态:updated')
console.log('当前el状态:', this.$el)
console.log('当前data状态:', this.$data)
console.log('当前name状态:', this.name)
},
beforeDestroy() {
console.group('当前状态:beforeDestroy')
console.log('当前el状态:', this.$el)
console.log('当前data状态:', this.$data)
console.log('当前name状态:', this.name)
},
destroyed() {
console.group('当前状态:destroyed')
console.log('当前el状态:', this.$el)
console.log('当前data状态:', this.$data)
console.log('当前name状态:', this.name)
//组件销毁,清理定时器
clearInterval(this.t)
this.t = null
console.log('destoryed')
},
})
var vm = new Vue({
el: '#app',
data: {
isShow: true
},
methods:{
init(){
console.log('init')
},
},
mounted() {
console.log('mounted执行;了')
//ajax向后端获取数据
this.init()
},
})
</script>
</html>
与后端交互的几种方式
向后端发送ajax请求
三种方式
- jQuery的ajax
- fetch(原生)
- axios(用的最多)
jQuery的ajax
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
<div v-for="data in data_list">
<h3>{{data.name}}</h3>
<img :src="data.poster" alt="">
<h5>导演:{{data.director}}</h5>
</div>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
data_list: []
},
methods: {
get_data() {
//发送请求
// let _this=this
$.ajax({
url: 'http://127.0.0.1:5000/',
type: 'get',
success: (data) => {
let data_obj=JSON.parse(data)
// console.log(typeof data_obj)
this.data_list = data_obj.data.films
}
// success: function (data) {
// // console.log(data)
// _this.data_list = data
// }
})
}
},
mounted() {
this.get_data()
},
})
</script>
</html>
fetch(原生)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
<div v-for="data in data_list">
<h3>{{data.name}}</h3>
<img :src="data.poster" alt="">
<h5>导演:{{data.director}}</h5>
</div>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
data_list: []
},
methods: {
get_data() {
//发送请求
fetch("http://127.0.0.1:5000/").then(res => res.json()).then(res => {
console.log(res.data.films)
this.data_list = res.data.films
})
}
},
mounted() {
this.get_data()
},
})
</script>
</html>
axios(用的最多)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="app">
<div v-for="data in data_list">
{[ data.name ]}
<img :src="data.poster" alt="">
{[ data.director ]}
{[ data.synopsis ]}
</div>
</div>
<script>
var vm = new Vue({
el:'#app',
data:{
data_list:[]
},
delimiters:['{[', ']}'],
methods:{
get_data(){
axios({
url:'http://127.0.0.1:8090/index/',
methods:'get'
}).then(res=>{
this.data_list = res.data.data.films
})
}
},
mounted(){
this.get_data()
}
})
</script>
</body>
</html>
计算属性
优点
- 在同一个页面中使用多次计算属性,不会多次执行
- 不需要加括号,直接使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
<input type="text" v-model='name'>
<br>
您输入的是:{{get_name()}}
<br>
您输入的是2:{{get_name()}}
<hr>
<!-- 您输入的是:{{name.substring(0,1).toUpperCase()+name.substring(1)}}-->
<!-- 计算属性优点-->
<!-- 1 在同一个页面中使用多次计算属性,不会多次执行-->
<!-- 2 不需要加括号,直接使用-->
<br>
计算属性:您输入的是:{{upper_name}}
<br>
计算属性2:您输入的是:{{upper_name}}
计算属性2:您输入的是:{{upper_name}}
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
name:''
},
computed:{
upper_name(){
console.log('计算属性我执行了')
return this.name.substring(0,1).toUpperCase()+this.name.substring(1)
},
},
methods:{
get_name(){
console.log('get_name我执行了')
return this.name.substring(0,1).toUpperCase()+this.name.substring(1)
},
}
})
</script>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
<input type="text" v-model='search'>
<div v-for="data in new_list">
{{data}}
</div>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
search: '',
data_list: ['aaa', 'abc', 'abcde', 'abcdef', 'bbb', 'bac']
},
computed: {
new_list() {
return this.data_list.filter(item => {
return item.indexOf(this.search) > -1
})
}
},
methods: {}
})
</script>
</html>
虚拟dom和diff算法
其实呢不只是vue,react中在执行列表渲染时也会要求给每个组件添加key这个属性。
key简单点来说就是唯一标识,就像ID一样唯一性
要知道,vue和react都实现了一套虚拟DOM,使我们可以不直接操作DOM元素,只操作数据便可以重新渲染页面。而隐藏在背后的原理便是其高效的Diff算法。
只做同层级的对比
按照key值比较,出现新的key就插入
通组件对比
具体实现
把树按照层级分解
同key值比较
通组件对比
<div id="box">
<div v-if="isShow">111</div>
<p v-else>222</p>
<!--
{tag:div,value:111}
{tag:p,value:222}
直接不比较,直接删除div,新增p
-->
<div v-if="isShow">111</div>
<div v-else>222</div>
<!--
{tag:div,value:111}
{tag:div,value:222}
比较都是div,只替换文本内容
-->
</div>
详细:https://segmentfault.com/a/1190000020170310
组件
- 介绍
- 全局组件
- 局部组件
- 组建通信之父传子
介绍
1 组件的作用
扩展 HTML 元素,封装可重用的代码,目的是复用
例如:
有一个轮播图,可以在很多页面中使用,一个轮播有js,css,html
组件把js,css,html放到一起,有逻辑,有样式,有html
2 组件分类:局部组件和全局组件
全局组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
<myheader></myheader>
<div>我是div</div>
<myheader></myheader>
</div>
</body>
<script>
// 定义一个全局组件
// 组件可以有data,methods,computed....,但是data 必须是一个函数
Vue.component('myheader', {
template: `
<div>
<h1 style="background-color: greenyellow">我是全局组件:{{name}}</h1>
<button @click="handleClick">点我弹出美女</button>
</div>
`,
data(){
return {
name:'lqz'
}
},
methods:{
handleClick(){
alert('美女')
}
},
mounted(){},
computed:{
}
})
var vm = new Vue({
el: '#app',
data: {},
})
</script>
</html>
局部组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
<myheader></myheader>
<div>我是div</div>
<myheader></myheader>
<div></div>
</div>
</body>
<script>
// 定义一个全局组件
//组件可以有data,methods,computed....,但是data 必须是一个函数
Vue.component('myheader', {
template: `
<div>
<h1 style="background-color: greenyellow">我是全局组件:{{name}}</h1>
<button @click="handleClick">点我弹出美女</button>
<hr>
<child></child>
</div>
`,
data(){
return {
name:'lqz'
}
},
methods:{
handleClick(){
alert('美女')
}
},
mounted(){},
computed:{
},
components:{
child:{
template: `<div>
<span>{{age}}</span>
</div>`,
data(){
return {
age:19
}
},
methods:{
}
}
}
})
var vm = new Vue({
el: '#app',
data: {},
})
</script>
</html>
组建通信之父传子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
<myheader :myname="name" :myshow="false"></myheader>
{{obj.length}}
</div>
</body>
<script>
// 定义一个全局组件
//组件可以有data,methods,computed....,但是data 必须是一个函数
Vue.component('myheader', {
template: `
<div>
<h1 style="background-color: greenyellow">我是全局组件:{{myname}}</h1>
<button @click="handleClick">点我弹出美女</button>
<br>
{{myshow}}
<hr>
<child v-if=""></child>
</div>
`,
data(){
return {
name:'lqz'
}
},
methods:{
handleClick(){
alert('美女')
}
},
mounted(){},
computed:{
},
components:{
child:{
template: `<div>
<span>{{age}}</span>
</div>`,
data(){
return {
age:19
}
},
methods:{
}
}
},
// props:['myname'] , //注册一下
// 属性验证
props:{
myname:String,
myshow:Boolean
},
})
var vm = new Vue({
el: '#app',
data: {
name:'egon'
},
})
</script>
</html>
组建通信之子传父(通过自定义事件)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="box">
<navbar @myevent="handleEvent"></navbar>
</div>
</body>
<script>
// 定义全局组件
Vue.component('navbar', {
template: `
<div>
<h1>我是navbar</h1>
<hr>
<input type="text" v-model="name">
<br>
<button @click="handleClick">我是子组件的button</button>
</div>
`,
data() {
return {
name: 'lqz'
}
},
methods: {
handleClick() {
// 触发父组件中myevent这个自定义事件对应的函数执行
this.$emit('myevent',this.name)
}
}
})
var vm = new Vue({
el: '#box',
data: {},
methods: {
handleEvent(name) {
console.log('我执行了')
console.log('从子组件传递的name:'+name)
}
}
})
</script>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="box">
<navbar @myevent="handleEvent" v-if="myshow"></navbar>
</div>
</body>
<script>
// 定义全局组件
Vue.component('navbar', {
template: `
<div>
<h1>我是navbar</h1>
<hr>
<button @click="handleClick">点我隐藏子组件</button>
</div>
`,
data() {
return {
// myshow: true
}
},
methods: {
handleClick() {
// 触发父组件中myevent这个自定义事件对应的函数执行
// this.myshow = !this.myshow
this.$emit('myevent', false)
}
}
})
var vm = new Vue({
el: '#box',
data: {
myshow: true
},
methods: {
handleEvent(show) {
this.myshow = show
}
}
})
</script>
</html>
ref属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="box">
ref放在标签上,拿到的是原生节点
<br>
ref放在组件上,拿到的是组件对象(数据,方法,直接使用即可)
<hr>
<h1>ref用在标签上</h1>
<input type="text" ref="myinput">
<button @click="handleClick">点我触发事件</button>
<hr>
<h1>ref用在组件上</h1>
<navbar ref="mynavbar"></navbar>
</div>
</body>
<script>
// 定义全局组件
Vue.component('navbar', {
template: `
<div>
<h3>我是navbar</h3>
<hr>
</div>
`,
data() {
return {
myshow: true
}
},
methods: {
handleClick(a) {
console.log('父组件调用我,传入了:'+a)
}
}
})
var vm = new Vue({
el: '#box',
data: {
myshow: true
},
methods: {
handleClick() {
//this.$refs 取到一个对象,放着你在标签上写得ref对应的value值
//在父组件中直接取到了子组件的值(从子传到父)
// console.log(this.$refs.mynavbar.myshow)
//从父传子
// this.$refs.mynavbar.myshow='sss'
//调用子组件方法
this.$refs.mynavbar.handleClick('lqz')
}
}
})
</script>
</html>
事件总线
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="box">
<child1></child1>
<hr>
<child2></child2>
</div>
</body>
<script>
// 借助事件总线,实现跨组件通信
//定义一个事件总线
var bus=new Vue()
Vue.component('child1', {
template: `
<div>
<input type="text" v-model="msg">
<button @click="send_msg">发送</button>
<hr>
</div>
`,
data() {
return {
msg: ''
}
},
methods:{
send_msg(){
bus.$emit('suibian',this.msg)
}
}
})
Vue.component('child2', {
template: `
<div>
<h5>我收到的内容是:{{recv_msg}}</h5>
</div>
`,
data() {
return {
recv_msg:''
}
},
mounted(){
bus.$on('suibian',msg=> {
this.recv_msg=msg
})
}
})
var vm = new Vue({
el: '#box',
data: {},
methods: {}
})
</script>
</html>
动态组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="box">
<button @click="who='Home'">首页</button>
<button @click="who='User'">用户</button>
<button @click="who='Order'">订单</button>
<keep-alive>
<component :is="who"></component>
</keep-alive>
</div>
</body>
<script>
Vue.component('Home', {
template: `
<div>
首页
</div>
`,
data() {
return {}
},
})
Vue.component('User', {
template: `
<div>
用户组件
<input type="text" v-model="name">
</div>
`,
data() {
return {
name: ''
}
},
})
Vue.component('Order', {
template: `
<div>
订单页面
</div>
`,
data() {
return {}
},
})
var vm = new Vue({
el: '#box',
data: {
who: 'Home'
},
})
</script>
</html>
插槽
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="box">
<Home>阿斯顿发送到</Home>
<Order>
<button slot="b" @click="handleClick">我是个按钮</button>
</Order>
</div>
</body>
<script>
Vue.component('Home', {
template: `
<div>
首页
<div>
<slot></slot>
</div>
</div>
`,
data() {
return {}
},
})
Vue.component('Order', {
template: `
<div>
订单页面
<slot name="a"></slot>
<br>
我是一行数据
<br>
<slot name="b"></slot>
</div>
`,
data() {
return {}
},
})
var vm = new Vue({
el: '#box',
data: {
who: 'Home'
},
methods:{
handleClick(){
console.log('我被点了')
}
}
})
</script>
</html>
Vue-CLI 搭建vue项目
1 ECMAScript,javascript,nodejs的关系
2 安装nodejs(安装解释器)
3 java:sun---》oracle(甲骨文)----》有些包,收费
-安卓使用java开发,涉及到版权
-jdk:java开发工具包,做java开发,需要安装它 1.5 1.8大更新 java 15
-jre:java运行环境,
-jvm:java虚拟机,最少要占200m内存空间
4 安装node,一路下一步
node:就是python命令
npm:就是python的pip命令,npm下载模块慢,我们使用cmpm下载
cnpm:阿里提供的
npm install -g cnpm --registry=https://registry.npm.taobao.org
5 安装vue脚手架
cnpm install -g @vue/cli
6 多出vue命令
vue create my-project: 创建出一个vue项目,等同于djagnoadmin createproject 名字
# OR
vue ui
7 开发
-使用pycharm开发vue项目
-装vue插件
8 运行起项目
-terminal中:npm run serve
vue项目目录介绍
myfirstvue # 项目名
-node_modules # 该项目所有的依赖,如果要把项目给别人,这个文件夹要删掉(很大)
-public # 文件夹
-favicon.ico #小图标
-index.html # 整个vue项目的index.html,单页面开发
-src # 核心
-store # 如果装了vuex,就会有这个文件夹
-router #如果装了vue router ,就会有这个文件夹
-assets # 存放资源文件(js,css,img)
-components # 小组件(在这写小组件)
-views #页面组件(在这写页面组件)
main.js # 整个项目的入口,核心配置
App.vue # 根组件
-package.json # 项目的依赖,不能删
-README.md # 介绍
vue组件介绍
每个组件有三部分组成
template:写html
script:写js
style:写css
<template>
<div class="about">
<h1>写html</h1>
</div>
</template>
<script>
js代码
</script>
<style>
css代码
</style>
vue-router的使用
1 以后,新建一个页面组件,写三部分
2 在router下的index.js内配置一下
const routes = [
{ // / 路径,显示Home这个页面组件
path: '/',
name: 'Home',
component: Home
},
{
path: '/order',
name: 'Order',
component: Order
},
{
path: '/about',
name: 'About',
// component: () => import('../views/About.vue')
component: About,
}
]
3 在根vue中写
<div id="app">
<router-view/>
</div>
4 以后要跳转到某个页面
<router-link to="/路径">
<button>点我跳转到order</button>
</router-link>
在项目中新建组件和使用
1 在components文件夹创建一个 xx.vue
2 在其他组件中使用
-在scripts中
import HelloWorld from '../components/HelloWorld.vue'
export default {
name: 'Home',
components: {
HelloWorld
}
}
3 在html中直接使用
<HelloWorld/>
js导入导出语法(了解)
1 有一些变量,函数,想在其他地方都用,可以写成一个包
新建一个文件夹,在文件夹中写index.js
在内部写函数,写变量,最后一定要导出
var name='lqz'
function add(a,b) {
return a+b
}
export default {
name,
add
}
2 在想用的位置,导入使用即可
import xx from '../lqz'
console.log(xx.add(1,2))
使用axios
1 安装 cnpm install axios
2 导入使用
import axios from 'axios'
axios.get('api/index/').then(res => {})
前端代理
1 vue.config.js中module.exports = {
devServer: {
proxy: {
'/api': {
target: 'http://127.0.0.1:8000',
changeOrigin: true
}
}
},
}
2 使用axios发送请求
mounted() {
axios.get('api/index/').then(res => {
console.log(res.data)
this.data_list = res.data.data.films
})
}
bootstrap和jq的使用
1 安装
cnpm install jquery
cnpm install bootstrap@3
2 配置vue.config.js中
const webpack = require("webpack");
module.exports = {
configureWebpack: {
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery",
"window.$": "jquery",
Popper: ["popper.js", "default"]
})
]
}
};
3 main.js中
import 'bootstrap'
import 'bootstrap/dist/css/bootstrap.min.css'
elementui的使用
1 安装
cnpm install element-ui -S
2 main.js中配置
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);