提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
Vue目录
一、Vue是什么?
Vue是一套用于构建用户界面的渐进式框架.
Vue为MVVM框架模式
M – model
v – view 视图 – T–template 就是html
VM是vue框架的核心,数据驱动视图的核心功能
二、基础内容
1.ES6
ECMAScript 6(简称ES6)是于2015年6月正式发布的JavaScript语言的标准,在Vue中大量使用,同时Vue也支持ES5.
2.ES6基本语法
ECMAScript 6(简称ES6)是于2015年6月正式发布的JavaScript语言的标准,在Vue中大量使用,同时Vue也支持ES5.
ES6使用let声明变量,const声明常量
代码如下:
var a = 'xx' //es5
let b = 'oo' //es6
let 声明变量的特点
1 不在从属于顶层对象window
let username = 'chao'
window.username;
结果:undefined
2 变量不能在var重复声明
3 不存在变量提升
console.log(hh2);
var hh2 = 'ss';
结果: undefined
console.log(hh); // 报错
let hh = 'ss';
const声明常量,不能修改
const Pi = 3.1415926....
const Pi = 11 //报错
模板语法
let a = 'xx'
let name = `${a}oo`
name:结果"xxoo"
3.ES5和ES6函数对比
ES5函数代码如下(示例):
// es5
function add(x,y){
return x+y
}
add(1,2);
// 匿名函数
var add = function(x){
return x
}
ES6函数代码如下(示例):
// es6
// 匿名函数
let add = function(x){
return x
}
// 箭头函数
let add = (x) => {
return x
}
// 简写形式
let add = x => x ;
let add = (x,y) => x+y
4.ES5和ES6对象封装函数对比
注意:箭头函数没有自己的this,它的this是继承而来,默认指向在定义它时所处的对象(宿主对象)。
ES5对象封装函数代码如下(示例):
// es5中自定义对象里面封装函数
var name = '王'
var person = {
name:'刘',
age:18,
f1:function(){
console.log(this);
console.log(this.name); //
}
}
person.f1()
// 箭头函数 -- var
var name = '王'
var person = {
name:'刘',
age:18,
f1:()=>{
console.log(this);
console.log(this.name); //
}
}
person.f1()
ES6对象封装函数代码如下(示例):
// 箭头函数 -- es6
let name = '王'
let person = {
name:'刘',
age:18,
f1:()=>{
console.log(this); // Window {parent: Window, opener: null, top: Window, length: 2, BigInt: ƒ, …}
console.log(this.name); // undefined
}
}
person.f1()
// 函数单体模式
let name = '王振'
let person = {
name:'刘伟',
age:18,
//f1:function(){
f1(){ //不会改变this的指向
console.log(this);
console.log(this.name); //
}
}
person.f1()
4.ES5和ES6类写法对比
ES5使用原型链给类封装方法
ES5类写法代码如下(示例):
// es5 没有类的概念,写法
function Person(name,age){
this.name = name; // 类似于self
this.age = age;
}
// 使用
var p1 = new Person('杨', 16);
p1.name;
结果:"杨"
// es5封装方法,原型链
Person.prototype.f2 = function(){console.log('xxxxxx')};
p1.f2(); // 结果'xxxxxx'
ES6类写法代码如下(示例):
//es6 class声明类(了解)
class Person2{
constructor(name,age){
this.name = name;
this.age = age;
}
showName(){console.log(this.name)};
};
let p3 = new Person2('汉子',16);
p3.name;
"汉子"
p3.showName();
汉子
三、简单使用
1.安装使用
官网: https://cn.vuejs.org/
安装:https://cn.vuejs.org/v2/guide/installation.html
下载vue.js,然后引入使用
2.简单语法
变量可以进行简单逻辑运行:
变量代码如下(示例):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title
</head>
<body>
<div id="app">
<h1>{{ name }}</h1>
<h1>{{ meinv.split('').reverse().join('') }}</h1> <!-- 字符串翻转 -->
<h1>{{ num+1 }}</h1> <!-- 四则运算 -->
<h1>{{ 1+1 }}</h1> <!-- 四则运算 -->
<h1>{{ info.name }}</h1> <!-- 属性取值 -->
<h1>{{ 1>2?'真':'假' }}</h1> <!-- 三元运算、三目运算 -->
<h1>{{ num>2?'真':'假' }}</h1>
<h1>{{ hobby_list }}</h1>
</div>
</body>
<script src="vue.js"></script>
<script>
let vm = new Vue({
el:'#app', //值为css选择器,多数都使用id属性的值, vue圈地,圈的地里面才能使用vue的语法,外面不能用
data:{ // 数据属性
name:'王',
num:100,
meinv: 'simin',
info:{
name:'xx',
age:'18'
},
hobby_list:[
'美女','帅哥',
]
}
})
</script>
</html>
3.vm对象取值
在vm内部使用带
号
取
值
v
m
.
号取值 vm.
号取值vm.el;
vm.
d
a
t
a
;
v
m
.
data; vm.
data;vm.data.hobby_list;
在html中也可以去掉$取值使用vm.el;
vm.data;
vm.data.hobby_list;
4.数组更新与检测
- 数据双向绑定时,数据变化,页面变,页面变化数据变
- 使用以下方法操作数组,可以检测变动:push,pop,shift,unshift,splice,sort,reverse
- 不会检测变动filter(),concat(),slice(),map(),新数组替换旧数组
-页面不会更改:vm.arr.concat([‘44’,‘55’])
-解决vm.arr=vm.arr.concat([‘44’,‘55’]) 3 页面不会更改:通过索引值更新数组
-解决方案一:
vm.arr[0]
“11”
vm.arr[0]=‘99’
“99”
vm.arr.splice(0,1,‘88’)
[“99”]
-解决方案二 Vue.set(vm.arr,0,‘lqz’)
四、指令系统
一般以标签属性的方式来写,语法: 指令系统=’'值"
1.文本操作(v-text,v-html)
代码如下(示例):
<p v-text="aele">
</p>
<p v-html="aele">
</p>
...
<script src="vue.js"></script>
<script>
let vm = new Vue({
el:'#app', //值为css选择器,多数都使用id属性的值, vue圈地,圈的地里面才能使用vue的语法,外面不能用
data:{ // 数据属性
name:'王',
aele:'<a href="">百度</a>',
num:100,
meinv: 'simin',
}
})
</script>
2.条件渲染(v-if,v-show)
v-if条件判断
代码如下(示例):
<div id="app">
<h1 v-if="num>100">{{name}}</h1>
<h1 v-else-if="num<100">{{name}}牛逼</h1>
<h1 v-else>{{meinv}}</h1>
</div>
<script src="vue.js"></script>
<script>
let vm = new Vue({
el:'#app', //值为css选择器,多数都使用id属性的值, vue圈地,圈的地里面才能使用vue的语法,外面不能用
data:{ // 数据属性
name:'王',
aele:'<a href="">百度</a>',
num:100,
}
})
</script>
v-show 控制标签显示或隐藏的
<div id="app">
<h1 v-show="num>100">{{name}}</h1>
<h1>思</h1>
</div>
let vm = new Vue({
el:'#app', //值为css选择器,多数都使用id属性的值, vue圈地,圈的地里面才能使用vue的语法,外面不能用
data:{ // 数据属性
name:'王',
aele:'<a href="">百度</a>',
num:100,
}
})
v-if和v-show的区别:
v-if 控制标签生成或者去除的
v-show 控制标签显示或者隐藏的
频繁切换标签显示与否,尽量使用v-show,不会重组文档结构,那么切换起来效率高
不频繁的可以用v-if,条件不成立,不会生成标签,渲染就快一些
3.属性绑定v-bind与事件绑定v-on
注意:属性绑定赋值具有多种方式
代码如下(示例):
<body>
<div id="app">
<!-- 属性绑定v-bind-->
<div xx="hahah"></div> <!--静态模式-->
<div v-bind:xx="name"></div> <!--动态模式-->
<div :bb="age"></div> <!--动态简写模式-->
<!-- 一:动态赋值属性绑定对象之字典值为bool值时-->
<!-- 使用字典键值(值为true时把键赋值给属性绑定对象)对动态赋值属性绑定对象-->
<div :class="{'c1':true, 'c2':true}">这是一个测试</div>
<!-- 使用数组加字典键值(值为true时把键赋值给属性绑定对象)对动态赋值属性绑定对象-->
<div :class="[{'c1':true}, {'c2':false}]">这是一个测试2</div>
<!-- 事件绑定-->
<div v-on:click="num++">加</div>
<!-- 事件绑定简写@替代v-on:-->
<div @click="num--">减</div>
<div>{{num}}</div>
</div>
</body>
<script src="vue.js"></script>
<script>
let vm = new Vue({
el:"#app",
data:{
name:"陈",
age:16,
num:100,
}
})
</script>
4.Vue数据属性写法
注意:数据属性可以使用两种写法.建议使用return写法
代码如下(示例):
<script>
let vm = new Vue({
el:'#app', //值为css选择器,多数都使用id属性的值, vue圈地,圈的地里面才能使用vue的语法,外面不能用
// data:{ // 数据属性
// name:'王',
// aele:'<a href="">百度</a>',
// num:100,
// meinv: 'simin',
// }
// 建议使用
data(){ // 这样写数据属性是最常用的方式,因为后面学和使用组件的功能时,必须要这样写数据属性
return { // 数据属性
name:'王',
aele:'<a href="">百度</a>',
num:100,
meinv: 'simin',
}
}
})
</script>
5.v-model双向数据绑定与methods属性
注意:简单的input标签值同步加减
代码如下(示例):
<body>
<div id="app">
<button @click="num++">+</button>
<!-- <input type="text" :value="num">-->
<input type="text" v-model="num"> <!-- 双向数据绑定 -->
<button @click="Handler">-</button>
<p>{{num}}</p>
<!-- 使用methods实现显示密码和隐藏密码的循环切换-->
<input :type="type"> <button @click="show">{{xx}}</button>
</div>
</body>
<script src="vue.js"></script>
<script>
new Vue({
el:'#app',
data(){
return {
num:10,
}
},
methods:{
常规模式
// Handler:function () {
// //console.log(this.num);
// if (this.num > 0){
// this.num--;
// }
//
// }
单体模式
Handler() {
//console.log(this.num);
if (this.num > 0){
this.num--;
},
show(){
if (this.type === 'password'){
this.type = 'text';
this.xx = '隐藏密码';
}else {
this.type = 'password';
this.xx = '显示密码';
}
}
}
}
})
</script
6.v-model之lazy,number,trim修饰词
.lazy:延迟同步值,和change以及blur一样,但输入框失去焦点时同步
.number:将输入数值转换为数字类型
…trim:过滤输入值首尾的空白符
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<h1>lazy延迟同步值</h1>
<!-- 延迟同步值,和change以及blur一样,但输入框失去焦点时同步-->
<input type="text" v-model.lazy="mytext">
<br>
{{mytext}}
<h1>number将输入数值转换为数字类型</h1>
<input type="text" v-model.number.lazy="mynumber">
<br>
{{mynumber}}
<h1>trim过滤输入值首尾的空白符号</h1>
<input type="text" v-model="mytriber">
<br>
||{{mytriber}}||
</div>
</body>
<script src="../day02/vue.js"></script>
<script>
let vm = new Vue({
el:'#app',
data(){
return {
mytext:'',
mynumber:'',
mytriber:'',
}
}
})
</script>
</html>
7.v-for遍历及vm过滤器属性及监听属性及计算属性
使用v-for时:
- 1 v-for循环数组,对象时,建议在控件(组件,标签)写一个key属性,属性值唯一
- 2 页面更新以后,加速dom的替换(渲染),虚拟dom的替换diff算法
- 3 :key=“变量”
vm局部过滤器属性:filters
vm全局过滤器属性filter
- 全局过滤器可以在任意vm组件中使用
- 局部组件只可以在自己的vm组件中使用
- 过滤器可以叠加使用
vm监听属性:watch
vm计算属性:computed
循环容器数据生成table记录,并通过全局或局部过滤器增加元素,并通过监听某数据是否发生变化做出反应示例:
代码如下(示例):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<ul>
<li :key="value.id" v-for="(value, index) in info">{{value.name|true_man|lalala}}----{{index}}</li>
<li :key="index" v-for="(value, index) in infoma">{{index|false_new}}----{{value}}</li>
</ul>
<div>{{count_xx}}</div>
<button @click="info[0].name='ggg'">点我</button>
</div>
</body>
<script src="vue.js"></script>
<script>
<!-- 全局过滤器(不局限于某个vm范围内使用) -->
Vue.filter('lalala', function (val) {
return val + '全局过滤器'
})
let vm = new Vue({
//vm作用域
el: "#app",
//视图数据及属性
data() {
return {
info: [
{'name': '陈', 'age': 18},
{'name': 'en', 'age': 23},
{'name': 'lir', 'age': 56},
{'name': 'hji', 'age': 89},
],
infoma:{
name:'Chen',
age:12,
price:34,
}
}
},
//局部过滤器(过滤器属性)
filters:{
true_man:function (val) {
return val + "真汉子"
},
//单体模式
false_new(val){
return val + "女孩子"
},
},
//计算属性
computed:{
count_xx:function () {
return this.info[0].name + "----------------------------" + this.infoma.name
},
},
//监听属性:一旦监听的变量发生变化,则将该改变值传入函数中运行,执行相应逻辑
watch:{
'info.0.name':function (val) {
console.log(val)
}
}
})
</script>
</html>
8.表单控制
通过v-model属性,实时获取表单输入的内容
代码如下(示例)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<h1>表单相关之checkbox</h1>
<input type="text" v-model="mytext">
<br>
{{mytext}}
<br>
<h1>表单相关之</h1>
<textarea name="" id="" cols="30" rows="10" v-model="myarea"></textarea>
<br>
{{myarea}}
<input type="checkbox" v-model="mycheck">点我选择
<br>
{{mycheck}}
<br>
<!-- 单选-->
<input type="radio" v-model="myradio" value="男">男
<input type="radio" v-model="myradio" value="女">女
<input type="radio" v-model="myradio" value="未知">未知
<br>
{{myradio}}
<br>
<input type="radio" v-model="myradio1" value="1111">1111
<input type="radio" v-model="myradio1" value="2222">2222
<br>
{{myradio1}}
<h1>多选checkbox</h1>
<input type="checkbox" v-model="mylist" value="hhhh">hhh
<input type="checkbox" v-model="mylist" value="666">666
<input type="checkbox" v-model="mylist" value="ttt">tttt
<br>
{{mylist}}
</div>
</body>
<script src="vue.js"></script>
<script>
let vm = new Vue({
el:'#app',
data(){
return {
mytext:'',
myarea:'',
mycheck:'',
myradio:'',
myradio1:'',
mylist:[],
}
}
})
</script>
</html>
9.购物车案例
通过表单控制内容实时更新商品总价
代码如下(示例)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<ul>
<input type="checkbox" v-model="isAll" @change="chooseall">全选/全不选
<li v-for="data in shoppinglist">
<button @click="data.number++">+</button>
<input type="checkbox" v-model="mylist" :value="data" @change="changeone">
{{data}}
<button @click="cutnumber(data)">-</button>
</li>
</ul>
<br>
价格总数是{{getPrice()}}
<br>
{{mylist}}
</div>
</body>
<script src="vue.js"></script>
<script>
let vm = new Vue({
el: "#app",
data() {
return {
shoppinglist: [
{name: '特斯拉', price: 10, number: 1, id: '1'},
{name: '苹果', price: 3, number: 4, id: '2'},
{name: '香蕉', price: 80, number: 6, id: '3'}
],
mylist:[],
isAll:false,
}
},
methods:{
//根据实时的选中列表计算总价
getPrice(){
let totalmoney = 0
for (i in this.mylist){
totalmoney+=this.mylist[i]['price']*this.mylist[i]['number']
}
return totalmoney
},
chooseall(){
if (this.isAll){
this.mylist=this.shoppinglist
}
if (this.isAll == false){
this.mylist=[]
}
},
//当多选框中没有被全部选中时全选框不会被选中,全部选中时全选框更新为选中状态
changeone(){
if (this.mylist.length==this.shoppinglist.length){
this.isAll=true
}else{
this.isAll=false
}
},
//判断商品个数是否低于1
cutnumber(data){
if (data.number>1){
data.number--
}
}
}
})
</script>
</html>
十.自定义指令
Vue自定义指令和组件一样存在着全局注册和局部注册两种方式。先来看看注册全局指令的方式,通过 Vue.directive( id, [definition] ) 方式注册全局指令,第一个参数为自定义指令名称(指令名称不需要加 v- 前缀,默认是自动加上前缀的,使用指令的时候一定要加上前缀),第二个参数可以是对象数据,也可以是一个指令函数
代码如下(示例)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<div>啦啦啦啦啦</div>
<br>
<div v-mystyle="">这是自定义指令标签</div>
<br>
<!-- 如果只对自定义指令设置inserted方法,不会同步更新使用的变量值,还需要设置update方法-->
<button @click="changecolor">点我改变颜色测试自定义指令是否同步更新</button>
<div v-mystyle="testcolor">自定义指令参数测试</div>
</div>
</body>
<script src="../day02/vue.js"></script>
<script>
Vue.directive('mystyle',{
//创建自定义指令对象则会执行inserted函数
//自定义指令触发的inserted函数接收的第一个参数为固定值,即使用自定义指令的dom对象
inserted(ev, testcolor){
console.log(ev)
//通过操作dom对象进行各种修改,如下修改标签的背景颜色
ev.style.backgroundColor='green'
//传入的参数为一个对象,通过.value获取变量值
// console.log(testcolor)
ev.style.backgroundColor=testcolor.value
},
//可同步自定义指令绑定的属性变量
update(ev,testcolor){
ev.style.backgroundColor=testcolor.value
}
})
let vm = new Vue({
el:'#app',
data(){
return {
testcolor:'blue'
}
},
methods:{
changecolor(){
this.testcolor='red'
}
}
})
</script>
</html>
通过在Vue实例中添加 directives 对象数据注册局部自定义指令
代码如下(示例):
<div id="app" class="demo">
<!-- 局部注册 -->
<input type="text" placeholder="我是局部自定义指令" v-focus2>
</div>
<script>
new Vue({
el: "#app",
directives: {
focus2: {
inserted: function(el){
el.focus();
}
}
}
})
</script>
五、样式操作
1.class类值操作
代码如下(示例):
<div id="app">
<button @click="status=!status">改变样式</button>
<!-- 方式二-->
<!-- <div :class="status?'c1':'c2'">-->
<!-- 方式一:常用-->
<!-- <div :class="{c1:num===100,c2:status}">-->
<!-- 方式三:不常用,使用字典数组-->
<div :class="[m1, m2]">
啦啦啦啦不知道说啥
</div>
</div>
</body>
<script src="vue.js"></script>
<script>
let vm = new Vue({
el:"#app",
data(){
return {
status:false,
num:100,
m1:{'c1':true},
m2:{'c2':true}
}
}
})
</script>
选项卡简单示例:
运用知识点:class中可以放置固定类属性,而其它类属性可以根据属性绑定class进行增加
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
#card{
width: 500px;
height: 350px;
}
.title{
height:50px;
}
.title span{
width: 100px;
height: 50px;
background-color:#ccc;
display: inline-block;
line-height: 50px; /* 设置行和当前元素的高度相等,就可以让文本内容上下居中 */
text-align:center;
}
.content .list{
width: 500px;
height: 300px;
background-color: yellow;
display: none;
}
.content .active{
display: block;
}
.title .current{
background-color: yellow;
}
</style>
<script src="vue.js"></script>
</head>
<body>
<div id="card">
<div class="title">
<span :class="{current:num===1}" @click="num=1">国内新闻</span>
<span :class="{current:num===2}" @click="num=2">国际新闻</span>
<span :class="{current:num===3}" @click="num=3">银河新闻</span>
<!--<span>{{num}}</span>-->
</div>
<div class="content">
<div class="list" :class="{active:num===1}">国内新闻列表</div>
<div class="list" :class="{active:num===2}">国际新闻列表</div>
<div class="list" :class="{active:num===3}">银河新闻列表</div>
</div>
</div>
<script>
// 思路:
// 当用户点击标题栏的按钮[span]时,显示对应索引下标的内容块[.list]
// 代码实现:
var card = new Vue({
el:"#card",
data:{
num:0,
},
});
</script>
</body>
</html>
2.style键值操作
代码如下(示例):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.c1 {
color: red;
}
.c2 {
background-color: green;
}
</style>
</head>
<body>
<div id="app">
<button @click="status=!status">改变样式</button>
<!-- 静态方式-->
<!-- <div style="color: red; background-color: green">-->
<!-- 动态方式一:使用属性绑定动态设置style值(注意:'-'连接词需要变换成后一个单纯首字母大写)-->
<!-- <div :style="{color: colorcontent, backgroundColor: backcolorcontent, fontSize: fontcontent + 'px'}">-->
<!-- 动态方式二:将属性值字典在vm中设置完毕后赋值给属性绑定对象-->
<!-- <div :style="ss">-->
<!-- 方式三:使用数组加字典键值对赋值属性绑定对象-->
<div :style="[ss1, ss2]">
啦啦啦啦不知道说啥
</div>
</div>
</body>
<script src="vue.js"></script>
<script>
let vm = new Vue({
el: "#app",
data() {
return {
status: false,
num: 100,
m1: {'c1': true},
m2: {'c2': true},
colorcontent: 'red',
backcolorcontent: 'green',
fontcontent: 30,
ss: {
color: 'red', backgroundColor:
'pink', fontSize: '30px'
},
ss1: {
color: 'red', backgroundColor:
'black',
},
ss2: {
fontSize: '40px'
}
}
}
})
</script>
</html>
六、vue与后端交互的三种方式
1.ajax
Ajax 即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML),是指一种创建交互式、快速动态网页应用的网页开发技术,无需重新加载整个网页的情况下,能够更新部分网页的技术。
前端代码如下(示例):
使用ajax需要先引入jquery
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<--使用ajax需要先引入jquery-->
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<script src="js/vue.js"></script>
<title>Title</title>
</head>
<body>
<div id="box">
<button @click="handleClick">点我加载美女数据</button>
美女你好:{{mytext}}
</div>
</body>
<script>
var myajax=$
var vm = new Vue({
el: '#box',
data: {
mytext:'',
},
methods:{
handleClick(){
myajax.ajax({
url:'http://127.0.0.1:5000/',
method:'get',
success: (data)=> {
console.log(data)
this.mytext=data
}
})
}
}
})
</script>
</html>
后端代码如下(python的flask框架):
from flask import Flask,make_response
app=Flask(__name__)
@app.route('/')
def index():
print('请求来了')
res=make_response('hello world')
res.headers['Access-Control-Allow-Origin'] = '*'
return res
if __name__ == '__main__':
app.run()
2.fetch
fetch是一种HTTP数据请求的方式,是XMLHttpRequest的一种替代方案。fetch不是ajax的进一步封装,而是原生js
前端代码如下(示例):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="js/vue.js"></script>
<title>Title</title>
</head>
<body>
<div id="box">
<button @click="handleClick">点我加载美女数据</button>
从后端加载的数据:
<br>
用户名:{{name}}
<br>
年龄:{{age}}
</div>
</body>
<script>
var vm = new Vue({
el: '#box',
data: {
name: '',
age:''
},
methods: {
handleClick() {
fetch('http://127.0.0.1:5000/').then(response => {
return response.json()
}).then(json => {
console.log('从后端获取的json数据', json)
this.name=json.name
this.age=json.age
}).catch(ex => {
console.log('出异常', ex)
})
}
}
})
</script>
</html>
后端代码如下(python的flask框架):
from flask import Flask,make_response,jsonify
app=Flask(__name__)
@app.route('/')
def index():
res=jsonify({'name':'lqz','age':18})
# 这两行代码处理跨域
res=make_response(res)
res.headers['Access-Control-Allow-Origin'] = '*'
return res
if __name__ == '__main__':
app.run()
3.axios
Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中
前端代码如下(示例):
使用axios需要先引入axios的js文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="js/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<title>Title</title>
</head>
<body>
<div id="box">
<button @click="handleClick">点我加载电影数据</button>
<ul>
<li v-for="item in datalist">
<p>电影名:{{item.name}}</p>
<p>导演:{{item.director}}</p>
<img :src="item.poster">
</li>
</ul>
</div>
</body>
<script>
var vm = new Vue({
el: '#box',
data: {
datalist:[],
},
methods: {
handleClick() {
axios.get("http://127.0.0.1:5000/film").then(res=>{
console.log(res.data)
if(res.data.status==0){
this.datalist=res.data.data.films
}
})
}
}
})
</script>
</html>
后端代码如下(python的flask框架):
from flask import Flask, make_response, jsonify
import json
app = Flask(__name__)
@app.route('/film')
def film():
with open('film.json', 'rt', encoding='utf-8') as f:
dic = json.load(f)
res = jsonify(dic)
# 这两行代码处理跨域
res = make_response(res)
res.headers['Access-Control-Allow-Origin'] = '*'
return res
if __name__ == '__main__':
app.run()
七、vm生命周期钩子函数
1.八个生命周期函数
vm生命周期钩子函数即在构造vm对象的各个阶段执行的相关函数,期终最常用的是created函数,在此函数中编写ajax从后端获取实时数据
- beforeCreated:创建vm对象前运行,此时el和data均不存在
- created:创建vm对象后运行,此时el还未关联html,不存在,data对象已经被创建
- beforeMount:此时vm对象已经获取到el的原生html标签以及data的所有数据,将实际数据替换视图中原生js变量前执行
- mounted:将vm对象数据替换完原生js变量后实行
- beforeUpdate:组件数据发生更新之前执行
- updated:组件数据更新完成后执行
- beforeDestroy:组件销毁之前执行
- destroyed:组件销毁之后执行
代码如下(示例):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<button @click="changeclick">点我有惊喜!</button>
<div><img :src="myurl" alt=""></div>
<div>{{info}}</div>
<App01 v-if="isShow"></App01>
</div>
</body>
<script src="../day02/vue.js"></script>
<script>
let vm = new Vue({
el: "#app",
data() {
return {
info: '根组件',
myurl: '',
isShow: true,
}
},
//创建vm对象之前运行,此时el和data均不存在
beforeCreate: function () {
console.log('---------->beforeCreate')
console.log(this.$el)
console.log(this.$data)
},
//创建vm对象之后运行,此时el还未关联html,不存在,data对象已经被创建
created() {
console.log('---------->created')
console.log(this.$el)
console.log(this.$data)
},
//此时vm对象已经获取到el的原生html标签以及data的所有数据,将实际数据替换视图中原生js变量前执行
beforeMount() {
console.log('---------->beforeMount')
//此时el对象的html标签还是原生js变量
console.log(this.$el)
console.log(this.$data)
},
//将vm对象数据替换完原生js变量后实行
mounted() {
console.log('---------->mounted')
//此时el对象的html的js变量以及被替换完成
console.log(this.$el)
console.log(this.$data)
},
methods: {
changeclick() {
this.info = this.info + "changeclick"
this.myurl = 'https://i.pinimg.com/564x/35/20/3f/35203f4ee700a9ac5a11291caf6e9fa7.jpg'
this.isShow = !this.isShow
},
},
//组件数据发生更新之前执行
beforeUpdate() {
console.log('---------->beforeUpdate')
console.log(this.$el.innerHTML)
console.log(this.$data.info)
},
//组件数据更新完成之后执行
updated() {
console.log('---------->updated')
console.log(this.$el.innerHTML)
console.log(this.$data.info)
},
components: {
App01: {
data() {
return {
info: '我是App01',
}
},
template: `
<div>
<div>{{ info }}</div>
</div>`,
//组件销毁之前执行
beforeDestroy() {
console.log('---------->beforeDestroy')
console.log(this.$el)
},
//组件销毁之后执行
destroyed() {
console.log('---------->destroyed')
console.log(this.$el)
},
},
}
})
</script>
</html>
2.定时任务与延时任务
setTimeout(function () {
alert(33333)
},3000) //延迟3s钟干什么事
setInterval(
function () {
alert(444)
},3000
)//每隔3s钟干什么事
八、事件处理
1.冒泡阻止之stop,prevent
代码如下(示例):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.c1{
height: 100px;
width: 100px;
background-color: green;
}
.c2{
height: 200px;
width: 200px;
background-color: brown;
}
</style>
</head>
<body>
<div id="app">
<div class="c2" @click="clickc2">
<!-- 阻止事件冒泡方式一:使用stop.prevent-->
<!-- <div class="c1" @click.stop.prevent="clickc1">-->
<!-- 阻止事件冒泡方式二:使用stop-->
<div class="c1" @click.stop="clickc1">
</div>
</div>
<form action="127.0.0.1">
<input type="text">
<!-- 阻止form表单页面刷新时需要使用stop.prevent而不能使用stop:不会向目标地址发送请求,并停止刷新页面-->
<input type="submit" @click.stop.prevent="">
</form>
<!--阻止a标签向目标地址发送请求从而阻止页面刷新(同时一样需要使用stop.prevent而不能使用stop)-->
<a href="127.0.0.1" @click.stop="">点我点我</a>
</div>
</body>
<script src="vue.js"></script>
<script>
let vm = new Vue({
el:"#app",
methods:{
clickc1:function () {
alert('c1')
},
clickc2(){
alert('c2')
},
},
})
</script>
</html>
2.事件修饰符stop,self,once,prevent
- .stop 阻止事件冒泡
- .self 只处理自己的事件,子控件冒泡的事件不处理
- .prevent 阻止a链接跳转
- .once只处理一次就解绑(抽奖页面)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!-- self只处理自己触发的事件,不处理子控件触发的-->
<!-- <ul @click.self="handleul">-->
<!-- <li v-for="data in datalist" @click="handleli">{{data}}</li>-->
<ul @click="handleul">
<!-- stop阻止父控件事件的触发 -->
<!-- <li v-for="data in datalist" @click.stop="handleli">{{data}}</li>-->
<!-- once只触发一次事件-->
<li v-for="data in datalist" @click.once="handleli">{{data}}</li>
</ul>
<!-- prevent阻止a标签调转-->
<a href="https://www.baidu.com/" @click.prevent="">点我看美女</a>
<a href="https://www.baidu.com/" @click.once="">点我看丑女</a>
</div>
</body>
<script src="vue.js"></script>
<script>
let vm = new Vue({
el:'#app',
data(){
return {
datalist:['dasdasd', '大叔大婶多0', '大是大撒旦撒旦撒']
}
},
methods:{
handleli(){
alert('li被点击了')
},
handleul(){
alert('ul被点击了')
}
}
})
</script>
</html>
3.按键修饰符
按下回车键触发事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!-- 按下回车键触发事件的两种方式-->
<input type="text" @keyup.enter="handleenter">
<input type="text" @keyup.13="handleenter">
</div>
</body>
<script src="vue.js"></script>
<script>
let vm = new Vue({
el:'#app',
methods:{
handleenter(){
alert('111111111')
}
}
})
</script>
</html>
4.input实时过滤案例之blur,change,input属性
- blur:失去焦点触发
- change:失去焦点触发,跟blur一样
- input:数据发生变化,就会触发
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!-- <input type="text" v-model='mytest' @blur="handleblur">-->
<!-- <input type="text" v-model="mytest" @change="handlechange">-->
<input type="text" v-model="mytest" @input="handleinput">
<button @click="isShow=!isShow">点我折叠,展开</button>
<button @click="clickshow">点我折叠,展开</button>
<ul v-show="isShow">
<li v-for="data in newlist">{{data}}</li>
</ul>
</div>
</body>
<script src="vue.js"></script>
<script>
let vm = new Vue({
el:'#app',
data(){
return {
mytest:'',
isShow:true,
datalist: ['aaa', 'abc', 'abcde', 'abcdef', 'bbb', 'bac'],
newlist: ['aaa', 'abc', 'abcde', 'abcdef', 'bbb', 'bac'],
}
},
methods:{
//blur 失去焦点触发
handleblur(){
this.newlist=this.datalist.filter((item)=> {
return item.indexOf(this.mytest) > -1
})
},
//失去焦点时触发,和blur一样
handlechange(){
this.newlist=this.datalist.filter((item)=>{
return item.indexOf(this.mytest) > -1
})
},
//数据发生变化时触发
handleinput(){
this.newlist=this.datalist.filter((item)=>{
return item.indexOf(this.mytest) > -1
})
},
clickshow(){
this.isShow = !this.isShow
},
}
})
</script>
</html>
九、组件化开发
1.简介
所谓组件化开发,就是把页面拆分成多个组件,每个组件依赖的 CSS、JS、模板、图片等资源放在一起开发和维护。 因为组件是资源独立的,所以组件在系统内部可复用,组件和组件之间可以嵌套,如果项目比较复杂,可以极大简化代码量,并且对后期的需求变更和维护也更加友好
2.全局组件与局部组件
对于全局组件引用需要二步:
- 使用Vue.component声明全局组件
- 直接在html中引用
对于局部组件引用需要三步:
- 使用let声明局部组件
- 在父组件的components属性中注册
- 在html中引用
代码如下(示例):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!-- 使用局部组件-->
<!-- <xx></xx>-->
<App></App>
<!-- 使用全局组件-->
<num></num>
</div>
</body>
<script src="../vue.js"></script>
<script>
<!-- 声明全局组件-->
Vue.component('num',{
data() {
return {
num:"我是全局组件",
}
},
template: `
<div style="color: darkred;background-color: aqua">
<div>
{{num}}
</div>
</div>
`
})
<!-- 声明局部组件-->
let App = {
data(){
return {
appmsg:'我是局部组件'
}
},
template:`
<div class="app">
<div>{{appmsg}}</div>
</div>
`
}
let vm = new Vue({
el:"#app",
// 挂载局部组件
components:{
// xx:App,
// App:App,
// 键值同名简写
App,
}
})
</script>
</html>
3.vue-router
通过不同的访问路径,加载不同的组件到单页面中(同一个html文件),vue做的叫做单页面应用(SPA).
代码如下(示例):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title
</head>
<body>
<div id="app">
<App></App>
</div>
</body>
<script src="../vue.js"></script>
<script src="vue-router.js"></script>
<script>
// 第一步:
Vue.use(VueRouter); // 将VueRouter功能注入到Vue中
// 第二步:写组件
let home = {
data(){
return {
msg:'我是home页面',
}
},
template:`
<div class="home">
<h1>{{msg}}</h1>
</div>
`,
}
let spa = {
data(){
return {
msg:'我是spa页面',
}
},
template:`
<div class="spa">
<h1>{{msg}}</h1>
</div>
`
}
// 127.0.0.1:8000/home/
// 127.0.0.1:8000/spa/
// 声子
let App = {
data(){
return {
appmsg:'我是app组件',
num:20,
soncount:'',
}
},
// a href='/home/'
// 第六步:写连接,写出口
template:`
<div>
<router-link to="/home/">首页</router-link>
<router-link to="/spa/">spa页</router-link>
<router-view></router-view>
</div>
`,
}
// 第三步:写路由规则
const routes = [
{path:'/home/', component:home, },
{path:'/spa/', component:spa, },
]
// 第四步:实例化vue-router对象
let router = new VueRouter({
routes,
})
// 第五步:挂载router对象
let vm = new Vue({
el:'#app', //
router, // 挂载到vue对象上
data(){
return {
// appmsg:'xxxx'
}
},
components:{
// App:App, // 挂子
App,
}
})
</script>
</html>
4.slot插槽
插槽用于决定将所携带的内容,插入到指定的某个位置,从而使模板分块,具有模块化的特质和更大的重用性。插槽显不显示、怎样显示是由父组件来控制的,而插槽在哪里显示就由子组件来进行控制
代码如下(基本示例):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<App01>
<div style="background-color: #cccccc;width: 300px;height: 300px">我是插槽内容
<div style="background-color: red;height: 200px">啦啦啦啦</div>
</div>
</App01>
</div>
</body>
<script src="../day02/vue.js"></script>
<script>
let App01 = {
data(){
return {
info:'我是App01',
}
},
template:`<div>
<div>{{info}}</div>
<br>
<h1>插槽内容如下</h1>
<slot></slot>
</div>`,
}
let vm = new Vue({
el:"#app",
components:{
App01,
},
})
</script>
</html>
5.具名slot插槽
可以根据给slot标签定义名字,动态的调整不同slot内容显示位置
代码如下(基本示例):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<App01>
<div slot="p1" style="font-size: 30px;color: #F8A746">我是具名插槽p1</div>
<div slot="div1" style="font-size: 40px;background-color: goldenrod">我是具名插槽div1</div>
</App01>
</div>
</body>
<script src="../day02/vue.js"></script>
<script>
let vm = new Vue({
el:"#app",
components:{
App01:{
data(){
return {
info:'我是App01子组件',
}
},
template:`
<div>
<slot name="p1"></slot>
<br>
<div>{{info}}</div>
<br>
<slot name="div1"></slot>
</div>`,
},
}
})
</script>
</html>
6.swiper轮播图
swiper3官方使用介绍地址:https://3.swiper.com.cn/usage/index.html
代码如下(基本示例):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!-- 使用cdn引入swiper插件-->
<!-- <link rel="stylesheet" href="https://unpkg.com/swiper/swiper-bundle.min.css">-->
<!-- <script src="https://unpkg.com/swiper/swiper-bundle.min.js"></script>-->
<!-- 下载css和js的swiper插件引入-->
<link rel="stylesheet" href="css/swiper-bundle.min.css">
<script src="js/swiper-bundle.min.js"></script>
<title>Title</title>
<style>
.swiper-container {
width: 20%;
height: 300px;
}
</style>
</head>
<body>
<div id="app">
<div class="swiper-container">
<div class="swiper-wrapper">
<div class="swiper-slide" v-for="data in datalist">
<img :src="data" alt="">
</div>
</div>
<!-- 如果需要分页器 -->
<div class="swiper-pagination"></div>
<!-- 如果需要导航按钮 -->
<div class="swiper-button-prev"></div>
<div class="swiper-button-next"></div>
<!-- 如果需要滚动条 -->
<div class="swiper-scrollbar"></div>
</div>
</div>
</body>
<script src="../day02/vue.js"></script>
<script>
let vm = new Vue({
el: "#app",
data() {
return {
datalist: [],
}
},
mounted() {
//模拟延迟更新数据
setTimeout(() => {
this.datalist = ['https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSexbO9msUXxfpaIqvoMGsNAOVmB7mBSlKuzg&usqp=CAU',
'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQqcFNy-_4bkWQ-lsuS4REnergyo-NhnN6q1g&usqp=CAU',
'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMUMTEyiCjuSt2R511YdI2pFBKhCgc0hXw2g&usqp=CAU',
'https://hongdou.files.wordpress.com/2008/07/alan.jpg',]
}, 1000)
},
updated() {
//创建swiper对象
var mySwiper = new Swiper('.swiper-container', {
direction: 'vertical', // 垂直切换选项
loop: true, // 循环模式选项
// 如果需要分页器
pagination: {
el: '.swiper-pagination',
},
// 如果需要前进后退按钮
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
// 如果需要滚动条
scrollbar: {
el: '.swiper-scrollbar',
},
})
}
})
</script>
</html>
7.自定义swiper组件封装
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="css/swiper-bundle.min.css">
<script src="js/swiper-bundle.min.js"></script>
<title>Title</title>
<style>
.swiper-container {
width: 30%;
height: 200px;
}
</style>
</head>
<body>
<div id="app">
<!-- <swiper>-->
<!-- <div class="swiper-wrapper">-->
<!-- <div class="swiper-slide" v-for="data in datalist">-->
<!-- <img :src="data" alt="">-->
<!-- </div>-->
<!-- </div>-->
<!-- </swiper>-->
<br>
<!-- 利用key的diff算法,检测某属性(例子为datalist2.length)是否有变化,有变化则重新dom加载swiper标签-->
<swiper :key="datalist2.length">
<div class="swiper-wrapper">
<div class="swiper-slide" v-for="data in datalist2">
<img :src="data" alt="">
</div>
</div>
</swiper>
<br>
<button @click="changeclick">点我更新轮播图</button>
</div>
</body>
<script src="../day02/vue.js"></script>
<script>
Vue.component('swiper', {
template: `
<div>
<div class="swiper-container">
<slot></slot>
<div class="swiper-pagination"></div>
<div class="swiper-button-prev"></div>
<div class="swiper-button-next"></div>
<div class="swiper-scrollbar"></div>
</div>
</div>`,
//方式二:以生命周期函数mounted与key属性组合实时更新轮播图(推荐使用)
mounted(){
//创建swiper对象
var mySwiper = new Swiper('.swiper-container', {
// direction: 'vertical', // 垂直切换选项
loop: true, // 循环模式选项
// 如果需要分页器
pagination: {
el: '.swiper-pagination',
},
// 如果需要前进后退按钮
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
// 如果需要滚动条
scrollbar: {
el: '.swiper-scrollbar',
},
})
}
,
// 方式一:首先利用生命周期函数mounted挂载完所有数据后创建swiper对象,再通过updated检测轮播图数据是否有变化,变化则重新创建swiper对象(
// 缺点:不断创建swiper对象,占用系统资源)
// updated() {
// //创建swiper对象
// var mySwiper = new Swiper('.swiper-container', {
// // direction: 'vertical', // 垂直切换选项
// loop: true, // 循环模式选项
//
// // 如果需要分页器
// pagination: {
// el: '.swiper-pagination',
// },
// // 如果需要前进后退按钮
// navigation: {
// nextEl: '.swiper-button-next',
// prevEl: '.swiper-button-prev',
// },
// // 如果需要滚动条
// scrollbar: {
// el: '.swiper-scrollbar',
// },
// })
// }
})
let vm = new Vue({
el:'#app',
//以下实际开发过程中应使用ajax或fetch或axios获取后端轮播图数据
data(){
return {
datalist:['https://img02.sogoucdn.com/app/a/100520093/f9d5c084396d06f6-90e0186edb2b7e85-21031fafd8361dc28552b457dd142992.jpg',
'https://img04.sogoucdn.com/app/a/100520093/f9d5c084396d06f6-0c7006bf1d0bb8d5-44cfb308fd53675f90401be304dc572d.jpg',
'https://img01.sogoucdn.com/app/a/100520093/f9d5c084396d06f6-0c7006bf1d0bb8d5-0078fbef558ee280fa662414de3823f5.jpg',],
datalist2:[
'https://t1.hxzdhn.com/uploads/tu/202004/9999/b55aa006d9.jpg',
'https://t1.hxzdhn.com/uploads/tu/202004/9999/a9d8e1e269.jpg',
'https://t1.hxzdhn.com/uploads/tu/202003/9999/54b8abd1c4.jpg',
],
}
},
methods:{
changeclick(){
this.datalist=[
'https://i04piccdn.sogoucdn.com/42910fceabcbfb31',
'https://desk-fd.zol-img.com.cn/t_s960x600c5/g5/M00/02/05/ChMkJlbKyJ-Id75qAAF12opqVdsAALIEgP-ChQAAXXy302.jpg',
'http://01.imgmini.eastday.com/mobile/20170717/20170717150831_19b069e290a1d007893af0e4779a3ab5_6.jpeg'
]
this.datalist2=[
'http://img.mp.itc.cn/upload/20170327/a452c4ea380a4ae5b182e37e9a215ea4_th.jpg',
'https://img.zcool.cn/community/01d70e5986b06f000000212962dcfe.jpg@1280w_1l_2o_100sh.jpg',
'http://img31.mtime.cn/mg/2012/10/07/132153.70879515.jpg',
'http://pix1.tvzhe.com/stills/drama/95/30/b/L7=tW7CoLn=.jpg',
]
}
}
})
</script>
</html>
十、组件间值交互
1.父组件传值给子组件
父组件往子组件传递值需要两步:
- 在父组件使用子组件的标签上加自定义属性
- 在子组件中声明props属性来接受数据
代码如下(示例):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<App></App>
</div>
</body>
<script src="../vue.js"></script>
<script>
let Vheader = {
data() {
return {
msg: "我是子组件",
sonmsg:"我是子组件的属性值",
}
},
// 子组件使用父组件中传递下来的变量
template: `
<div style="background-color: aqua">
<div>{{ msg }}</div>
<div>{{ num }}</div>
<div>{{ constnum }}</div>
</div>
`,
// 子组件中使用props属性接收父组件传递的变量
props: ['num', 'constnum'],
}
// 块组件下挂载一个一个子组件
let App = {
data() {
return {
fanum: "我是父组件的属性值",
}
},
components: {
Vheader,
},
// 父组件中指定需要传递的变量或固定值
template: `
<div>
<Vheader :num="fanum" constnum="我是父组件传递的固定值"></Vheader>
</div>
`
}
// 根组件一般挂载块组件
let vm = new Vue({
el: "#app",
components: {
App,
},
})
</script>
</html>
2.子组件传值给父组件
子组件往父组件传值需要两步:
- 子组件中使用this.$emit(‘父组件的自定义事件名称’,值)
- 父组件中定义一个父组件的自定义事件名称对应的那个方法来接受数据
代码如下(示例):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<App></App>
</div>
</body>
<script src="../vue.js"></script>
<script>
let Vheader = {
data() {
return {
info: "我是子组件1",
val: "我是子组件val值",
xx: "我是子组件xx值",
firstval: "first子组件val值",
firstxx: "first子组件xx值",
test:"挂载完所有数据后传值给父组件",
}
},
template: `
<div style="background-color: aquamarine">
<div>{{ info }}</div>
<button @click="doit">点我传值给父组件</button>
</div>
`,
//方式一:条件触发传值给父组件
methods: {
doit() {
this.$emit('sonxx', this.val, this.xx)
}
},
//方式二:加载完所有data数据时就传递父组件
created() {
this.$emit('firstsonxx', this.firstval, this.firstxx)
},
//方式三:挂载完所有数据到html后传递值给父组件
mounted(){
this.$emit('mountedsonmsg', this.test)
}
}
let App = {
data() {
return {
info: "我是快组件",
valnum: "",
xxnum: "",
firstvalnum: "",
firstxxnum: "",
mountmsg:"",
}
},
components: {
Vheader,
},
template: `
<div>
<Vheader @sonxx="getmsg" @firstsonxx="getfirstmsg" @mountedsonmsg="getmountmsg"></Vheader>
<div style="color: darkred">{{ info }}</div>
<div>{{mountmsg}}</div>
<div>created调用子组件数学值为{{ firstvalnum }}----{{ firstxxnum }}</div>
<div>调用子组件数学值为{{ valnum }}----{{ xxnum }}</div>
</div>
`,
methods: {
getmsg(val, xx) {
console.log(22222222222222)
this.valnum = val;
this.xxnum = xx;
},
getfirstmsg(val, xx) {
this.firstvalnum= val;
this.firstxxnum = xx;
},
getmountmsg(val){
this.mountmsg = val;
}
},
}
//创建跟组件vm对象
let vm = new Vue({
el: "#app",
components: {
App,
}
})
</script>
</html>
3.事件总线
不同层级的不同组件间通信
- 声明一个vue对象
- 往vue对象上放数据
- 从vue对象上拿数据
代码如下(示例):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<App01></App01>
</div>
</body>
<script src="../vue.js"></script>
<script>
<!-- 声明一个空vue对象-->
let bus = new Vue()
let compon01 = {
data(){
return {
info:"我是compon01",
val:"我是com01的值",
msg:"msg01",
cre:"created",
moun:"mounted",
}
},
template: `<div>
<div style="background-color: aquamarine">{{info}}</div>
<button @click="pullval">点我传值给compon02</button>
</div>`,
//方式一:条件触发传值给目标子组件
methods:{
pullval(){
bus.$emit('com01val',this.val,this.msg);
}
},
// 不支持传值给子组件
// created() {
// console.log(111111111111);
// bus.$emit('cre','444444');
// },
// 方式二:挂载完所有数据后将值传递给目标子组件
mounted(){
bus.$emit('com01val02',this.moun);
bus.$emit('cre',this.cre);
}
}
let compon02 = {
data(){
return {
info:"我是compon02",
val:"",
msg:"",
res:"",
moun:"",
}
},
template:`
<div style="background-color: bisque">
<div>{{info}}</div>
<div>收到的值为{{val}}-----{{msg}}</div>
<div>test----{{res}}---{{moun}}</div>
</div>
`,
//$on中包含watch监听功能,一旦监听到目标键值对创建即执行
created(){
bus.$on("com01val",(val,msg)=>{
this.val = val;
this.msg = msg;
});
bus.$on("cre",(val)=>{
this.res = val;
});
bus.$on("com01val02",(val)=>{
this.moun = val;
});
}
}
let App01 = {
data(){
return {
info:"我是App01",
}
},
components: {
compon01,
compon02,
},
template:`
<div>
<compon01></compon01>
<compon02></compon02>
</div>
`
}
let vm = new Vue({
el:"#app",
components:{
App01,
}
})
</script>
</html>
4.ref属性通信
可实现组件间通信,子父和父子都可以使用
- ref放在标签上,拿到的是原生节点
- ref放在组件上,拿到的是组件对象,
通过这种方式实现子传父(this.$refs.mychild.text)
通过这种方式实现父传子(调用子组件方法传参数)
代码如下(示例):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<App01 ref="myApp01"></App01>
<button @click="senddata">点我传值给子组件</button>
<h1>子组件传递给父组件的值为-------{{msg}}</h1>
<input type="text" ref="fathertext">传递给子组件的输入值
</div>
</body>
<script src="../day02/vue.js"></script>
<script>
let App01 = {
data(){
return {
info:'我是子组件App01的子组件app01',
fathermsg:'我是子组件app01传给父组件App01的值',
msg:'',
msgtest:'',
msginput:'',
}
},
template:`<div>
<h1>{{info}}</h1>
<h2>{{msg}}</h2>
<h2>{{msgtest}}</h2>
<h2>{{msginput}}</h2>
</div>`,
methods: {
getmsg(val){
console.log('4444444444444444')
this.msg=val
}
}
}
let vm = new Vue({
el:"#app",
data(){
return {
info:'我是根组件!',
sonmsg:'我是传给子组件的值',
msg:'',
}
},
components:{
App01,
},
methods:{
senddata(){
console.log('66666666666666')
//在调用子组件标签中设置ref属性
//使用ref属性直接调用子组件的方法,可以通过参数进行值传递(父传递子)
this.$refs.myApp01.getmsg(this.sonmsg)
//使用ref属性直接对子组件的数据进行赋值(父传子)
this.$refs.myApp01.msgtest='测试'
//使用ref属性调用子组件的数据对父组件进行赋值(子传父)
this.msg=this.$refs.myApp01.fathermsg
console.log(this.$refs.fathertext)
//通过对input标签设置ref属性,可以获取输入的实时值
console.log(this.$refs.fathertext.value)
//将实时获取的值传递给子组件(父传子)
this.$refs.myApp01.msginput=this.$refs.fathertext.value
}
}
})
</script>
</html>
十一、vue_cli
1.安装准备
一般情况下,单文件组件,我们运行在 自动化工具vue-CLI中,可以帮我们编译单文件组件。所以我们需要在系统中先搭建vue-CLI工具,
官网:https://cli.vuejs.org/zh/
nodejs npm – python pip
Vue CLI 需要 Node.js 8.9 或更高版本 (推荐 8.11.0+),node.js是一个js作为代码的后端语言,将浏览器的js代码解析器抽离出来了,作为自己node.js语言的解析器。你可以使用 nvm 或 nvm-windows在同一台电脑中管理多个 Node 版本。因为这个vue cli脚手架的运行需要借助到node.js,所以要先安装node.js,通过脚手架进行开发的时候,前端就可以直接运行服务进行调试。
nvm工具的下载和安装: https://www.jianshu.com/p/d0e0935b150a或https://www.jianshu.com/p/622ad36ee020
安装记录:
打开:https://github.com/coreybutler/nvm-windows/releases
安装完成以后,先查看环境变量是否设置好了.
常用的nvm命令
nvm list # 列出目前在nvm里面安装的所有node版本
nvm install node版本号 # 安装指定版本的node.js
nvm uninstall node版本号 # 卸载指定版本的node.js
nvm use node版本号 # 切换当前使用的node.js版本
如果使用nvm工具,则直接下载不用自己手动下载,如果使用nvm下载安装 node的npm比较慢的时候,可以修改nvm的配置文件(在安装根目录下)
# settings.txt
root: C:\tool\nvm [这里的目录地址是安装nvm时自己设置的地址,要根据实际修改]
path: C:\tool\nodejs
arch: 64
proxy: none
node_mirror: http://npm.taobao.org/mirrors/node/
npm_mirror: https://npm.taobao.org/mirrors/npm/
2.安装node.js
Node.js是一个新的后端(后台)语言,它的语法和JavaScript类似,所以可以说它是属于前端的后端语言,后端语言和前端语言的区别:
- 运行环境:后端语言一般运行在服务器端,前端语言运行在客户端的浏览器上
- 功能:后端语言可以操作文件,可以读写数据库,前端语言不能操作文件,不能读写数据库。
我们一般安装LTS(长线支持版本):
下载地址:https://nodejs.org/en/download/【上面已经安装了nvm,那么这里不用手动安装了】
node.js的版本有两大分支:
官方发布的node.js版本:0.xx.xx 这种版本号就是官方发布的版本
社区发布的node.js版本:xx.xx.x 就是社区开发的版本
3.npm简单使用
在安装node.js完成后,在node.js中会同时帮我们安装一个npm包管理器npm。我们可以借助npm命令来安装node.js的包
npm install -g 包名 # 安装模块 -g表示全局安装,如果没有-g,则表示在当前项目安装
npm list # 查看当前目录下已安装的node包
npm view 包名 engines # 查看包所依赖的Node的版本
npm outdated # 检查包是否已经过时,命令会列出所有已过时的包
npm update 包名 # 更新node包
npm uninstall 包名 # 卸载node包
npm 命令 -h # 查看指定命令的帮助文档
4.安装vue_cli
使用npm安装vue_cli
npm install -g vue-cli
npm install -g vue-cli --registry=https://registry.npm.taobao.org
如果安装速度过慢,一直超时,可以考虑切换npm镜像源:http://npm.taobao.org/
4.cmd下创建vue_cli
cd切换到想要保存vue_cli项目位置后创建项目
vue init webpack 项目名称
按照需求设置属性
成功效果
按照提示,运行项目
npm run dev
成功后的效果