1 vue
1 vue介绍
1-1 前端发展史
# 1 html(5),css(3),javascript=(ECMA:5,补充es6语法,最新:13,bom:浏览器对象,dom:文档对象)--》编写一个个的页面 -> 给后端(PHP、Python、Go、Java) -> 后端嵌入模板语法(dtl:django的模版语法 xx.html ) -> 后端渲染完数据 -> 返回数据给前端 -> 在浏览器中查看
# 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:一套编码 编到14个平台----》学习vue的性价比很高
# 9 在不久的将来 ,前端框架可能会一统天下
# ts和es:
typescript:微软出的脚本语言,强类型,微软开发的一个开源的编程语言,通过在JavaScript的基础上添加静态类型定义构建而成
ecma:标准---》js语言,弱类型
typescript是js的超集
写前端可以使用js,也可以使用ts,ts兼容js的
js:历史遗留了很多坑
1-2 vue介绍
# Vue (读音 /vjuː/,类似于 view)--->1 js框架(jquery)--->2 渐进式框架(单个页面使用vue,整个项目都使用vue)
是一套用于构建用户界面的渐进式框架
与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用
Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合
# 官网:https://cn.vuejs.org/
# Vue 版本问题:两个版本(些许差距,基础都是一样的)
-2.x版本:老版本
-3.x版本:完整支持ts语法,2020年---》
-vue: 正处于转型期,大量公司还在用vue2,少量公司在用vue3
# 特点
-通过 HTML、CSS、JavaScript构建应用--》要有这些东西基础
-不断繁荣的生态系统,可以在一个库和一套完整框架之间自如伸缩
-20kB min+gzip 运行大小 超快虚拟 DOM 最省心的优化
# M-V-VM思想
-django:MTV mvc架构
-MVP:移动端会使用
-Vue:M-V-VM 架构---》js的变量---》写到dom(文档)中
-Model :vue对象的data属性里面的数据,这里的数据要显示到页面中,js里面有变量
-View :vue中数据要显示的HTML页面,在vue中,也称之为“视图模板” (HTML+CSS)
-ViewModel:vue中编写代码时的vm对象,它是vue.js的核心,负责连接 View 和 Model数据的中转,保证视图和数据的一致性,所以前面代码中,data里面的数据被显示中p标签中就是vm对象自动完成的(双向数据绑定:JS中变量变了,HTML中数据也跟着改变)
-以后不需要咱们操作dom了---》因为有vm这层---》jquery选择器,原生js 完全用不到了---》jq已经完成自己的历史使命了,慢慢退出舞台了
# 组件化开发、单页面开发
-组件化开发:把某些可能会多次使用的 htm,css,js,写成单独的,以后直接引入即可
-单页面开发:如果是vue项目,整个项目其实就一个 index.html 页面
-以后都是只有一个index.html 看到的页面变化,不是多个html页面在变化,而是组件的替换

