Vue开发
前端发展历史
1、HTML(5)、CSS(3)、JavaScript(ES5、ES6):编写一个个的页面发送给后端(PHP、Python、Go、Java),后端嵌入模板语法进行渲染,渲染完数据后返回给前端方便在浏览器中查看
2、Ajax的出现前端实现了向后台发送异步请求,例如python中Render+Ajax混合
3、单用Ajax(加载数据,DOM渲染页面): 前后端分离的雏形
4、 [Angular框架](https://angular.cn/)的出现(1个JS框架):出现了“ 前端工程化 ”的概念(前端也是1个工程、1个项目)
5、 [React](https://react.docschina.org/)、[Vue框架](https://cn.vuejs.org/):当下最火的2个前端框架( Vue :国人喜欢用, React :外国人喜欢用)
6、 移动开发(Android+IOS) + Web(Web+微信小程序+支付宝小程序) + 桌面开发(Windows桌面):前端 -> 大前端
7、 一套代码在各个平台运行(大前端): 谷歌Flutter(Dart语言:和Java很像) 可以运行在IOS、Android、PC端
8、 在Vue框架的基础性上 [uni-app](https://uniapp.dcloud.io/):一套编码 编到10个平台
9 、在不久的将来 ,前端框架可能会一统天下
Vue的介绍的基本使用
Vue简介
是一套用于构建用户界面的 渐进式框架 ,与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用,Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合,另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动, 渐进式框架 可以局部使用,只用一部分,也可以整个工程都使用它
官网:https://cn.vuejs.org/ 中文文档:https://cn.vuejs.org/v2/guide/[
Vue特点
易用:通过 HTML、CSS、JavaScript构建应用灵活不断繁荣的生态系统,可以在一个库和一套完整框架之间自如伸缩
高效:20kB min+gzip 运行大小超快虚拟 DOM最省心的优化
M-V-VM思想
MVVM的介绍
M-V-VM 是Model-View-ViewModel的缩写,它是一种基于前端开发的架构模式,是一种事件驱动编程方式
-Model:vue对象的data属性里面的数据,这里的数据要显示到页面中
-View:vue中数据要显示的HTML页面,在vue中,也称为视图模板HTML+CSS
-ViewModel:vue中编写代码时的vm对象,它是vue.js的核心,负责连接View和 Model数据的中转,保证视图和数据的一致性,所以前面代码中,data里面的数据被显示中p标签中就是vm对象自动完成的
双向数据绑定:JS中变量变了,HTML中数据也跟着改变
MVVM的特性
-低耦合
--视图 (View)可以独立于Model变化和修改 ,1个ViewModel可以绑定到不同的View上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变
-可复用
--可以把一些视图逻辑放在1个ViewModel中,让很多View重用这端视图的逻辑 (以此减少代码冗余)
-独立开发
--开发 人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计
-可测试
--界面元素是比较难以测试的,而现在的测试可以 针对ViewModel 来编写 ③ MVVM的逻辑
-组件化开发、单页面开发
--组件开发类似于DTL中的include,每一个组件的内容都可以被替换和复用,单页面开发只需要1个页面,结合组件化开发来替换页面中的内容页面的切换只是组件的替换,页面还是只有1个index.html
版本选择
--1.X:使用得较少
--2.X: 普遍使用
--3.X:出了很久了,一些新项目可能会选择使用,但是他跟vue2的语法有差距,但是在vue3中完全兼容vue2的语法,可以在vue3上写vue2,但是官方不建议了,因为虽然兼容,但是运行效率会变低
引入方式
--CDN方式引入
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
--下载后导入
<script src="js/vue.js"></script>
解释型的语言是需要解释器的,js就是一门解释型语言,只不过js解释器被集成到了浏览器中,所以在浏览器的Console中输入命令,就和在cmd中输入python后,进入交互式环境一样
nodejs:一门后端语言,把chrome的v8引擎(解释器),安装到操作系统之上使用的解释器
开发前端使用什么编辑器(IDE)
--jetbrains系列:捷克公司
-java——idea(最开始只有这个)
-python——pycharm
-go——goland
-php——phpstorm
--前端
-webstorm
-AndroidStadio——谷歌买了jetbrains的授权后+adt,做出来的一款免费的编辑器 vscode:微软的软件,开源免费,轻量级,可以编写python、go、前端等vim开发
--小众的前端开发方式
-sublime text也是写前端的
专业的前端工作者会使用vscode或是webstrom,但是因为pycharm跟webstorm都是一家公司的,他们可以说都是以java为基础进行开发的我们编写前端使用:pycharm+vue插件
vue插件 点击右上角的file按钮,然后点击settings出现下图界面:
plugins-->搜索插件-->安装vue插件
简单使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue的简单使用</title>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>
<div id="box">
{{name}}
</div>
</body>
<script>
// 先产生一个vue对象
let vm = new Vue({
el: '#box',
// 在box这个div中可以写 vue的语法
data: {name: 'Hello World'}
}) </script>
</html>
插值语法
mvvm演示
我们在vue语法中通过标签的id对他托管,我们可以在被托管的标签内写上{{ }},来使用插值表达式,但是不能跟django的模板语法一样写在标签的属性中
<div id={{name}}></div>
# 这样不行
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
姓名:{{name}}
<br>
<input type="text" v-model="name">
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: { // data中定义的变量,以后直接从vm实例直接可以拿到
name: 'lqz',
age: 19
}
})
</script>
</html>
插值语法
在插值表达式中我们可以使用插值语法
#插值语法中可以放
-变量,对象取值,数组取值
-简单的js语法
-函数()
ps:插值不能写在标签的属性上,只能写在标签内部
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="vue.js"></script>
</head>
<body>
<div id="app">
<p>名字:{{name}}</p>
<p>年龄:{{age}}</p>
<p>爱好:{{hobby}}----->第一个爱好:{{hobby[1]}}</p>
<!-- 这里因为hobby对应的是一个数组,所以要用中括号通过索引取值-->
<p>信息:{{info}}----》年龄:{{info.age}}---{{info['age']}}</p>
<!-- 这里的info是字典类型,因此可以用点的方式或是通过键来取值-->
<p>运算:{{10*2+3*4}}</p>
<!-- 这是进行数学运算-->
<p>三目运算符【条件?'符合条件的结果':'不符合条件的结果'】:{{10>90?'大于':'小于'}}</p>
<p>标签(默认不会渲染成标签):{{myurl}}</p>
<p>函数()</p>
<!-- 这里的函数是<p>{{函数()}}</p>的形式来调用函数的意思-->
</div>
</body>
<script>
var vv = new Vue({
el: '#app',
data: {
name: 'zzh',
age:22,
hobby:['吃','喝','玩'],
info:{name:'zzh',age:22},
myurl:'<a href="http://www.baidu.com">点我看美女</a>'
}
})
</script>
</html>
文本指令
指令 | 释义 |
---|---|
v-html | 让HTML渲染成页面 |
v-text | 标签内容显示js变量对应的值 |
v-show | 放1个布尔值:为真 标签就显示;为假 标签就不显示 |
v-if | 放1个布尔值:为真 标签就显示;为假 标签就不显示 |
指令系统
-v-xx 写在标签属性上,任意标签
-v-xx="name" ----》原来插值语法中能写的,它都能写,不要再加 {{}}
# 指令系统:vue提供的以v-xx写在标签属性上的 ,统称为指令,
例如,a_url必须是data中定义的变量
<p v-text="a_url"></p>
v-text直接把字符串内容渲染在标签内部,等同于
<p v-text="a_url"></p>
<p>{{a_url}}</p>
v-html 把字符串的内容渲染成标签,写在标签内部
<p v-html="a_url"></p>
# v-show 等于布尔值,该标签是否显示 控制样式显示不显示:
<p style="display: none;"></p>
# v-if 等于布尔值,该标签是否显示 整个标签之间删除,效率低,在dom中删除标签
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="vue.js"></script>
</head>
<body>
<div id="app">
<h2>v-text</h2>
<p v-text="a_url"></p>
<h2>v-html</h2>
<p v-html="a_url"></p>
<h2>v-show</h2>
<img src="https://img2.woyaogexing.com/2023/02/10/f426aeefcf78b0f6e88bba4e67437409.jpeg" alt="" v-show="show"
width="200px" height="200px">
<h2>v-if</h2>
<div v-if="show_if">
<img src="https://img2.woyaogexing.com/2023/02/13/0253c158c222e0db0ea0bf68df21d315.jpeg" alt="" width="200px"
height="200px">
</div>
</div>
</body>
<script>
var vv = new Vue({
el: '#app',
data: {
a_url: '<a href="http://www.baidu.com">点我看美女</a>',
show: true,
show_if: true
}
})
</script>
</html>
打开浏览器的Console更改show_if的值为false就可以让图片消失
属性指令
# 标签上的属性可以绑定变量,以后变量变化,属性的值跟着变化
-href
-src
-name
-class
-style
-height
。。。
# 语法
v-bind:属性名="变量名"
# 可以简写
:属性名="变量名"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="vue.js"></script>
</head>
<body>
<div id="app">
<a :href="url">疯狂的兔子</a>
<br>
<img :src="photo" alt="" :height="h" :width="w">
</div>
</body>
<script>
var vv = new Vue({
el: '#app',
data: {
url: 'http://www.cnblogs.com',
photo: 'https://s1.ax1x.com/2022/12/02/zBbHdU.jpg',
h:'200px',
w:'200px'
}
})
</script>
</html>
事件指令
# 事件指令是:点击事件,双击事件,滑动事件。。。。。用的最多的是点击事件click
v-on:事件名='函数'
<button v-on:click="handleClick">点我看美女</button>
函数必须写在methods的配置项中
methods:{
'handleClick':function (){
// alert('美女')
console.log(this) // this 就是当前vue实例,就是vm实例
this.show=!this.show
},
}
-点击button就会触发绑定函数(handleClick)的执行
# 可以简写,以后都用简写
v-on:事件名='函数名’
可以简写成
@事件名='函数名'
methods配置项中写成 这种形式 es6的对象写法
handleClick() {}
如果函数中再套函数,如果内部不是箭头函数,this指向有问题,需要在外部定义一下
var _this = this
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="vue.js"></script>
</head>
<body>
<div id="app">
<button @click="handleClick">点我看兔子</button>
<!-- 这里的@click相当于v-on:click="handleClick"-->
<div v-show="show">
<img src="https://s1.ax1x.com/2022/12/02/zBbHdU.jpg" alt="" width="200px"
height="200px">
</div>
</div>
</body>
<script>
var vv = new Vue({
el: '#app',
data: {
show: false
},
methods:{
'handleClick':function (){
// alert('兔子')
console.log(this) // this 就是当前vue实例,就是vv实例
this.show=!this.show // 这里的感叹号相当于取反的操作
},
}
})
</script>
</html>
在es6的语法中可以简写methods中方法的代码
原本的
'clicked': function () {
var _this = this
setInterval(function () {
var i = Math.round(Math.random() * (_this.myurl.length - 1))
console.log(i)
_this.url = _this.myurl[i]
},2000)
this.con = !this.con
}
简写的
clicked() {
var _this = this
setInterval(function () {
var i = Math.round(Math.random() * (_this.myurl.length - 1))
console.log(i)
_this.url = _this.myurl[i]
},2000)
this.con = !this.con
}
class和style
# 本身他俩都是属性指令,但是他们比较特殊,应用更广泛,单独再讲
# class:推荐用数组
:class='变量' [1,2,3]
变量可以是字符串,数组,对象
# style:推荐用对象
:style='变量' {'name':'whh'}
变量可以是字符串,数组,对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="vue.js"></script>
<style>
.font {
font-size: 60px;
}
.red {
background-color: red;
}
.green {
background-color: green;
}
.font-color {
color: yellow;
}
</style>
</head>
<body>
<div id="app">
<h1>clss</h1>
<div :class="class_obj">我是div</div>
<h1>style</h1>
<div :style="style_obj">我是style-----div</div>
</div>
</body>
<script>
var vv = new Vue({
el: '#app',
data: {
// class_str:'font',
// 当class属性使用的变量是一个字符串的时候,修改这个变量就需要重新写一遍,比较麻烦
// class_list:['font'], # 推荐
// 当class属性使用的变量是一个列表的时候可以用push(),pop()对列表的内容进行增删
class_obj: {font: true, green: false, 'font-color': false},
// 当class属性使用的变量是一个字典的时候,内部的键可以不写引号,但是对于名称中有横杠的变量,不能省略横杠,会查找不到的
style_str: 'color: green;font-size:80px',
// style_list: [{color:'yellow'}, {'font-size':'90px'}], // style属性绑定的变量使用列表的时候需要内部套字典
style_list: [{color: 'yellow'}, {fontSize: '90px'}], // 可以用驼峰
style_obj: {color: 'yellow', fontSize: '80px'}
// style_obj: {color: 'yellow', 'font-size': '80px'}
},
})
</script>
</html>
条件渲染
条件渲染也是添加在标签的属性中
# v-if=条件
放在标签上,如果条件成立,该标签就显示,如果条件不成立,该标签就不显示
# v-else-if=条件
放在标签上,如果条件成立,该标签就显示,如果条件不成立,该标签就不显示
# v-else
放在标签上,上面条件都不成立,显示这个标签
举例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="vue.js"></script>
</head>
<body>
<div id="app">
<h1>通过分数显示文字</h1>
<div v-if="score>=90">优秀</div>
<div v-else-if="score>=80&&score<90">良好</div>
<div v-else-if="score>=60&&score<80">及格</div>
<div v-else>不及格</div>
</div>
</body>
<script>
var vv = new Vue({
el: '#app',
data: {
score: 99
},
})
</script>
</html>
列表渲染
列表渲染我们需要使用bootstrap的组件,因此我们需要导入他的cdn或是文件,然后再去官网上拿他的样式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="vue.js"></script>
<link rel="stylesheet" href="bootstrap-3.4.1-dist/css/bootstrap.css">
<script src="bootstrap-3.4.1-dist/js/bootstrap.js"></script>
</head>
<body>
<div id="app">
<div class="container-fluid">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<div class="text-center">
<h1>v-if+v-for 显示购物车</h1>
<button @click="handleClick" class="btn btn-danger">点我显示</button>
</div>
<div v-if="show">
<table class="table table-hover">
<thead>
<tr>
<th>id</th>
<th>商品名</th>
<th>商品价格</th>
</tr>
</thead>
<tbody>
<tr v-for="item in good_list">
<th scope="row">{{item.id}}</th>
<td>{{item.name}}</td>
<td>{{item.price}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</body>
<script>
var vv = new Vue({
el: '#app',
data: {
show: false,
good_list: [
{id: 1, name: '钢笔', price: '29'},
{id: 2, name: '铅笔', price: '29'},
{id: 3, name: '文具盒', price: '298'},
{id: 4, name: '彩笔', price: '298'},
]
},
methods: {
handleClick() {
this.show = !this.show
},
}
})
</script>
</html>
js的几种循环方式
v-for可以循环的变量
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div>
<div class="app">
<h1>v-for可以循环什么?</h1>
<h2>循环数组</h2>
<span v-for="item in l">{{item}}</span>
<h2>循环数组带索引</h2>
<div v-for="(item,index) in l">第 {{index + 1}}个,值是:{{item}}</div>
<h2>循环对象,默认是value</h2>
<div v-for="item in info">{{item}}</div>
<h2>循环对象,带key和value</h2>
<div v-for="(item,key) in info">key值是:{{key}}-----{{item}}</div>
<h2>循环字符串</h2>
<div v-for="item in s">
<p v-if="item!=' '">{{item}}</p>
<br v-else>
</div>
<h2>循环字符串-带索引</h2>
<div v-for="(item,index) in s">
<p v-if="item!=' '">{{item}}---->索引是:{{index}}</p>
<br v-else>
</div>
<h2>循环数字</h2>
<div v-for="item in 8">{{item}}</div>
<h2>循环数字-带索引</h2>
<div v-for="(item,index) in 8">{{item}}----索引是:{{index}}</div>
</div>
</div>
</body>
<script>
var l1 = [4, 5, 6,]
new Vue({
el: '.app',
data: {
l: [1, 2, 3],
info: {name: 'lqz', age: 19, l1},
s: 'hello world'
},
methods: {},
})
</script>
</html>
js的循环方式
// js的循环
//基于索引的循环
//python中没有基于索引的循环,python都是基于迭代的循环
var a = [4, 5, 6, 7]
for(i=0;i<10;i++){
for (i = 0; i < a.length; i++) {
console.log(i)
console.log(a[i])
}
//js的in循环,拿到的是索引,跟vue的v-for区分,vue-for拿到的是内容
var a = [4, 5, 6, 7]
for (i in a) {
console.log(i)
console.log(a[i])
}
//es6语法,of循环
var a = [4, 5, 6, 7]
for (item of a) {
console.log(item)
}
//数组的方法,forEach循环
var a = [4, 5, 6, 7]
a.forEach(function (item) {
console.log(item)
})
//jquery的循环,可以循环数组、对象
var a = [4, 5, 6, 7]
$.each(a, function (index, item) {
console.log(index)
console.log(item)
})
key值的解释
//vue的v-for写在标签上,在标签上加一个key,用属性指令绑定一个变量,key的值每次都不一样,这样可以加速虚拟dom的替换,从而提高循环效率,key值必须唯一
<div v-for="item in 8" :key="item">{{item}}</div>
数组,对象的检测与更新
当我们在页面代码中以k:v键值对的方法添加新的数据时,数据可能已经完成了添加
但是对应的前端页面并没有更新,这是因为数据有可能是被劫持了
这种情况下,我们使用以下代码添加即可
Vue.set(this.info, 'hobby', '篮球')
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div>
<div class="app">
<h1>循环对象</h1>
<div v-for="(value,key) in info">
<h3>key值是:{{key}}</h3>
<h2>value是:{{value}}</h2>
<hr>
</div>
<button @click="handleAdd">点我,加数据</button>
</div>
</div>
</body>
<script>
var vm = new Vue({
el: '.app',
data: {
info: {name: 'lqz', age: 19},
},
methods: {
handleAdd() {
// 页面不会变,单是值有了
this.info['hobby'] = '篮球'
// 遇到数据变了,页面没变的情况,使用以下代码
Vue.set(this.info, 'hobby', '篮球')
}
},
})
</script>
</html>
input事件
# input 的事件:
click
input 当输入框进行输入的时候 触发的事件
change 当元素的值发生改变时 触发的事件
blur 当输入框失去焦点的时候 触发的事件
focus 当获得焦点,触发事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div>
<div class="app">
<h1>点击事件click</h1>
<input type="text" @click="handleClick">
<h1>失去焦点</h1>
<input type="text" @blur="handleBlur">
<h1>input事件,只要输入,就会触发</h1>
<input type="text" @input="handleInput">
<h1>change事件</h1>
<input type="text" @change="handleChange">
<h1>focus事件</h1>
<input type="text" @focus="handleFocus">
</div>
</div>
</body>
<script>
var vm = new Vue({
el: '.app',
data: {},
methods: {
handleClick() {
alert('点了')
},
handleBlur() {
console.log('失去了')
},
handleInput() {
console.log('输入了东西')
},
handleChange() {
console.log('我变了')
},
handleFocus() {
console.log('我获得了')
}
}
})
</script>
</html>
v-model双向数据绑定
input框可以输入数据,输入后,就被js变量拿到,如果使用 :value='变量' 这种形式,页面中输入框变化,变量不会变,使用v-model做双向数据绑定
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div>
<div class="app">
<h1>单向数据绑定</h1>
<input type="text" :value="name">---->{{name}}--->单向数据绑定
<h1>双向数据绑定</h1>
<input type="text" v-model="age">---->{{age}}--->双向数据绑定
</div>
</div>
</body>
<script>
var vm = new Vue({
el: '.app',
data: {
name: 'lqz',
age:10
},
})
</script>
</html>
过滤案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div>
<div class="app">
<h1>过滤案例</h1>
<p>请输入要搜索的内容:<input type="text" v-model="myText" @input="handleInput"></p>
<ul>
<li v-for="item in newDataList">{{item}}</li>
</ul>
</div>
</div>
</body>
<script>
var vm = new Vue({
el: '.app',
data: {
myText: '',
dataList: ['a', 'at', 'atom', 'be', 'beyond', 'cs', 'csrf'],
newDataList: ['a', 'at', 'atom', 'be', 'beyond', 'cs', 'csrf'],
},
methods: {
handleInput() {
this.newDataList = this.dataList.filter(item => {
//判断item在不在myText中
// this 指向问题
if (_this.myText.indexOf(item) >= 0) { // 判断输入的值myText是否在item中
if (item.indexOf(_this.myText) >= 0) {
return true
} else {
return false
}
//上面5行,简写成
return item.indexOf(this.myText) >= 0
})
this.newDataList = this.dataList.filter(
item => item.indexOf(this.myText) >= 0
)
},
}
})
// 数组的过滤方法
var dataList = ['a', 'at', 'atom', 'be', 'beyond', 'cs', 'csrf']
var newDataList = dataList.filter(function (item) {
return false // return true表示这个值保留,false 表示这个值不要
})
console.log(newDataList)
// 字符串的indexOf方法,判断子字符串是否在当前字符串中,如果在返回的是索引,如果不在返回-1
var s = 'lqz is handsome'
var s1 = 'qqq'
var i = s.indexOf(s1)
console.log(i)
//es6 的箭头函数写法---》函数中套函数,this指向有问题,有了箭头函数,箭头函数没有自己的this,用的都是上一级的this
1 无参数,无返回值箭头函数
var f = () => {
console.log('函数')
}
2 有一个参数,没有返回值的箭头函数 括号可以去掉,可以加
var f = item => {
console.log(item)
}
3 有多个参数,没有返回值的箭头函数 括号不能去掉
var f = (item, key) => {
console.log(item)
}
4 有一个参数,一个返回值
var f = (item)=> {
return item + 'lqz'
}
var f = item => {
return item + 'lqz'
}
var f = item => item + 'lqz'
var res = f('lqz')
console.log(res)
</script>
</html>
事件修饰符
事件修饰符 | 释义 |
---|---|
.stop | 只处理自己的事件,子控件冒泡的事件不处理(阻止事件冒泡) |
.self | 只处理自己的事件,子控件冒泡的事件不处理 |
.prevent | 阻止a链接的跳转 |
.once | 事件只会触发一次(适用于抽奖页面) |
事件修饰符可以当作事件触发后的一些修饰动作同时触发
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div>
<div class="app">
<h1>事件修饰符stop,子控件不再冒泡给父控件</h1>
<ul @click='handleUl'>
<li @click.stop="handleLi">第一</li>
<li>第二</li>
</ul>
<h1>事件修饰符self:只处理自己的事件,子控件的冒泡,不处理</h1>
<ul @click.self='handleUl'>
<li @click="handleLi">第一</li>
<li>第二</li>
</ul>
<h1>prevent阻止a的跳转</h1>
<a href="http://www.baidu.com" @click.prevent="handleA">点我看美女</a>
<h1>once 只响应一次</h1>
<button @click.once="handleClick">点我抽奖</button>
</div>
</div>
</body>
<script>
var vm = new Vue({
el: '.app',
data: {},
methods: {
handleLi() {
console.log('li被点击了')
},
handleUl() {
console.log('ul被点击了')
},
handleA() {
console.log('a标签被点了')
// 阻止a的跳转,自己决定要不要跳
// 手动指定跳
location.href = 'http://www.cnblogs.com'
},
handleClick() {
console.log('我被点了')
}
}
})
</script>
</html>
按键修饰符
# 按键事件:按了键盘某个键,就会触发函数的执行
@keyup="handleKeyUp"
# 按键修饰符:只有某个按键被按下才触发
@keyup.enter
@keyup.13
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div>
<div class="app">
<input type="text" v-model="text" @keyup="handleKeyUp">-–>{{text}}-->
<input type="text" v-model="text" @keyup.13="handleKeyUp2">-–>{{text}}-->
<input type="text" v-model="text" @keyup.enter="handleKeyUp2(1,$event)">--->{{text}}
</div>
</div>
</body>
<script>
var vm = new Vue({
el: '.app',
data: {
text: ''
},
methods: {
handleKeyUp(event) {
// console.log('按键被按下了')
// keyCode 对照表https://blog.csdn.net/zqian1994/article/details/109486445
// console.log('按钮被按下了:', event.key, event.keyCode)
if (event.keyCode == 13) {
console.log('开始跟后端交换搜索了')
}
},
handleKeyUp2(a, event) {
console.log(event)
console.log('enter被按了')
}
}
})
</script>
</html>
表单控制
# input ----》变量类型是什么?
text 类型
radio:单选
checkbox:单选和多选
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div>
<div class="app">
<p>用户名:<input type="text" v-model="username"></p>
<p>密码:<input type="password" v-model="password"></p>
<p>性别:
男:<input type="radio" v-model="gender" value="1">
女:<input type="radio" v-model="gender" value="2">
</p>
<p>记住密码:<input type="checkbox" v-model="remember"></p>
<p>爱好:
篮球:<input type="checkbox" v-model="hobby" value="篮球">
足球:<input type="checkbox" v-model="hobby" value="足球">
排球:<input type="checkbox" v-model="hobby" value="排球">
</p>
<button @click="handleClick">登录</button>
</div>
</div>
</body>
<script>
var vm = new Vue({
el: '.app',
data: {
username: '',
password: '',
gender: '', // radio单选,多个radio绑定同一个变量,选中某个,就对应value值
remember: false, // checkbox 单选是true或false
hobby: [] // checkbox 多选是数组类型,必须一开始定义就是数组,多个checkbox绑定一个变量
},
methods: {
handleClick() {
console.log(this.username, this.password, this.gender, this.remember, this.hobby)
}
}
})
</script>
</html>
购物车案例
基本购物车
# js的变量只要发生变化,html页面中使用该变量的地方,就会重新渲染
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"
integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
</head>
<body>
<div class="app">
<div class="container-fluid">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<h1>购物车案例</h1>
<table class="table table-bordered">
<thead>
<tr>
<th>商品编号</th>
<th>商品名字</th>
<th>商品价格</th>
<th>商品数量</th>
<th>选择</th>
</tr>
</thead>
<tbody>
<tr v-for="item in goodList">
<th scope="row">{{item.id}}</th>
<td>{{item.name}}</td>
<td>{{item.price}}</td>
<td>{{item.number}}</td>
<td><input type="checkbox" v-model="checkGroup" :value="item"></td>
</tr>
</tbody>
</table>
<hr>
<p>选中商品:{{checkGroup}}</p>
<p>总价格:{{getPrice()}}</p>
</div>
</div>
</div>
</div>
</body>
<script>
var vm = new Vue({
el: '.app',
data: {
goodList: [
{id: '1', name: '钢笔', price: 20.1, number: 2},
{id: '2', name: '饼干', price: 4, number: 1},
{id: '3', name: '辣条', price: 5, number: 5},
],
checkGroup: []
},
methods: {
getPrice() {
// 通过checkGroup里面的对象,计算出总价格
var total = 0
for (item of this.checkGroup) {
total += item.price * item.number
}
return total
}
}
})
</script>
</html>
带全选全不选
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"
integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
</head>
<body>
<div class="app">
<div class="container-fluid">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<h1>购物车案例</h1>
<table class="table table-bordered">
<thead>
<tr>
<th>商品编号</th>
<th>商品名字</th>
<th>商品价格</th>
<th>商品数量</th>
<th>全选/全不选 <input type="checkbox" v-model="checkAll" @change="handleCheckAll"></th>
</tr>
</thead>
<tbody>
<tr v-for="item in goodList">
<th scope="row">{{item.id}}</th>
<td>{{item.name}}</td>
<td>{{item.price}}</td>
<td>{{item.number}}</td>
<td><input type="checkbox" v-model="checkGroup" :value="item" @change="handelCheckOne"></td>
</tr>
</tbody>
</table>
<hr>
<p>选中商品:{{checkGroup}}---{{checkAll}}</p>
<p>总价格:{{getPrice()}}</p>
</div>
</div>
</div>
</div>
</body>
<script>
var vm = new Vue({
el: '.app',
data: {
goodList: [
{id: '1', name: '钢笔', price: 20.1, number: 2},
{id: '2', name: '饼干', price: 4, number: 1},
{id: '3', name: '辣条', price: 5, number: 5},
],
checkGroup: [],
checkAll: false,
},
methods: {
getPrice() {
// 通过checkGroup里面的对象,计算出总价格
var total = 0
for (item of this.checkGroup) {
total += item.price * item.number
}
return total
},
handleCheckAll() {
if (this.checkAll) {
this.checkGroup = this.goodList
} else {
this.checkGroup = []
}
},
handelCheckOne() {
// console.log('一个被点了')
if (this.checkGroup.length==this.goodList.length){
this.checkAll=true
}else {
this.checkAll=false
}
}
}
})
</script>
</html>
带加减
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"
integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
</head>
<body>
<div class="app">
<div class="container-fluid">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<h1>购物车案例</h1>
<table class="table table-bordered">
<thead>
<tr>
<th>商品编号</th>
<th>商品名字</th>
<th>商品价格</th>
<th>商品数量</th>
<th>全选/全不选 <input type="checkbox" v-model="checkAll" @change="handleCheckAll"></th>
</tr>
</thead>
<tbody>
<tr v-for="item in goodList">
<th scope="row">{{item.id}}</th>
<td>{{item.name}}</td>
<td>{{item.price}}</td>
<td>
<button @click="handleDown(item)">-</button>
{{item.number}}
<button @click="item.number++">+</button>
</td>
<td><input type="checkbox" v-model="checkGroup" :value="item" @change="handelCheckOne"></td>
</tr>
</tbody>
</table>
<hr>
<p>选中商品:{{checkGroup}}---{{checkAll}}</p>
<p>总价格:{{getPrice()}}</p>
</div>
</div>
</div>
</div>
</body>
<script>
var vm = new Vue({
el: '.app',
data: {
goodList: [
{id: '1', name: '钢笔', price: 20.1, number: 2},
{id: '2', name: '饼干', price: 4, number: 1},
{id: '3', name: '辣条', price: 5, number: 5},
],
checkGroup: [],
checkAll: false,
},
methods: {
getPrice() {
// 通过checkGroup里面的对象,计算出总价格
var total = 0
for (item of this.checkGroup) {
total += item.price * item.number
}
return total
},
handleCheckAll() {
if (this.checkAll) {
this.checkGroup = this.goodList
} else {
this.checkGroup = []
}
},
handelCheckOne() {
// console.log('一个被点了')
if (this.checkGroup.length == this.goodList.length) {
this.checkAll = true
} else {
this.checkAll = false
}
},
handleDown(item) {
if (item.number > 1) {
item.number--
} else {
alert('太少了,受不了了')
}
}
}
})
</script>
</html>
可变与不可变类型(值与引用)
# python
-不可变类型:数字,字符串,元组
-可变类型:列表,字典,集合
-python中没有值类型和引用类型的叫法----【因为python一切皆对象,对象都是地址都是引用】
-可变类型当参数传到函数中,在函数中修改会影响原来的
-不可变类型当参数传到函数中,在函数中修改不会影响原来的
# python 函数参数传递是值传递还是引用传递? 这个问题不应该有
# js 传入了item 对象,在函数中修改,影响了原来的
-js 的对象是引用类型
-平时我们用的数组等数据类型,如果值会因为方法中的运行改变的就是值类型
v-model进阶
- lazy:等待input框的数据绑定时区焦点之后再变化
- number:数字开头的情况,只保留数字,后面的字母不保留;字母开头的情况,都保留(即不生效了)
- trim:去除首位的空格
vue
<!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>lazy</h1>
<input type="text" v-model.lazy="myText">---->{{myText}}
<h1>number</h1>
<input type="text" v-model.number="myNumber">---->{{myNumber}}
<h1>trim</h1>
<input type="text" v-model.trim="myTrim">---->{{myTrim}}
</div>
</body>
<script>
var vm = new Vue({
el: '.app',
data: {
myText: '',
myNumber: '',
myTrim: ''
},
})
</script>
</html>
vue与后端交互
跨域问题
当我们使用vue编写的前端给后端的drf项目发送请求,会出现报错,导致的结果就是请求被浏览器给拦截了。
拦截的原因:
从报错上看我们可以得知他是被一个叫CORS(跨域资源共享)的东西拦截了,因为没有'Access-Control-Allow-Origin'这个东西
这里我们不深入了解,我们只要知道在前后端分离的项目中,只要向不是地址栏中的 [域:地址和端口]发送请求,拿的数据,浏览器就会拦截,需要加上Access-Control-Allow-Origin信息才能发送请求
处理跨域问题
-后端代码中处理----》只需要在响应头中加入字段允许即可
jquerry的ajax
这里的后端是用flask写的
from flask import Flask, jsonify, make_response
app = Flask(__name__)
@app.route('/')
def index():
print('执行了')
res = make_response(jsonify({'name': '彭于晏', 'age': 19, 'gender': 'male'}))
res.headers['Access-Control-Allow-Origin'] = '*' # 把这个key和value加入到响应头,就没有跨域问题了
return res
if __name__ == '__main__':
app.run()
ps:这里我们同时使用了vue和jquery两个前端js框架,以后并不建议这么用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
</head>
<body>
<div class="app">
<h1>点击加载用户信息</h1>
<button @click="handleClick">点我</button>
<div v-if="age!=0">
<p>用户名:{{name}}</p>
<p>年龄:{{age}}</p>
<p>性别:{{gender}}</p>
</div>
<div v-else>
无用户信息
</div>
</div>
</body>
<script>
var vm = new Vue({
el: '.app',
data: {
name:'',
age:0,
gender:'未知'
},
methods: {
handleClick() {
//1 学过的,jq的ajax
$.ajax({
url: 'http://127.0.0.1:5000/',
type: 'get',
success: data => {
// console.log(data)
this.name=data.name
this.age=data.age
this.gender=data.gender
}
})
}
}
})
</script>
</html>
fetch发送ajax请求
fetch简介
fetch介绍
提供了一个 JavaScript 接口,用于访问和操纵 HTTP 管道的一些具体部分,例如请求和响应
它还提供了一个全局 fetch()
方法,该方法提供了一种简单,合理的方式来跨网络异步获取资源
-新的发送ajax 接口
-用起来比较方便
-支持promise写法[最新的异步写法]
-解决了原生的XMLHttpRequest兼容性的问题
-不是所有浏览器都支持
-主流现在是用axios[第三方]发送请求
# XMLHttpRequest: 原生js提供的
-比较老,不同浏览器需要做一些兼容性的处理,写起来比较麻烦
-jq基于它做了封装
# 发送ajax请求,
fetch基本结构
fetch('http://example.com/movies.json')
.then(function(response) {
return response.json();
})
.then(function(myJson) {
console.log(myJson);
});
<!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>
<button @click="handleClick">点我</button>
<div v-if="age!=0">
<p>用户名:{{name}}</p>
<p>年龄:{{age}}</p>
<p>性别:{{gender}}</p>
</div>
<div v-else>
无用户信息
</div>
</div>
</body>
<script>
var vm = new Vue({
el: '.app',
data: {
name: '',
age: 0,
gender: '未知'
},
methods: {
handleClick() {
//1 fetch
fetch('http://127.0.0.1:5000/').then(response => response.json()).then(res => {
// 对象
console.log(res)
this.name = res.name
this.age = res.age
this.gender = res.gender
})
}
}
})
</script>
</html>
axios发送ajax请求
1.Axios简介
① Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中
② axios官网:http://www.axios-js.com/
实例
https://m.maizuo.com/v5/?co=mzmovie#/films/nowPlaying
ps:
- 以后都用它,作用在vue上 ,第三方的模块
- Axios 是一个基于 promise 的 HTTP 库,是基于XMLHttpRequest封装的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
<script src="./js/axios.js"></script>
</head>
<body>
<div class="app">
<h1>点击加载用户信息</h1>
<button @click="handleClick">点我</button>
<div v-if="age!=0">
<p>用户名:{{name}}</p>
<p>年龄:{{age}}</p>
<p>性别:{{gender}}</p>
</div>
<div v-else>
无用户信息
</div>
</div>
</body>
<script>
var vm = new Vue({
el: '.app',
data: {
name: '',
age: 0,
gender: '未知'
},
methods: {
handleClick() {
//1 axios
axios.get('http://127.0.0.1:5000/').then(res => {
// res是对象,有点特殊,真正的数据(想要body体内容),在res.data中
console.log(res)
this.name = res.data.data.name
this.age = res.data.data.age
this.gender = res.data.data.gender
})
}
}
})
</script>
</html>
电影展示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
<script src="./js/axios.js"></script>
</head>
<body>
<div class="app">
<h1>热映电影</h1>
<button @click="handleClick">点我</button>
<ul>
<li v-for="item in dataList">
<h2>名字:{{item.name}}</h2>
<h3>导演:{{item.director}}</h3>
<h3>类型:{{item.category}}</h3>
<p>简介:{{item.synopsis}}</p>
<img :src="item.poster" alt="" height="300px" width="200px">
</li>
</ul>
</div>
</body>
<script>
var vm = new Vue({
el: '.app',
data: {
dataList: []
},
methods: {
handleClick() {
//1 axios
axios.get('http://127.0.0.1:5000/film').then(res => {
this.dataList = res.data.data.films
})
}
}
})
</script>
</html>
from flask import Flask, jsonify, make_response
import json
app = Flask(__name__)
@app.route('/')
def index():
print('执行了')
# res = make_response(jsonify({'name': '彭于晏', 'age': 19, 'gender': 'male'}))
res = make_response(jsonify({'code': 100, 'msg': '成功', 'data': {'name': '彭于晏', 'age': 19, 'gender': 'male'}}))
res.headers['Access-Control-Allow-Origin'] = '*' # 把这个key和value加入到响应头,就没有跨域问题了
return res
@app.route('/film')
def film():
with open('./film.json', 'r', encoding='utf-8') as f:
res_dict = json.load(f)
res = make_response(jsonify(res_dict))
res.headers['Access-Control-Allow-Origin'] = '*' # 把这个key和value加入到响应头,就没有跨域问题了
return res
if __name__ == '__main__':
app.run()
vue生命周期
生命周期八大钩子
钩子函数名称 | 描述 |
---|---|
beforeCreate | 创建Vue实例之前调用 |
created | 创建Vue实例成功后调用(可以在此处发送异步请求后端数据) |
beforeMount | 渲染DOM之前调用 |
mounted | 渲染DOM之后调用 |
beforeUpdate | 重新渲染之前调用(数据更新等操作时,控制DOM重新渲染) |
updated | 重新渲染完成之后调用 |
beforeDestroy | 销毁之前调用 |
destroyed | 销毁之后调用 |
# 从vue实例创建开始,到实例被销毁,总共经历了8个生命周期钩子[只要写了就会执行]函数
-钩子:反序列化验证---》钩子函数
-学名[专门名字]---》面向切面编程(AOP)
-OOP:面向对象编程
# 重点:
-1 用的最多的,created 发送ajax请求----》有的人放在mounted中加载
-2 beforeDestroy
-组件一创建,created中启动一个定时器
-组件被销毁,beforeDestroy销毁定时器
# 实现实时聊天效果(在线聊天室)
-轮询:定时器+ajax http:http版本区别
-长轮询:定时器+ajax http
-websocket协议:服务端主动推送消息
https://zhuanlan.zhihu.com/p/371500343
vue组件
组件相当于Python中的模块 拓展HTML元素 可以重复使用的代码 使用它就是为了重复使用
例如:一个轮播图需要使用放到很多页面当中使用, 一个轮播图有它自己的Js Css Html,
组件就可以快捷的做出一个轮播图 有自己的JS Css Html放到一起 有自己的逻辑样式这样到哪里都可以使用了不用重复代码
定义组件的两种方式
全局组件:全局可以使用的组件 可以用在任意其他的组件中
局部组件:局部组件只能在定义的组件中使用
# 组件化开发的好处:重用代码
# 组件分类
-全局组件:在任意组件中都可以使用
-局部组件:只能在当前组件中使用
定义全局组件
Vue.component('child', {
template: `
<div>
<button>后退</button>
<span style="font-size: 40px">首页--{{ name }}</span>
<button @click="handleFor">前进</button>
<lqz1></lqz1>
</div>`,// 里面写html内容,必须包在一个标签中
data() { // data必须是方法,返回对象
return {
name: '彭于晏',
t: null
}
},
methods: {
handleFor() {
this.name = 'lqz'
}
},
components: {
'lqz1': {
template: `
<div>
<h1>局部组件---{{ age }}</h1>
</div>`,
data() {
return {
age: 19
}
}
},
}
})
定义局部组件
var foo={
template: `
<div>
<h1>局部组件---{{ age }}</h1>
</div>`,
data() {
return {
age: 19
}
}
}
var vm = new Vue({
...
components: {
foo
}
})
补充
# 1 之前前后端交互,使用xml格式
# 2 后来json 格式出现,前后端交互,主流都是json格式
-可能觉得不安全
-前后端加密解密方式
# 4 目前有些比json更安全,高效,节约空间的编码格式,后期可能前后端交互使用某种
组件其他
# 根组件 和 组件 一些问题
-new Vew()---->管理div----》根组件
-自己再定义的全局,局部是组件
-组件有自己的html,css,js ---》数据,事件,。。。。。
-在组件中,this 代指当前组件
-父子组件的data是无法共享的
-data是1个函数,需要有返回值(return)
组件间通信之父传子
# 组件间数据不共享----》需要进行数据传递
# 父传子:使用自定义属性方式
<!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>字符串的age–>age="age"</h2>-->
<!-- <child age="age"></child>-->
<!-- <h2>:age="19"</h2>-->
<!-- <child :age="19"></child>-->
<!-- <h2>age="19"</h2>-->
<!-- <child age="19"></child>-->
<!-- <h2>:age="age"</h2>-->
<child :age="age" myname="彭于晏"></child>
<h1>属性验证---》传入的必须是xx类型</h1>
<!-- <h2>字符串的age–>age="age"</h2>-->
<!-- <child age="age"></child>-->
<!-- <h2>:age="19"</h2>-->
<!-- <child :age="19"></child>-->
<!-- <h2>age="19"</h2>-->
<!-- <child age="19"></child>-->
<!-- <h2>:age="age"</h2>-->
<!-- <child :age="age"></child>-->
</div>
</body>
<script>
// 父中有age,子child 只有name,没有age,现在把父中的age传到child中,显示
var child = {
template: `
<div>
<button>后退</button>
首页--->名字:{{ myname }}--->年龄:{{ age }}
<button>前进</button>
</div>`,
data() {
return {
myname: 'lqz'
}
},
// props: ['age'],
props: {age: Number, myname: String},
}
var vm = new Vue({
el: '.app',
data: {
age: 19
},
components: {
child
}
})
</script>
</html>
组件间通信之子传父
# 通过自定义事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
<p>子组件传递过来的数据: {{mytext}}</p>
<hr>
<child @myevent="handleEvent"></child>
<hr>
</div>
</body>
<script>
var child = {
template: `
<div>
<input type="text" v-model="mytext">
<button @click="handleSend">点我传递</button>
</div>`,
data() {
return {
mytext: ''
}
},
methods: {
handleSend() {
// alert(this.mytext)
// 子组件中,触发自定义事件的执行,会执行父组件自定义事件绑定的函数,有几个参数,就传几个参数
this.$emit('myevent', this.mytext)
}
}
}
var vm = new Vue({
el: '.app',
data: {
mytext: ''
},
methods: {
handleEvent(mytext) {
this.mytext = mytext
}
},
components: {
child
}
})
</script>
</html>
ref属性
# 自定义属性和自定义事件 可以实现父子传值
# ref属性 可以更方便的实现父子通信
# ref属性放在普通标签上 <input type="text" ref="myinput">
-通过this.$refs.myinput 拿到的是原生dom对象,通过原生dom修改 标签
#ref属性放在组件上 <child ref="mychild"></child>
-通过this.$refs.mychild 拿到的是组件对象,既然拿到了组件对象,组件对象中的 变量,方法,都能直接通过 . 的方式调用
-因此不需要关注是子传父,还是父传子,直接通过组件对象,使用即可
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
<button @click="handleClick">点我</button>
----》{{age}}
<br>
<input type="text" ref="myinput">
<div ref="mydiv">我是div</div>
<hr>
<child ref="mychild"></child>
<hr>
</div>
</body>
<script>
// 父中有age,子child 只有name,没有age,现在把父中的age传到child中,显示
var child = {
template: `
<div>
<h1>名字:{{ name }}--->年龄:{{ age }}</h1>
<button @click="handleClick">点我弹出名字</button>
</div>`,
data() {
return {
name: 'lqz',
age: 19
}
},
methods: {
handleClick() {
alert(this.name)
}
}
}
var vm = new Vue({
el: '.app',
data: {
age: 999,
},
methods: {
handleClick() {
// 1 ref 属性放在普通标签上,拿到标签的dom对象
// 通过this.$refs可以拿到所有标签上写了ref属性的 标签 ,对象类型 key值是ref对应的value值, value值是原生dom对象
// console.log(this.$refs)
// 直接修改原生dom对象的value属性,input就能看到有值了
// this.$refs.myinput.value = 'lqz is handsome'
//2 ref 属性放在 组件上,拿到的是 组件对象 ,就可以使用组件对象的属性和方法
// console.log(this.$refs) // 对象中有3个值,两个普通标签,一个组件
// this.$refs.mychild 就是组件对象,可以 .属性, .方法
// this.age = this.$refs.mychild.age
// 重点:以后就不需要关注是子传父还是父传子了,直接通过对象取值赋值即可,而且可以主动调用子组件中的函数
this.$refs.mychild.handleClick()
}
},
components: {
child
}
})
</script>
</html>
动态组件
不使用动态组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
<span @click="handleClick('home')">首页</span>| <span @click="handleClick('order')">订单</span> | <span
@click="handleClick('goods')">商品</span>
<home v-if="chooseType=='home'"></home>
<order v-else-if="chooseType=='order'"></order>
<goods v-else></goods>
</div>
</body>
<script>
var home = {
template: `
<div>
<h1>home页面</h1>
</div>`,
}
var order = {
template: `
<div>
<h1>order页面</h1>
</div>`,
}
var goods = {
template: `
<div>
<h1>商品页面</h1>
</div>`,
}
var vm = new Vue({
el: '.app',
data: {
chooseType: 'home'
},
methods: {
handleClick(type) {
this.chooseType = type
}
},
components: {
home,
order, goods
}
})
</script>
</html>
动态组件 component标签
component标签可以替换我们上面写的组件名称,变成动态加载,在他的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">
<span @click="handleClick('home')">首页</span>| <span @click="handleClick('order')">订单</span> | <span
@click="handleClick('goods')">商品</span>
<component :is="who"></component>
</div>
</body>
<script>
var home = {
template: `
<div>
<h1>home页面</h1>
</div>`,
}
var order = {
template: `
<div>
<h1>order页面</h1>
</div>`,
}
var goods = {
template: `
<div>
<h1>商品页面</h1>
</div>`,
}
var vm = new Vue({
el: '.app',
data: {
who: 'home'
},
methods: {
handleClick(type) {
this.who = type
}
},
components: {
home,
order, goods
}
})
</script>
</html>
keep-alive保持组件不销毁
在上面的component标签中我们在使用的时候会发现写上一些输入框,然后再内部输入内容的话,切换组件会导致输入框中的内容消失,这时候我们就需要使用keep-alive保持组件不销毁。
他的使用方式也很简单,用他的标签把组件套起来就可以生效
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
<span @click="handleClick('home')">首页</span>| <span @click="handleClick('order')">订单</span> | <span
@click="handleClick('goods')">商品</span>
<keep-alive>
<component :is="who"></component>
</keep-alive>
</div>
</body>
<script>
var home = {
template: `
<div>
<h1>home页面</h1>
</div>`,
}
var order = {
template: `
<div>
<h1>order页面</h1>
</div>`,
}
var goods = {
template: `
<div>
<h1>商品页面</h1>
<input type="text" > <buttont>搜索</buttont>
</div>`,
}
var vm = new Vue({
el: '.app',
data: {
who: 'home'
},
methods: {
handleClick(type) {
this.who = type
}
},
components: {
home,
order, goods
}
})
</script>
</html>
插槽
- 一般情况下,编写完1个组件之后,组件的内容都是写死的,需要加数据 只能去组件中修改,扩展性很差
- 然后就出现了插槽这个概念,只需在组件中添加
<slot></slot>
,就可以在body的组件标签中添加内容
# 一般情况下,编写完1个组件之后,组件的内容都是写死的,需要加数据 只能去组件中修改,扩展性很差
# 然后就出现了插槽这个概念,只需在组件中添加<slot></slot>,就可以在body的组件标签中添加内容
匿名插槽
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
<hr>
<home>
<div>
<img src="./img.png" alt="">
</div>
</home>
<hr>
</div>
</body>
<script>
var home = {
template: `
<div>
<h1>home页面</h1>
<slot></slot>
<h1>结束了</h1>
</div>`,
}
var vm = new Vue({
el: '.app',
data: {},
components: {
home,
}
})
</script>
</html>
具名插槽
具名插槽跟匿名插槽的区别就是可以通过给当成添加内容的标签指定slot的值来绑定到对应的slot插槽上,在组件内的html代码上给slot标签写上name属性,然后再外面home组件对应的标签上,给添加进来的html标签加上slot属性进行对应就能匹配
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
<hr>
<home>
<div slot="a">
<img src="./img.png" alt="">
</div>
<div slot="b">
我是div
</div>
</home>
<hr>
</div>
</body>
<script>
var home = {
template: `
<div>
<h1>home页面</h1>
<slot name="a"></slot>
<h1>结束了</h1>
<slot name="b"></slot>
</div>`,
}
var vm = new Vue({
el: '.app',
data: {},
components: {
home,
}
})
</script>
</html>
计算属性
- 计算属性只有使用的变量发生变化时,才重新运算
- 计算属性就像Python中的property,可以把方法/函数伪装成属性
使用事项
- 我们在使用计算属性的时候,只需要在Vue实例下定义一个computed属性,在他内部定义的函数都是相当于python中经过伪装的函数。
- 我们可以在网页中使用插值语法使用他,在使用的时候就不用加括号了。
- 计算属性必须要有return来返回值
# 计算属性只有使用的变量发生变化时,才重新运算
# 计算属性就像Python中的property,可以把方法/函数伪装成属性
计算属性基本使用
<!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>input输入单词,首字母转成大写展示</h1>-->
<!-- <input type="text" v-model="mytext">--–>{{mytext.slice(0, 1).toUpperCase() + mytext.slice(1)}}-->
<h1>input输入单词,首字母转成大写展示---函数方式---》只要页面刷新,无论跟它有没有关,都会重新运算</h1>
<!-- <input type="text" v-model="mytext">--–>{{getUpper()}}-->
<input type="text" v-model="mytext">---->{{newText}}
<br>
<input type="text" v-model="age">--->{{age}}
</div>
</body>
<script>
var vm = new Vue({
el: '.app',
data: {
mytext: '',
age: 10
},
methods: {
getUpper() {
console.log('函数---我执行了')
return this.mytext.slice(0, 1).toUpperCase() + this.mytext.slice(1)
}
},
// 计算属性---->computed 里面写方法,以后,方法当属性用 ,一定要有return值
computed: {
newText() {
console.log('计算属性---我执行了')
return this.mytext.slice(0, 1).toUpperCase() + this.mytext.slice(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>
<div class="app">
<h1>过滤案例</h1>
<p>请输入要搜索的内容:<input type="text" v-model="myText"></p>
<ul>
<li v-for="item in newDateList">{{item}}</li>
</ul>
</div>
</div>
</body>
<script>
var vm = new Vue({
el: '.app',
data: {
myText: '',
dataList: ['a', 'at', 'atom', 'be', 'beyond', 'cs', 'csrf'],
},
computed: {
newDateList() {
return this.dataList.filter(
item => item.indexOf(this.myText) >= 0
)
}
}
})
</script>
</html>
监听属性
我们在页面的html代码部分绑定两个按钮,这两个按钮的方法就是改变我们定义的变量course_type的值,而我们通过他的值来控制展示的内容
然后我们定义一个方法created,我们假设他就是用于发送ajax请求获取数据的方法,方法的内容我们定义在methods中。
接着我们在下面定义监听属性的配置,watch中的方法名称就是需要监听的变量的变量名,然后我们针对监听到变化后需要进行的操作对他进行操作。
这里我们就是获取数据展示不同的标签页
# 在data 中定义了一些变量,只要变量发生变化,我们就执行一个函数
watch:{
属性名(){
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div>
<div class="app">
<!-- <span @click="handleClick(1)">Python</span>| <span @click="handleClick(2)">Linux</span>-->
<span @click="course_type=1">Python</span>| <span @click="course_type=2">Linux</span>
<div>
假设有很多课程,点击上面的标签可以完成过滤
</div>
</div>
</div>
</body>
<script>
var vm = new Vue({
el: '.app',
data: {
course_type: '0'
},
created() {
this.getData()
},
methods: {
getData() {
// 发送ajax ,获取所有课程,通过course过滤
// http://127.0.0.1:8080/api/v1/courses?course_type=0
},
// handleClick(type){
// this.course_type=type
// this.getData()
// }
},
watch: {
course_type() {
console.log('我变化了')
this.getData()
}
}
})
</script>
</html>
node环境搭建
Vue-CLI 项目搭建
Vue-CLI 项目相当于vue框架的脚手架,可以创建vue项目
node环境介绍
node是一个基于Chrome V8引擎的javascript运行环境,是运行在服务器端的javascript
可以使用node搭建服务器,连接数据库。让前端开发人员走向后端开发。
Vue-CLI 项目(vue脚手架)必须要安装 node js 解释型语言
# Vue-CLI 项目搭建
-vue 脚手架 可以创建vue项目
# vue脚手架必须要按照 node js 解释型语言
-node js是一门后端语言
-JavaScript只能运行在浏览器中,因为浏览器中有他的解释器环境
-基于谷歌浏览器的v8引擎(js解释器),使它能够运行在操作系统上
-文件操作
-网络操作
-数据库操作 模块
-nodejs 解释器环境
-http://nodejs.cn/ 下载对应平台的nodejs解释器
-一路下一步安装
-安装完成会有两个可执行问题
python node
pip npm
-打开cmd
node 进入到了node环境
npm install 装模块
Vue-cli创建项目
vue脚手架是什么?
-
- 它是一个专门为单页面(SPA)应用快速搭建繁杂的脚手架,它是基于webpack的基础开发出来的一款能够快速的帮助我们构建一个用来开发vue的项目目录、结构(vue和webpack的项目模板)。
- vue脚手架通常使用在大型项目中,能够加快我们的开发速度。而小型项目不推荐使用脚手架,因为反而会拖慢我们项目的开发速度
为什么会有vue脚手架?
-
- 因为 webpack 配置繁琐, 阻止一批想用 vue 但是不会 webpack 的开发人员,所以作者直接将所有 vue 项目中用到的配置全部帮你写好了,这样,就不需要开发人员再去配置基础 webpack 配置项了
- 也就是说,使用 vue-cli 这个脚手架工具后,再也不用担心 webpack 配置问题了, 我们前端只需要写 vue 代码, 来实现功能即可
使用vue-cli就可以按照后端项目的写法来进行前端开发,将项目中的代码进行编译后渲染为纯粹的HTML,CSS,JS
而在这之前我们首先要完成相应的环境搭建,首先是安装node环境,到官网下载对应的安装包,选择安装路径后完成安装,并把可执行文件路径添加到环境变量就算完成环境搭建了
node一共有两个可执行文件
-node-->相当于python解释器
-npm-->相当于python自带的pip工具
node.js来源
最初js只能在浏览器中运行,浏览器相当于最佳解释器,在此基础上,基于Google浏览器的V8引擎,完成了node.js,这是使用C语言完成的可以使js运行操作系统上的网络包,文件,数据库等等,相当于针对前端人员开发的编写后端逻辑的环境,这极大方便了全栈开发人员,既可以完成页面搭建,也可以进行后端开发,而node大量使用了协程,据说性能很高
补充:
MD5是普遍使用的文件完整性校验技术,下载后的文件生成的MD5值与官网提供的如果一模一样,那说明文件没有问题,但是如果文件被篡改或者有丢失,那么它们的MD5之一定是不一样的
解释型语言与编译型语言
-解释型语言开发的代码必须要运行在解释器之上,pyinstaller在打包时也是将解释器环境打包在目录中
-编译型语言是直接将代码编译为不同平台的可执行文件,编译之后的文件直接双击即可运行
-Java虽然号称一处编码处处运行,但是它的本质是将代码运行在Java虚拟机上,原理是在代码完成之后编译为字节码文件,然后将字节码文件运行在Java虚拟机上
创建Vue项目需要使用到的工具
-2.x 使用vue-cli https://cli.vuejs.org/zh/
-3.x 使用vue-cli
-vite只能创建vue3 效率非常高
创建Vue项目过程
1.安装vue-cli
npm install -g @vue/cli
原生的npm工具使用的是国外的镜像源,我们可以使用cnpm来代替,cnpm是淘宝出的工具,下载的时候,去淘宝镜像下载,速度更快
npm install -g cnpm --registry=https://registry.npm.taobao.org
-g相当于全局安装
使用cnpm下载
cnpm install -g @vue/cli
2.创建项目
在cmd就可以进行项目创建,与Django的django-admin命令类似
vue create 项目名
创建项目会比较费时间,我们可以终止进程后,使用以下命令清一下缓存在进行创建
npm cache clean --force
创建项目慢的原因
--从GitHub拉取空项目,网络环境问
--除了项目本身之外,还会拉取项目所有依赖文件
也可以在cmd中输入vue ui,在浏览器页面中进行项目的创建
具体创建流程
vue项目目录介绍
-在命令行中执行(注意路径)
-npm run serve
-使用 pycharm ,点击绿色箭头执行
# vue 项目目录介绍
myfirstvue # 项目名
-node_modules # 非常多第三方模块,以后把项目复制给别人时【上传git要忽略掉】,这个文件夹删掉,很多小文件,项目的依赖,项目要运行,没有它不行 如果没有只需要执行 cnpm install,根据package.json的依赖包,按装好依赖、
-public # 文件夹
--favicon.ico # 网站小图标
--index.html # spa 单页面应用,以后整个vue项目都是用这一个html,但你不用动他
-src # 文件夹--以后咱们都动这里面的
--assets # 静态资源,以后前端用的图片,js,css。。都放在这里
---logo.png # 图片
--components # 以后在这里放组件, xx.vue, 小组件
---HelloWorld.vue # 提供的展示组件
--router # 安装了Router,就会有这个文件夹,下面有个index.js
---index.js
--store # 安装了Vuex,就会有这个文件夹,下面有个index.js
---index.js
--views # 页面组件
---AboutView.vue
---HomeView.vue
-App.vue # 根组件,new Vue实例管理了 div,以后原来写在div中的东西,现在都写在App.vue
-main.js # 项目的启动入口
-.gitignore # git的忽略文件,后面学了git就会了
babel.config.js # bable配置文件,不用动
jsconfig.json # 配置文件,不用动
package.json #不用动,安装了第三方模块,它自动增加
package-lock.json # 锁定文件,忽略掉
README.md # 用户手册
vue.config.js # vue的配置文件
es6 导入导出语法
App.vue、main.js、About.vue文件中的内容
App.vue中代码
main.js中代码
About.vue中代码
由以上代码可以得知,vue项目文件结构分为三部分
# 组件的html内容都写在这里
<template>
</template>
# 组件使用的样式都写在这
<style>
</style>
# js的代码都写在这
<script>
</script>
所以在之后的学习过程中,我们的vue文件也参考该结构
main.js相当于项目入口js文件,App.vue是整个项目的根组件
执行流程为
// 找到index.html中的id为app的div,以后都在App.vue中写
new Vue({
render: h => h(App)
}).$mount('#app')
导入导出语法
# 在Python中支持编写包后再其他文件中导入该包
# js在es6版本后也加入了该功能,支持包的导入,和Python的区别在于js中的包需要导出后才能在其他文件进行导入并使用
默认导出方法,只能导出一个对象
-导出语法
export default 一般是个对象
-导入语法
import 别名 from '路径' # 别名就是我们到出的对象
命名导出导入
-导出语法 # 可以导出多个
export const name = '彭于晏'
export const add = (a, b) => {
console.log(name)
return a + b
}
export const age = 19
-导入语法
import {name, add} from './lqz/s1'
console.log(name)
console.log(add(33, 44))
导入简写
包下的index.js导入的时候,不用写到index.js的路径,等同于ptyhon的__init__.py
当包中含有`index.js`时,可以只导入报名,省略具体的`index.js`
# 包是
router
-index.js
#导入的时候
import lqz from './router'
Vue项目编写步骤
# 1 以后只需要写xx.vue
-页面组件
-小组件 给页面组件用的
# 2 组件中导出
export default {
name: 'HelloWorld',
data() {
return {
xx: '彭于晏'
}
},
}
# 3 在别的组件中要用,导入,注册
# 导入
import HelloWorld from '../components/HelloWorld.vue'
# 注册
export default {
components: {
HelloWorld
}
}
# 4 注册以后,在这个组件中就可以使用导入的组件 ,写在<template>
# 自定义属性
<HelloWorld msg="传进来的p"/>
查看HomeView.vue(页面组件):
查看HelloWorld.vue(小组件):
注意这里导出都需要使用默认导出,导出一个对象,在其他页面直接使用这个对象进行注册。
正常情况下,想要使用局部组件,需要在配置项components写组件相关信息:
但是,我们可以通过导入的方式,把HelloWorld(子)中的组件到HomeView(父)中注册:
组件注册成功之后,就可以在HomeView使用了:
子组件的msg属性,是通过父组件标签里写的自定义属性传过来的:
main.js导入根组件
main.js导入了App.vue根组件:
根组件中也需要有template、script、style三种标签。如果根组件中没有script标签,会导致挂载时没有数据,只有一个template配置项。
在根组件script标签内写导出的内容:
不用给导出的对象写template属性,这里会自动将上面template标签的内容挂载到这个对象上。
根组件的内容会通过new Vue({render: h => h(App)}).$mount('#app')
这行代码,最终挂载到index.html的div标签内。
以后开发组件,只需要在template标签内写就可以了:
跟之前的写法一样,只是换了写代码的位置。
vue项目集成axios、vue项目前后端打通
# 安装axios
-npm install axios -S
# 导入使用
<script>
import axios from 'axios'
</script>
# 发送请求,获取数据
axios.get('http://127.0.0.1:8000/books/').then(res => {
console.log(res.data)
this.bookList=res.data
})
# 先用这种方式解决跨域(django 项目)
1 pip3 install django-cors-headers
2 app中注册:
INSTALLED_APPS = (
...
'corsheaders',
...
)
3 中间件注册
MIDDLEWARE = [
...
'corsheaders.middleware.CorsMiddleware',
...
]
4 把下面的复制到配置文件中
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_METHODS = (
'DELETE',
'GET',
'OPTIONS',
'PATCH',
'POST',
'PUT',
'VIEW',
)
CORS_ALLOW_HEADERS = (
'XMLHttpRequest',
'X_FILENAME',
'accept-encoding',
'authorization',
'content-type',
'dnt',
'origin',
'user-agent',
'x-csrftoken',
'x-requested-with',
'Pragma',
)
在App.vue根组件写代码:
# 安装axios
-npm install axios -S
-npm install -S axios
-npm install -S axios@1.0.1 # 安装老版本
'''-S 表示将axios模块保存到package.json中'''
# 导入使用
import axios from 'axios'
在App.vue的script标签内导入axios:
通过axios发送请求:
处理跨域问题,参照上面的配置即可。
在template标签内使用插值语法,显示后端的数据:
前后端交互流程分析:
前后端交互版登录功能
登录功能:
写事件函数,通过axios发送post请求:
后端写登录接口:
前端发送的post请求里面携带的是json字符串,所以使用原生django应该在request.body里面接受。
props配置项
# props配置项: 在里面写接受父传子自定义的属性
# props配置项有三种写法:
-1 数组写法
-2 对象对象写法
-3 对象套对象写法
# 写法总结
// 普通使用
// props: ['msg'],
// 属性验证
// props: {msg: String},
// 指定类型,必填和默认值
props: {
msg: {
type: String, //类型
required: true, //必要性
default: '老王' //默认值
}
},
新建组件child.vue
:
在根组件引入组件:
在根组件中注册:
在根组件中使用:
根组件通过自定义属性进行父传子(可以写多个自定义属性):
子组件通过props配置项接受数据(数组写法):
子组件通过props配置项接受数据(对象写法):
可以进行属性的验证,虽然报错,但前端还是显示。
子组件通过props配置项接受数据(对象套对象写法):
这里设置了,如果自定义属性没填写数值,那么默认值是老王
,且控制台不会报错:
如果设置了required:true
,自定义属性不填,控制台会报错,但是前端还是会渲染默认值老王
。
混入
# mixin(混入) 可以把多个组件共用的配置提取成一个混入对象
-把多个组件中公用的东西,抽取出来,以后可以全局使用和局部使用
# 使用步骤
-1 写个mixin/index.js
export const hunhe = {
data() {
return {
name: '彭于晏'
}
},
methods: {
handlePrintName() {
alert(this.name)
}
},
}
-2 局部导入:在组件中
import {hunhe} from "@/mixin";
mixins:[hunhe,]
-3 全局使用,在main.js 中 以后所有组件都可以用
import {hunhe} from "@/mixin";
Vue.mixin(hunhe)
局部使用mixins
新建一个组件,并将其导入到根组件:
写根组件代码:
写child组件代码:
可见根组件和子组件有同样的函数handlePrintName。
在src新建mixin文件夹,在此文件夹下新建index.js文件,写如下代码:
这里的函数,直接将组件中的函数部分赋值过来。
在根组件中导入混入对象,开始使用:
再写一个mixins配置项:
如果一个组件的配置项里既有mixins,又有methods,这两个可以一起用吗?
注意:如上示例中,混入导入的和methods中的函数都是同一个名字。
直接说结论:先使用methods中的函数,如果在methods中找不到,再用mixins的。
扩展:
混入不仅仅可以抽取methods中的函数,还可以抽取data()
数据。
查找顺序和之前的一样,先使用组件自己的数据,如果没有数据,再去mixins中找数据。
create()
这种生命周期钩子函数也可以抽取到mixins。
全局引入mixins
需要在main.js中导入mixin包:
全局引入之后,相当于在所有组件中都加入了mixins配置项,所有组件就都可以使用混入的函数和数据了。
mixins具体使用情景:
比如有一个记录用户浏览记录的功能,通过引入mxins,可以实现在每个组件都可以使用这个功能。
插件
# 功能:用于增强Vue
本质:包含install方法的一个对象,install的第一个参数是Vue,第二个以后的参数是插件使用者传递的数据
# 使用步骤
-写一个 plugins/index.js
import Vue from "vue";
import axios from "axios";
import {hunhe} from '@/mixin'
export default {
install(miVue) {
// console.log(miVue)
// 1 vue 实例上放个变量
// Vue.prototype.$name = 'lqz' // 类比python,在类上放了一个属性,所有对象都能取到
// Vue.prototype.$ajax = axios
// 2 使用插件,加入混入
// 全局使用混入
// Vue.mixin(hunhe)
// 3 定义全局组件
// 4 定义自定义指令 v-lqz
Vue.directive("fbind", {
//指令与元素成功绑定时(一上来)
bind(element, binding) {
element.value = binding.value;
},
//指令所在元素被插入页面时
inserted(element, binding) {
element.focus();
},
//指令所在的模板被重新解析时
update(element, binding) {
element.value = binding.value;
},
});
}
}
2 在main.js 中使用插件
import plugins from '@/plugins'
Vue.use(plugins) // 本子,使用use,会自动触发插件对象中得install
3 以后再组件中可以直接用插件中写的东西
scoped样式
# 父组件写了style,子组件都会使用父组件的style
如果在根组件中写了样式,会在所有页面组件都生效,这样不太好,所有需要使用scoped。
# 父组件的样式,在子组件中会生效,在style上写 <style scoped> </style>让该样式只在当前组件中生效
# 示例
<style scoped>
h1 {
background-color: chartreuse;
}
</style>
父组件写了style,子组件都会使用父组件的style
如何写一个样式,令所有组件都生效:使用全局样式,在assets下创建css文件夹。
localStorage和sessionStorage
# window 浏览器对象有的东西
# 如果想在浏览器中存储数据,
永久存储:localStorage 不登录加购物车,没登录 搜索过的商品
关闭页面数据就没了(临时存储):sessionStorage
设定一个时间,到时候就过期:cookie
# 补充:序列化和反序列化
// 对象转json字符串
// JSON.stringify(person)
// json字符串转对象
// JSON.parse()
<template>
<div id="app">
<h1>localStorage操作</h1>
<button @click="saveStorage">点我向localStorage放数据</button>
<button @click="getStorage">点我获取localStorage数据</button>
<button @click="removeStorage">点我删除localStorage放数据</button>
<h1>sessionStorage操作</h1>
<button @click="saveSessionStorage">点我向localStorage放数据</button>
<button @click="getSessionStorage">点我获取localStorage数据</button>
<button @click="removeSessionStorage">点我删除localStorage放数据</button>
<h1>cookie操作</h1>
<button @click="saveCookie">点我向localStorage放数据</button>
<button @click="getCookie">点我获取localStorage数据</button>
<button @click="removeCookie">点我删除localStorage放数据</button>
</div>
</template>
<script>
import cookies from 'vue-cookies'
export default {
name: 'App',
data() {
return {}
},
methods: {
saveStorage() {
var person = {
name: '彭于晏',
age: 38
}
localStorage.setItem('userinfo', JSON.stringify(person))
},
getStorage() {
let userinfo = localStorage.getItem('userinfo')
console.log(userinfo)
console.log(typeof userinfo)
},
removeStorage() {
// localStorage.clear()
localStorage.removeItem('userinfo')
},
saveSessionStorage() {
var person = {
name: '彭于晏',
age: 38
}
sessionStorage.setItem('userinfo', JSON.stringify(person))
},
getSessionStorage() {
let userinfo = sessionStorage.getItem('userinfo')
console.log(userinfo)
console.log(typeof userinfo)
},
removeSessionStorage() {
// localStorage.clear()
sessionStorage.removeItem('userinfo')
},
saveCookie() {
cookies.set('name','lqz','7d') // 按秒计
},
getCookie() {
console.log(cookies.get('name'))
},
removeCookie() {
cookies.remove('name')
}
}
}
</script>
<style scoped>
h1 {
background-color: aqua;
}
</style>
集成elementui
# 第三方 样式库 常见的
-饿了么团队:elementui
-iview
-移动端的ui:vant
# 使用步骤
- 安装 npm i element-ui -S
-在main.js中引入