2 vue的快速使用
# 补充:工欲善其事必先利其器---》咱们要开发vue,需要有一个比较趁手 集成开发工具(IDE)
-vscode:微软出的,不仅可以写前端,还可以写python,go..... 免费的
-Jetbrains捷克的公司公司出的:全家桶:pycharm,goland,IDEA(java),phpstorm,webstorm(前端)。。。
-收费,挺贵 全家桶的授权:599刀一年 单版本授权 199刀 一年
-破解:pycharm本身跟webstorm师出同门
-直接使用Pycharm---》vue的插件,就可以写vue了----》讲课用,不需要再多下一个编辑器
-直接下载webstorm--》破解方案跟pycharm完全一样
# 使用Pycharm开发---》下载后有vue代码提示,不下也能开发vue
-新建一个项目(python项目也可以)
-装一个vue的插件:setting中搜plugins---》vue---》安装---》ok---》apply
# Vue 就是一个js框架----》把源代码下载下来(cdn),引入到页面中去
-先用vue2的讲:基础内容是一样的
-拿到vue2的源码,放在咱们工程中--》js文件夹下vue.js
-渐进式框架---》在一个html中使用vue---》跟之前使用jq是一模一样
下载地址:
https://cdn.jsdelivr.net/npm/vue/dist/vue.js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!-- 引入vue,跟之前引入jquery是一样的-->
<script src="./js/vue.js"></script>
<title>标题</title>
</head>
<body>
<div id="app">
<!--以后在这div内部,就可以写vue的语法了,插值语法,把变量放在{{}}内,它就会把变量渲染在这-->
<h1>{{name}}</h1>
</div>
</body>
<script>
// 写js代码,new 得到一个vue对象,传入配置项,传入一个对象,有key,有value
new Vue({
el: '#app', // 根据id 找到div,这个div就被vue托管了,以后div中就可以写vue的语法了
data: {
name: 'lqz' // 定义了一个变量 name
}
})
</script>
</html>
3 vue模板渲染
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="./js/vue.js"></script>
<title>标题</title>
</head>
<body>
<div id="app">
<h1>渲染变量</h1>
<p>我的名字:{{name}}</p>
<p>我的年龄:{{age}}</p>
<p>数组:{{l}}</p>
<p>数组取值:{{l[1]}}</p>
<p>对象:{{obj}}</p>
<p>对象取值:{{obj['age']}}</p>
<p>对象取值:{{obj.name}}</p>
<p>标签:{{s}}</p>
<h1>渲染函数--后面讲</h1>
<h1>渲染表达式:三目运算符,一定不要写太长</h1>
<p>{{age > 20 ? '男人' : '男孩'}}</p>
<p>{{age == 19}}</p>
</div>
</body>
<script>
new Vue({
el: '#app',
data: {
name: 'lqz',
age: 19,
l: [1, 2, 3], // js中叫数组,python中叫列表
obj: {name: '彭于晏', age: 40}, // js中叫对象,python中叫字典 对象取值不加引号表示变量
s: '<input type="text">',
t: 10 > 9 ? '大于' : '小于' // 跟python中的三元表达式是一样的 t= 条件 ? '符合条件':'不符合'
// t:'大于'
}
})
</script>
</html>
4 vue指令
# vue中有很多指令,放在标签上,以v-开头的,称之为指令,每个指令都能完成相应操作
<p v-html='js变量,函数,表达式'> </p>
4-1 文本指令
# v-html:把变量的内容当html渲染到标签中去(字符串是标签,会完整渲染)
# v-text:把变量内容当字符串写到到标签中(字符串是标签,不会渲染成标签),如果原来标签有内容,会去掉
-可以完成跟 {{}} 一样的功能,但是还是不一样的
# v-show:只能跟 true 或 false 或 表达式运算结果是布尔类型,控制标签的显示与否
# v-if :只能跟 true 或 false 或 表达式运算结果是布尔类型,控制标签的显示与否
# vue中面试题:v-if和v-show区别是什么?
-v-if:如果是false,不显示,标签也不存在(删除和添加标签,效率低)
-v-show,如果是false,不显示,但是标签存在,只是通过样式 dispaly=none控制的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="./js/vue.js"></script>
<title>标题</title>
</head>
<body>
<div id="app">
<h1>v-html</h1>
<p>{{s}}</p>
<p v-html="s"></p>
<div v-html="s"></div>
<h1>v-test</h1>
<p v-text="s">美女</p>
<h1>v-show和v-if</h1>
<div v-show="b2">美女</div>
<div v-if="b1">帅哥</div>
</div>
</body>
<script>
new Vue({
el: '#app',
data: {
s: '<input type="text">',
b1: true,
b2: false
}
})
</script>
</html>
补充:
MVVM:model的数据变,view也跟着变;只要view变化,model也跟着变化
# 双向数据绑定
# 把new Vue后的对象赋值给变量vm
var vm = new Vue({
el: '#app',
data: {
s: '<input type="text">',
b1: true,
b2: false
}
})
# 以后从vm中可以通过 vm._data 取到 实例化的时候的data
# 以后也可以从vm.变量名取到data中的变量
# 在控制台修改变量的值,页面会立马跟着变化 ---》以后只需要修改变量值即可,不需要操作dom了
# 就是后台变 或者数据库的数据变化,前端就变?不是
4-2 事件指令
# v-xx 放在标签中就是指令,指令就能完成不同的功能
# v-on:事件名='函数' : 给这个标签绑定一个事件,当触发这个事件,就会执行函数
-事件:click,blur,dbclick。。。很多
-函数 必须写在methods 对象内,可以使用es6的对象写法
# 重点:
v-on:事件名='函数' 可以简写成 @事件名='函数'(以后都用它)
# 补充
-html:标签
-css:样式(好看) bootstrap是css样式,element-ui
-js:动起来 jquery是js框架,vue是js框架,react
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<script src="./js/vue.js"></script>
<title>标题</title>
</head>
<body>
<div id="app">
<!-- <button class="btn btn-danger" v-on:click="handleClick">点我看美女</button>-->
<button class="btn btn-danger" @click="handleClick">点我看美女2</button>
<br>
<!-- 写个按钮,一点击就显示美女图片,再点击一次就不显示了-->
<button @click="handleShow">看我美女显示和消失</button>
<br>
<!-- <img v-show="zs" src="https://tva1.sinaimg.cn/large/00831rSTly1gd1u0jw182j30u00u043b.jpg" alt="" height="500px" width="500px">-->
<img v-if="zs" src="https://tva1.sinaimg.cn/large/00831rSTly1gd1u0jw182j30u00u043b.jpg" alt="" height="500px" width="500px">
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
zs:true,
}, // 变量写在这里
methods: {
// 方式一:es5的语法
// handleClick: function () {
// alert('美女')
// }
// 方式二:常用的,es6的语法
handleClick() {
alert('美女')
},
handleShow(){
// 修改show的值为 !show
// this代指的是vm对象,Vue对象
this.zs=!this.zs
}
}, // 函数写在这里
})
// es6 语法的对象写法
// var obj = {'name': 'lqz', 'age': 19}
// var obj1 = {name: 'lqz', age: 19}
// name = 'lqz'
// age = 19
// var onj2 = {name, age} // 等同于{name: 'lqz', age: 19} es6 对象写法
</script>
</html>
5 属性指令
# v-bind:属性名="变量"
-标签会有很多属性 <a href=""></a> <img src="" > <p name="xxx"></p> <button class="btn">点我</button>
-可以绑定标签的任意属性
v-bind可以简写成 : -----> :属性='变量'
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="./js/vue.js"></script>
<title>标题</title>
</head>
<body>
<div id="app">
<!-- <img v-bind:src="url" alt="">-->
<h1>点我随机弹美女图片</h1>
<button @click="handleClick">点我</button>
<br>
<!-- <img v-bind:src="url" alt="" width="500px" height="500px">-->
<img :src="url" alt="" width="500px" height="500px">
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
url: 'https://tva1.sinaimg.cn/large/00831rSTly1gd1u0jw182j30u00u043b.jpg',
l: ['https://img2.woyaogexing.com/2022/10/13/05e406595e217e0c!400x400.jpg',
'https://img2.woyaogexing.com/2022/10/13/c03408591b068c18!400x400.jpg',
'https://img2.woyaogexing.com/2022/10/13/f810d999375f7f1c!400x400.jpg']
},
methods: {
handleClick() {
// 随机从生成0--3的数字
this.url = this.l[Math.floor(Math.random()*3)];
}
}
})
</script>
</html>
6 style和class属性
# 属性指令:style和class属性特殊一点
# // class属性可以绑定:字符串,数组(常用,class由多个类组成,数组跟它最搭),对象
# // style 属性可以绑定: 字符串,数组,对象(常用)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="./js/vue.js"></script>
<title>标题</title>
<style>
.red {
color: crimson;
}
.back {
background: greenyellow;
}
.size {
font-size: 50px;
}
</style>
</head>
<body>
<div id="app">
<h1>class的三种绑定方式</h1>
<!-- <div :class="class_str">-->
<!-- <div :class="class_list">-->
<div :class="class_obj">
我是一个div
</div>
<hr>
<h1>style的三种绑定方式</h1>
<!-- <div style="font-size: 50px;background: pink;color: green">-->
<!-- <div :style="style_str">-->
<!-- <div :style="style_list">-->
<div :style="style_obj">
我是第二个div
</div>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
// class:字符串,数组(常用,class由多个类组成,数组跟它最搭),对象
class_str: 'red size',
class_list: ['red', 'size'], // 如果咱么向数组末尾最近一个类名,div样式就变了
class_obj: {red: true, size: false, back: false},
// style :字符串,数组,对象
style_str: 'font-size: 50px;background: pink',
style_list: [{'font-size': '50px'}, {'background': 'pink'}, {'color': 'green'}],
// style_list: [{fontSize: '50px'}, {background: 'pink'}, {color: 'green'}], // 跟上面一样,如果是 - 相连的两个单词可以改成驼峰形式
style_obj: {fontSize: '50px', background: 'pink', color: 'green'}, // style 来讲,它用的多
},
methods: {}
})
</script>
</html>
7 条件渲染
7-1 if-else
# 指令:实现符合某个条件,就显示某个标签
v-if v-else-if v-else
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="./js/vue.js"></script>
<title>标题</title>
<style>
</style>
</head>
<body>
<div id="app">
<p v-if="score>90">优秀</p>
<p v-else-if="score>70 && score<=90">良好</p>
<p v-else-if="score>60 && score<=70">及格</p>
<p v-else>不及格</p>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
score: 98,
},
})
</script>
</html>
7-1 for
# v-for 指令
-可以循环:数组 v-for="(url,index) in urls" 位置不能换
-可以循环:对象 v-for="(value,key) in obj" 如果只接收一个值,这个值就是value
-可也循环:数字 v-for="i in num" 从1开始,循环到数字的个数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="./js/vue.js"></script>
<title>标题</title>
<style>
</style>
</head>
<body>
<div id="app">
<h1>把所有美女,一行行显示在页面中</h1>
<ul>
<!-- <li v-for="url in urls">-->
<li v-for="(url,index) in urls">
<h3>第{{index + 1}}张美女</h3>
<img :src="url" alt="" height="100px" width="100px">
</li>
</ul>
<h1>循环对象</h1>
<!-- <p v-for="(value,key) in obj">key值为:{{key}},value值为:{{value}}</p>-->
<p v-for="value in obj">value值为:{{value}}</p>
<h1>循环数字</h1>
<p v-for="i in num">循环到了第:{{i}}</p>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
urls: ['https://img2.woyaogexing.com/2022/10/13/05e406595e217e0c!400x400.jpg',
'https://img2.woyaogexing.com/2022/10/13/c03408591b068c18!400x400.jpg',
'https://img2.woyaogexing.com/2022/10/13/f810d999375f7f1c!400x400.jpg'],
obj: {name: 'lqz', age: 19, bobby: '篮球'} , // hash类型 hashmap map 字典 对象 都是没有顺序
num:4
},
})
</script>
</html>
使用v-if和v-for写个购物车显示与不显示的案例
== 比较值是否一样
=== 比较类型和值是否一样
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="./js/vue.js"></script>
<link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<title>标题</title>
</head>
<body>
<div id="app">
<div class="container-fluid">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<div v-if="!good_list.length==0">
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>商品id号</th>
<th>商品名字</th>
<th>商品价格</th>
<th>商品数量</th>
</tr>
</thead>
<tbody>
<tr v-for="good in good_list">
<th scope="row">{{good.id}}</th>
<td>{{good.name}}</td>
<td>{{good.price}}</td>
<td>{{good.num}}</td>
</tr>
</tbody>
</table>
</div>
<div v-else>
空空如也
</div>
<hr>
<button @click="handleClick">点我刷新购物车</button>
</div>
</div>
</div>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
good_list: []
},
methods: {
handleClick() {
// 跟后端交互,拿到了数据
this.good_list = [
{id: 1, name: '小汽车', price: 100000, num: 1},
{id: 2, name: '钢笔', price: 6, num: 10},
{id: 3, name: '脸盆', price: 12, num: 6},
{id: 4, name: '水杯', price: 66, num: 5},
]
}
}
})
</script>
</html>
8 数据双向绑定
# input :text,password,select...
# text文本类型的双向数据绑定
-使用 :value='变量' 单向数据绑定,页面变化,变量不会跟着变---》一般不用
-使用 v-model='变量' 双向数据绑定,页面变化,变量变化都会相互影响
# 使用
<input type="text" v-model="v">
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="./js/vue.js"></script>
<link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<title>标题</title>
</head>
<body>
<div id="app">
<h1>v-model 只针对于input</h1>
请输入内容:<input type="text" v-model="v"> ---->{{v}}
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
v: '美女'
},
})
</script>
</html>
8-1 v-model进阶
# v-model 进阶之
lazy:双向数据绑定,只要修改输入框的值,就再更新数据,耗费资源,加了lazy后,等不输入了,变量再变化
number:输入框,只接收数字部分,如果输入了 123asdfasd,只保留123 数字部分
trim: 去掉输入内容前后的空白
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
<h1>v-model进阶</h1>
<p><input type="text" v-model.lazy="a">{{a}}</p>
<p><input type="text" v-model.number="b">{{b}}</p>
<p><input type="text" v-model.trim="c">{{c}}</p>
</div>
</body>
<script>
var vm = new Vue({
el: '.app',
data: {
a:'',
b:'',
c:'',
},
})
</script>
</html>
9 事件处理
# 事件:click,dbclick blur, input, change。。。
单击 双击 失去焦点 输入内容 发生变化
# input框会有blur, input, change 事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="./js/vue.js"></script>
<title>标题</title>
</head>
<body>
<div id="app">
<h1>失去焦点事件blur</h1>
<!-- 请输入名字:<input type="text" v-model="name" @blur="handleBlur">-->
<h1>change事件:失去焦点并数据发生变化才会触发</h1>
<!-- 请输入名字:<input type="text" v-model="name" @change="handleChange">-->
<h1>input事件:只要输入内容会触发</h1>
请输入名字:<input type="text" v-model="name" @input="handleInput">
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
name: '彭于晏'
},
methods: {
handleBlur() {
alert(this.name)
},
handleChange() {
console.log(this.name) // 跟python中print一样
},
handleInput(){
console.log(this.name)
}
}
})
</script>
</html>
9-1 过滤案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="./js/vue.js"></script>
<title>标题</title>
</head>
<body>
<div id="app">
<h1>过滤案例</h1>
<input type="text" v-model="search" @input="handleInput">
<ul>
<li v-for="item in newdataList">{{item}}</li>
</ul>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
search: '',
dataList: ['a', 'at', 'atom', 'atommon', 'be', 'beyond', 'cs', 'csrf', 'csrffe'],
newdataList: ['a', 'at', 'atom', 'atommon', 'be', 'beyond', 'cs', 'csrf', 'csrffe']
},
methods: {
handleInput() {
// this 指向问题
// 这个位置this是vue对象
// var _this = this
// this.dataList = this.dataList.filter(function (item) {
// console.log('----', _this) // this 还是vue对象吗?是浏览器对象
// return item.indexOf(_this.search) > -1
// })
// 使用es6的语法解决
this.newdataList = this.dataList.filter(item => {
// console.log('----', this) // 如果使用剪头函数,this还是vue(剪头函数没有自己的this)
return item.indexOf(this.search) > -1
})
}
}
})
// 补充:数组的内置方法,filter,传匿名函数进去,匿名函数如果返回true这个就保留,如果返回false,就不保留
// var search = 'a'
// var l = ['a', 'at', 'atom', 'atommon', 'be', 'beyond', 'cs', 'csrf', 'csrffe']
// var ll = l.filter(function (item) {
// return item.indexOf(search) > -1
// })
// console.log(ll)
// 补充:字符串有个indexOf,返回索引,如果大于-1,表示字字符串在当前字符串中
// var s='lqz is handsome'
// var res=s.indexOf('zoo') // 如果me在字符串中,就返回me在字符串的索引位置
// console.log(res)
// es6 的箭头函数
// 传统写法
// var a=function (name,age){
// console.log(name)
// }
// a("lxx")
// //es6 箭头函数 匿名函数的另一种写法
// var a= (name,age) =>{
// console.log(name)
// }
</script>
</html>
9-2 事件修饰符
# 放在事件后的
@click.once='函数'
.stop 只处理自己的事件,不再冒泡给父标签(阻止事件冒泡)
.self 只处理自己的事件,子控件冒泡的事件不处理
.prevent 阻止a链接的跳转
.once 事件只会触发一次(适用于抽奖页面)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="./js/vue.js"></script>
<title>标题</title>
</head>
<body>
<div id="app">
<h1>点击子标签,父标签的事件也触发:事件冒泡</h1>
<h2>阻止事件冒泡:点子标签,父标签不触发 stop</h2>
<ul @click="handleUl">
<li @click.stop="handleLi">点我看美女</li>
<li>点我看帅哥</li>
</ul>
<h1>点击子标签,父标签的事件也触发:事件冒泡</h1>
<h2>子标签的冒泡不处理:父标签写self,父标签只处理自己的事件,冒泡的事件不管</h2>
<ul @click.self="handleUl">
<li @click="handleLi">点我看美女</li>
<li>点我看帅哥</li>
</ul>
<h1>prevent 阻止a链接的跳转</h1>
<a href="http://www.liuqingzheng.top" @click.prevent="handleA">点我看美女</a>
<h1>once 只执行一次</h1>
<button @click.once="handleButton">点我秒杀</button>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {},
methods: {
handleLi() {
console.log("li被点击了")
},
handleUl() {
console.log("ul被点击了")
},
handleA() {
console.log('a被点击了,不会再跳转了')
},
handleButton() {
alert('秒杀成功')
}
}
})
</script>
</html>
9-3 按键修饰符
# 事件:input,change 除此之外还有 【按键】被按下和被抬起的事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="./js/vue.js"></script>
<title>标题</title>
</head>
<body>
<div id="app">
<h1>按键修饰符</h1>
<!-- <input type="text" @keyup="handleKeyUp($event)">-->
<input type="text" @keyup.enter="handleKeyUp($event)">
<input type="text" @keyup.esc="handleKeyUp($event)">
<input type="text" @keyup.="handleKeyUp($event)">
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {},
methods:{
handleKeyUp(event){
console.log('sdasfd')
if(event.code=='Enter') {
console.log('enter键被抬起了,开始搜索')
}
}
}
})
</script>
</html>
10 表单控制
# form表单---》input标签,单选,多选按钮
# 单选,多选的 v-model的绑定
# 1 checkbox的单选---》v-model绑定一个布尔值---》只要选中布尔就为true,反之亦然
# 2 radio的单选----》v-model绑定字符串----》选中字符串就是value对应的值
# 3 checkbox的多选---》v-model绑定一个数组---》多个选中,数组就有多个值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
<h1>表单控制之checkbox单选</h1>
<p>用户名:<input type="text" v-model="username"></p>
<p>密码:<input type="password" v-model="password"></p>
<p><input type="checkbox" v-model="isCheck">记住密码</p>
<p>
<input type="radio" v-model="gender" value="1">男
<input type="radio" v-model="gender" value="2">女
<input type="radio" v-model="gender" value="0">未知
</p>
<p>爱好(多选):</p>
<p>
<input type="checkbox" v-model="hobby" value="篮球"> 篮球
<input type="checkbox" v-model="hobby" value="足球"> 足球
<input type="checkbox" v-model="hobby" value="橄榄球"> 橄榄球
<input type="checkbox" v-model="hobby" value="乒乓球"> 乒乓球
</p>
<!-- <hr>-->
<!-- 密码是否选中:{{isCheck}}-->
<!-- <hr>-->
<!-- 性别是:{{gender}}-->
<!-- <hr>-->
<!-- 爱好是:{{hobby}}-->
<hr>
<input type="submit" value="提交" @click="handleSubmit">
</div>
</body>
<script>
var vm = new Vue({
el: '.app',
data: {
username: '',
password: '',
isCheck: false,
gender: '',
hobby:[],
},
methods: {
handleSubmit(){
//假设发送ajax到后端了
console.log(this.username)
console.log(this.password)
console.log(this.isCheck)
console.log(this.gender)
console.log(this.hobby)
}
},
})
</script>
</html>
11 js的循环方式
listAt = [1,2,3,4]
// 1 方式一:最基本的
for (let i=0; i<listAt.length; i++){
console.log(i)
}
// 0 1 2 3 4
// 2 in 循环 es5的语法
for (let item in listAt){
console.log(item)
}
// 0 1 2 3 4
// 3 for of es6的循环
for (item of listAt){
console.log(item)
}
// 1 2 3 4
// 4 数组foreach循环 (数组)
listAt.forEach(function (value, index) {
console.log('value-->', value, 'index-->', index)
})
// value--> 1 index--> 0
// value--> 2 index--> 1
// value--> 3 index--> 2
// value--> 4 index--> 3
// 5 jq $each 循环
$.each(listAt, function (index, value) {
console.log('value-->', value, 'index-->', key)
})
// value--> 1 index--> 0
// value--> 2 index--> 1
// value--> 3 index--> 2
// value--> 4 index--> 3
11-1 基本购物车案例
点击查看代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="./js/vue.js"></script>
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
</head>
<body>
<div class="app">
<div class="container-fluid">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<div style="margin-top: 30px">
<h1>购物车案例</h1>
<table class="table table-bordered">
<thead>
<tr>
<th>商品id</th>
<th>商品名字</th>
<th>商品价格</th>
<th>商品数量</th>
</tr>
</thead>
<tbody>
<tr v-for="good in goodList">
<th>{{good.id}}</th>
<td>{{good.name}}</td>
<td>{{good.price}}</td>
<td>{{good.count}}</td>
<td><input type="checkbox" v-model="buyGoods" :value="good"></td>
</tr>
</tbody>
</table>
<hr>
选中的商品:{{buyGoods}}
<hr>
总价格是:{{getPrice()}}
</div>
</div>
</div>
</div>
</div>
</body>
<script>
var vm = new Vue({
el: '.app',
data: {
goodList: [
{id: '1', name: '小汽车', price: 150000, count: 2},
{id: '2', name: '鸡蛋', price: 2, count: 1},
{id: '3', name: '饼干', price: 10, count: 6},
{id: '4', name: '钢笔', price: 15, count: 5},
{id: '5', name: '脸盆', price: 30, count: 3},
],
buyGoods:[],
},
methods:{
getPrice(){
var total=0
// 方式一:数组的循环:循环计算选中的商品价格
// this.buyGoods.forEach(function (v,i){
// total+=v.price*v.count
// })
// 方式二:es6 的 of 循环
for (item of this.buyGoods){
// console.log(item)
total+=item.price*item.count
}
return total
}
}
})
// var a=[33,22,888]
// a.forEach(function (value,index){
// console.log(value)
// console.log(index)
// })
// 对象没有forEach
// jq 的循环
// var a=[33,22,888]
// // var obj={name:'lqz',age:19}
// $.each(a,function (key,value){
// console.log(key)
// console.log(value)
// })
</script>
</html>
11-2 带全选,全不选
点击查看代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
<div class="container-fluid">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<div style="margin-top: 30px">
<h1>购物车案例</h1>
<table class="table table-bordered">
<thead>
<tr>
<th>商品id</th>
<th>商品名字</th>
<th>商品价格</th>
<th>商品数量</th>
<th><input type="checkbox" v-model="checkAll" @change="handleCheckAll"></th>
</tr>
</thead>
<tbody>
<tr v-for="good in goodList">
<th>{{good.id}}</th>
<td>{{good.name}}</td>
<td>{{good.price}}</td>
<td>{{good.count}}</td>
<td><input type="checkbox" v-model="buyGoods" :value="good" @change="handleCheckOne"></td>
</tr>
</tbody>
</table>
<hr>
选中的商品:{{buyGoods}}
<hr>
总价格是:{{getPrice()}}
</div>
</div>
</div>
</div>
</div>
</body>
<script>
var vm = new Vue({
el: '.app',
data: {
goodList: [
{id: '1', name: '小汽车', price: 150000, count: 2},
{id: '2', name: '鸡蛋', price: 2, count: 1},
{id: '3', name: '饼干', price: 10, count: 6},
{id: '4', name: '钢笔', price: 15, count: 5},
{id: '5', name: '脸盆', price: 30, count: 3},
],
buyGoods:[],
checkAll:false,
},
methods:{
getPrice(){
var total=0
// 方式二:es6 的 of 循环
for (item of this.buyGoods){
// console.log(item)
total+=item.price*item.count
}
return total
},
handleCheckAll(){
if(this.checkAll){
// 用户全选了,只需要把 buyGoods的值变为goodList
this.buyGoods=this.goodList
}else {
this.buyGoods=[]
}
},
handleCheckOne(){
// 判断buyGoods长度,是否等于goodList,如果等于说明用户全选了,把checkAll设置为true
// 否则设置为false
// if(this.buyGoods.length==this.goodList.length){
// // 说明用户通过单选,选全了
// this.checkAll=true
// }else {
// this.checkAll=false
// }
// 简写成
this.checkAll=(this.buyGoods.length==this.goodList.length)
}
}
})
</script>
</html>
11-3 带加减
点击查看代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
<div class="container-fluid">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<div style="margin-top: 30px">
<h1>购物车案例</h1>
<table class="table table-bordered">
<thead>
<tr>
<th>商品id</th>
<th>商品名字</th>
<th>商品价格</th>
<th>商品数量</th>
<th><input type="checkbox" v-model="checkAll" @change="handleCheckAll"></th>
</tr>
</thead>
<tbody>
<tr v-for="good in goodList">
<th>{{good.id}}</th>
<td>{{good.name}}</td>
<td>{{good.price}}</td>
<td><button @click="handleJian(good)">-</button>{{good.count}}<button @click="good.count++">+</button></td>
<td><input type="checkbox" v-model="buyGoods" :value="good" @change="handleCheckOne"></td>
</tr>
</tbody>
</table>
<hr>
选中的商品:{{buyGoods}}
<hr>
总价格是:{{getPrice()}}
</div>
</div>
</div>
</div>
</div>
</body>
<script>
var vm = new Vue({
el: '.app',
data: {
goodList: [
{id: '1', name: '小汽车', price: 150000, count: 2},
{id: '2', name: '鸡蛋', price: 2, count: 1},
{id: '3', name: '饼干', price: 10, count: 6},
{id: '4', name: '钢笔', price: 15, count: 5},
{id: '5', name: '脸盆', price: 30, count: 3},
],
buyGoods:[],
checkAll:false,
},
methods:{
getPrice(){
var total=0
// 方式二:es6 的 of 循环
for (item of this.buyGoods){
// console.log(item)
total+=item.price*item.count
}
return total
},
handleCheckAll(){
if(this.checkAll){
// 用户全选了,只需要把 buyGoods的值变为goodList
this.buyGoods=this.goodList
}else {
this.buyGoods=[]
}
},
handleCheckOne(){
// 判断buyGoods长度,是否等于goodList,如果等于说明用户全选了,把checkAll设置为true
// 否则设置为false
// if(this.buyGoods.length==this.goodList.length){
// // 说明用户通过单选,选全了
// this.checkAll=true
// }else {
// this.checkAll=false
// }
// 简写成
this.checkAll=(this.buyGoods.length==this.goodList.length)
},
handleJian(item){
if(item.count<=1){
alert('太少了,受不了了')
}else {
item.count--
}
}
}
})
</script>
</html>
12 vue的生命周期
-
组件化开发
vue的实例:vm 以及后面学的组件:vc 它们有生命周期:从创建开始,到销毁 vue中总共生命周期有8个钩子函数(4对),依次调用 -
钩子的意思:aop的体现(面向切面编程)
beforeCreate 创建Vue实例,组件实例对象创建 之前调用 created 创建Vue实例成功后调用(咱们用的对,可以在此处发送ajax请求后端数据) beforeMount 渲染DOM之前调用 mounted 渲染DOM之后调用 ---初始化完成了---- beforeUpdate 重新渲染之前调用(数据更新等操作时,控制DOM重新渲染) updated 重新渲染完成之后调用 ---一直在转圈---- ----销毁组件--- beforeDestroy 销毁之前调用 destroyed 销毁之后调用 -
重点
-created多一些:在这里面发送ajax请求,data的数据好了后,再发请求,去后端拿数据 -updated:数据变化,页面更新完后,执行它 -destroyed:组件销毁,会触发它,也会用 -组件创建了,起了个定时器,不停地打印hello world(每隔一段时间执行一个函数,延迟调用) -如果组件销毁了,定时器没有被销毁,会出现定时器还在执行的情况, -所以要在destroyed中把定时器取消掉,资源清理工作 -vm实例和组件实例都有8个生命周期钩子函数 -只要写了钩子函数,就会执行,不写就不会执行 -
补充
# 面向过程编程 # OOP编程:面向对象编程 # AOP编程:面向切面编程(对面向对象编程的补充),java的spring框架大量的使用 -python中装饰器 AOP编程的体现 -drf源码,反序列化的源码,钩子函数,aop体现
13 后端交互(ajax,fetch和axios)
# 跨域问题: 前后端分离的项目会出现
-浏览器有个安全策略:不允许向不同域(地址+端口号)发送请求获取数据,浏览器的 同源策略
-解决跨域:
-后端的cors(跨域资源共享)技术:就是在响应头中加入允许即可
-nginx做代理。。。
# 原生js发送ajax请求,jq发送ajax请求,fetch发送ajax请求,axios发送ajax请求
-原生:new XMLHttpRequest() 老api,坑很多
-jq基于它封装,封装出了$.ajax ,屏蔽了很多问题
-官方觉得XMLHttpRequest坑很多,搞了个fetch,跟XMLHttpRequest是平级的,比它好用,但是不支持ie
-axios继续基于XMLHttpRequest封装了,一个发送ajax请求的模块
13-1 方式1:使用jq的ajax方法
# 原生js写ajax,jq帮咱们写好了,处理好了浏览器版本间的不兼容,可以直接用
$.ajax({
url: 'http://127.0.0.1:8000/test/',
type: 'get',
success: data => {
// 后端返回json格式字符串,$.ajax拿到字符串,转成了js的对象,给了data
this.name = data.name
this.age = data.age
}
})
13-2 方式2:使用fetch
fetch('http://127.0.0.1:8000/test/').then(res => res.json()).then(res => {
console.log(res)
this.name = res.name
this.age = res.age
})
13-3 方式3:使用第三方,axios(js模块)
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
axios.get('http://127.0.0.1:8000/test/').then(res=>{
console.log(res.data) // 真正后端给的数据(res.data 才是真正的数据)
this.name=res.data.name
this.age=res.data.age
})
13-4 小案例
点击查看代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div class="app">
<div>
<ul>
<li v-for="film in filmsList">
<h3>电影标题:{{film.name}}</h3>
<img :src="film.poster" alt="" width="200px" height="400px">
<p>简介:{{film.synopsis}}</p>
</li>
</ul>
</div>
</div>
</body>
<script>
var vm = new Vue({
el: '.app',
data: {
filmsList: []
},
methods: {},
created() {
axios.get('http://127.0.0.1:8000/films/').then(res => {
this.filmsList=res.data.data.films
})
}
})
</script>
</html>
14 计算属性
# 计算 属性:1 以后当属性用 2 只有关联的数据变化,才重新运算 3 有缓存,数据没有变化,页面再更新,它也不变化
# 案例:有个input,输入英文后,把首字母变成大写
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
<h1>计算属性</h1>
<!-- 最简单方式-->
<h2>最简单方法首字母变大写</h2>
<!-- <input type="text" v-model="name">-–>{{name.slice(0, 1).toUpperCase() + name.slice(1)}}-->
<h2>使用函数实现,页面只要更新,这个函数就会重新执行,比较耗费资源</h2>
<!-- <input type="text" v-model="name">-–>{{getUpper()}}-->
<input type="text" v-model="age">--->{{age}}
<h3>通过计算属性实现:计算属性只有在它的相关依赖发生改变时才会重新求值</h3>
<input type="text" v-model="name">--->{{upperName}}
</div>
</body>
<script>
var vm = new Vue({
el: '.app',
data: {
name: '',
age: 0
},
methods: {
getUpper() {
console.log('我执行了')
return this.name.slice(0, 1).toUpperCase() + this.name.slice(1)
}
},
computed: {
upperName() {
console.log('我是计算属性,我执行了')
return this.name.slice(0, 1).toUpperCase() + this.name.slice(1)
}
}
})
</script>
</html>
通过计算属性,重写过滤案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="./js/vue.js"></script>
<title>标题</title>
</head>
<body>
<div id="app">
<h1>过滤案例</h1>
<input type="text" v-model="search">
<ul>
<li v-for="item in newdataList">{{item}}</li>
</ul>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
search: '',
dataList: ['a', 'at', 'atom', 'atommon', 'be', 'beyond', 'cs', 'csrf', 'csrffe'],
},
// 只要input框中数据发生变化search,newdataList会重新运算,只要一运算,v-for重新循环,实现了联动
computed:{
newdataList(){
return this.dataList.filter(item => {
return item.indexOf(this.search) > -1
})
}
}
})
</script>
</html>
15 监听属性
watch: {
categoryType: function (val) {
console.log('name发生了变化')
console.log(val)
// 向后端发送请求,请求回相应分类的数据,展示
}
}
# 只要categoryType发送变化,就会执行对应的函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
<h1>监听属性</h1>
<span @click="categoryType='美女'">美女</span>|
<span @click="categoryType='帅哥'">帅哥</span>|
<span @click="categoryType='老头'">老头</span>
<div>
</div>
</div>
</body>
<script>
var vm = new Vue({
el: '.app',
data: {
categoryType: '',
},
watch: {
categoryType: function (val) {
console.log('name发生了变化')
console.log(val)
// 向后端发送请求,请求回相应分类的数据,展示
}
}
})
</script>
</html>
16 组件化开发
# 作用:扩展 HTML 元素,封装可重用的代码,目的是复用
-例如:有一个轮播,可以在很多页面中使用,一个轮播有js,css,html
-组件把js,css,html放到一起,有逻辑,有样式,有html
# 多组件页面和单组件页面
-官方推荐,以后一个组件是一个 xx.vue 文件 ---》编译
# Single-Page application,缩写为 SPA:以后vue项目只有一个页面,看到的页面变化都是组件间的切换
# 全局组件和局部组件
16-1 全局组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
<h1>全局组件</h1>
<navbar></navbar>
</div>
</body>
<script>
// 定义一个全局组件,在任意组件中都可以使用
var obj = {
template: `
<div>
<button @click="handleBack">后退</button>
我是一个组件-->{{name}}
<button>前进</button>
</div>
`,
data() {
return {
name:'lqz'
}
}, // 重点,data必须是个函数,返回一个对象,组件可以在多个地方重复使用,如果就是对象,导致多个组件共用同一个对象的数据,出现错乱
methods: {
handleBack(){
alert('后退了')
}
},
// 学的所有放在vm对象中的,都可以用
}
Vue.component('navbar', obj)
var vm = new Vue({
el: '.app',
data: {},
})
</script>
</html>
16-2 局部组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
<h1>全局组件</h1>
<navbar></navbar>
<hr>
<lqz></lqz>
</div>
</body>
<script>
// 定义一个局部组件-->只能在某个组件中使用
var obj = {
template: `
<div>
<button @click="handleBack">后退</button>
我是一个组件-->{{ name }}
<button>前进</button>
</div>
`,
data() {
return {
name: 'lqz'
}
}, // 重点,data必须是个函数,返回一个对象,组件可以在多个地方重复使用,如果就是对象,导致多个组件共用同一个对象的数据,出现错乱
methods: {
handleBack() {
alert('后退了')
}
},
// 学的所有放在vm对象中的,都可以用
components: {} // 知道就可以了
}
Vue.component('navbar', obj)
var vm = new Vue({
el: '.app',
data: {},
components: {
lqz: {
template: `
<div>
<h3>我是局部组件</h3>
<button>点我看美女</button>
</div>`,
data() {
return {}
},
methods: {}
}
}
})
</script>
</html>
17 组件通信
各个组件间,数据,方法,都是隔离的
17-1 父传子(自定义属性)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
<h1>通过自定义属性,实现父传子</h1>
<h3>父组件中name:{{name}}</h3>
<hr>
<navbar :myname="name" :age="age"></navbar>
<hr>
</div>
</body>
<script>
// 定义一个全局组件,在任意组件中都可以使用
Vue.component('navbar', {
template: `
<div>
<button>前进</button>
名字是:{{myname}}--->年龄是:{{age}}
<button>后退</button>
</div>`,
props:['myname','age']
})
var vm = new Vue({
el: '.app',
data: {
name:'彭于晏',
age:99
},
})
</script>
</html>
17-2 子传父(自定义事件)
子组件点击按钮=>子组件执行函数this.$emit('自定义事件名字') =》注册在组件上的【自定义事件】对应的函数执行
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
<h1>通过自定义事件,实现子传父</h1>
<h3>父组件中收到子组件传递对值为:{{name}}</h3>
<hr>
<navbar @myevent="handleReceive"></navbar>
<hr>
</div>
</body>
<script>
Vue.component('navbar', {
template: `
<div>
<input type="text" v-model="iname">---》{{ iname }}
<br>
<button @click="handleClick">点我吧iname传递到父组件中</button>
</div>`,
data() {
return {
iname: ''
}
},
methods: {
handleClick() {
// 触发自定义事件的执行,并且传入当前组件中的iname
this.$emit('myevent', this.iname)
// alert(this.iname)
}
}
})
var vm = new Vue({
el: '.app',
data: {
name: '',
},
methods: {
handleReceive(iname) {
this.name = iname
}
}
})
//子组件点击按钮=>子组件执行函数this.$emit('自定义事件名字') =》注册在组件上的【自定义事件】对应的函数执行
</script>
</html>
18 ref属性
# 组件间通信---》通过ref属性,vue提供了一个ref属性,可以放在任意标签
-放在普通标签,通过 this.$refs.ref对应的名字 就能拿到原生dom对象,使用原生操作该dom
-放在自定义组件上,通过 this.$refs.ref对应的名字 就能拿到 组件对象,就可以调用对象的函数,使用对象的变量
-父组件中,拿到了子组件对象,对象中的属性,方法可以直接用,直接改
# 通过ref,子传父
-因为在父中,可以拿到子的对象,子对象中的所有变量,方法,都可以直接用
# 通过ref,实现父传子
-因为在父中,可以拿到子的对象, 子对象.变量=父的变量
# vuex---》实现跨组件间通信
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
<h1>ref实现组件间通信</h1>
{{name}}<br>
<input type="text" v-model="name" ref="myinput">
<button @click="handleClick">点我打印</button>
<hr>
<navbar ref="mynavbar"></navbar>
<hr>
<button @click="handleClick1">点我</button>
</div>
</body>
<script>
Vue.component('navbar', {
template: `
<div>
<input type="text" v-model="iname">---》{{ iname }}
<br>
</div>`,
data() {
return {
iname: ''
}
},
methods: {
handleClick() {
console.log('执行了')
return 'xxx'
}
}
})
var vm = new Vue({
el: '.app',
data: {
name: '',
},
methods: {
handleClick() {
console.log(this.$refs.myinput) // 打印原生dom对象
console.log(this.$refs.myinput.value) // input的value值
this.$refs.myinput.value = 'lqz is big'
alert(this.name)
},
handleClick1(){
console.log(this.$refs.mynavbar) // 相当于拿到了再组件中的this(组件对象)
console.log(this.$refs.mynavbar.iname)
// this.name=this.$refs.mynavbar.iname
// 父组件中直接执行子组件的方法
// this.$refs.mynavbar.handleClick() // 调用子组件的方法
this.$refs.mynavbar.iname='sssss'
}
}
})
</script>
</html>
19 动态组件
<component> 元素,动态地绑定多个组件到它的 is 属性
<keep-alive> 保留状态,避免重新渲染
# 场景: 组件是谁不确定,通过 is 确定显示那个组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
<h1>动态组件</h1>
<ul>
<li @click="myType='home'">首页</li>
<li @click="myType='goods'">商品</li>
<li @click="myType='shopping'">购物</li>
</ul>
<!-- 动态组件,is是哪个组件名字,这里就会显示那个组件-->
<component :is="myType"></component>
</div>
</body>
<script>
Vue.component('home', {
template: `
<div>
<h2>首页</h2>
</div>`
})
Vue.component('goods', {
template: `
<div>
<h2>商品</h2>
</div>`
})
Vue.component('shopping', {
template: `
<div>
<h2>购物</h2>
</div>`
})
var vm = new Vue({
el: '.app',
data: {
myType: 'home',
},
})
//子组件点击按钮=>子组件执行函数this.$emit('自定义事件名字') =》注册在组件上的【自定义事件】对应的函数执行
</script>
</html>
19-1 keep-alive
主要的作用:用于保存input输入的值。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
<h1>动态组件</h1>
<ul>
<li @click="myType='home'">首页</li>
<li @click="myType='goods'">商品</li>
<li @click="myType='shopping'">购物</li>
</ul>
<!-- 动态组件,is是哪个组件名字,这里就会显示那个组件-->
<keep-alive>
<component :is="myType"></component>
</keep-alive>
</div>
</body>
<script>
Vue.component('home', {
template: `
<div>
<h2>首页</h2>
</div>`
})
Vue.component('goods', {
template: `
<div>
<h2>商品</h2>
要搜索的商品:<input type="text">
</div>`
})
Vue.component('shopping', {
template: `
<div>
<h2>购物</h2>
</div>`
})
var vm = new Vue({
el: '.app',
data: {
myType: 'home',
},
})
//子组件点击按钮=>子组件执行函数this.$emit('自定义事件名字') =》注册在组件上的【自定义事件】对应的函数执行
</script>
</html>
20 slot插槽
子组件中添加slot标签,在调用组件时,可以放入值。
20-1 不具名插槽
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
<h1>插槽</h1>
<hr>
<home>
<div>
<img src="https://pic.maizuo.com/usr/movie/0c5874a81c7969c8eb7ddee7b6ff46b3.jpg" alt="" width="200px"
height="300px">
</div>
</home>
<hr>
<home>
<div>
我是div
</div>
</home>
</div>
</body>
<script>
Vue.component('home', {
template: `
<div>
<h2>首页</h2>
<slot></slot>
</div>`
})
var vm = new Vue({
el: '.app',
data: {
myType: 'home',
},
})
</script>
</html>
20-2 具名插槽
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
<h1>插槽</h1>
<hr>
<home>
<img src="https://pic.maizuo.com/usr/movie/0c5874a81c7969c8eb7ddee7b6ff46b3.jpg" alt="" width="200px"
height="300px" slot="bottom">
<div slot="top">
我是div
</div>
</home>
<hr>
</div>
</body>
<script>
Vue.component('home', {
template: `
<div>
<slot name="top"></slot>
<p>我是子组件</p>
<slot name="bottom"></slot>
</div>`
})
var vm = new Vue({
el: '.app',
data: {
myType: 'home',
},
})
</script>
</html>

浙公网安备 33010602011771号