Vue-cli
升级vue-cli v4.5
npm i -g @vue/cli@next
vite工具
npm init vite-app <project-name>
cd <project-name>
npm install
npm run dev
compostion api
为vue提供了更好的逻辑复用和代码逻辑
<h1>{{counter}}</h1>
<h2>{{num}}</h2>
<p ref="desc"></p>
</div>
</template>
<script>
import {computed, reactive, onMounted, onUnmounted, toRefs, watch, ref} from "vue";
export default {
name: 'HelloWorld',
props: {
msg: String
},
setup(){
const {counter,num}=getcounter()
//使用元素引用
const desc = ref(null)
//监听器
watch(counter,(val,oldVal)=>{
const p = desc.value
p.textContent=`change from ${oldVal} to ${val}`
})
return {counter,num,desc}
}
}
function getcounter(){
const data= reactive({
counter:1,
num: computed(() => data.counter*2)
})
//定时器
let timer
onMounted(()=>{
timer = setInterval(()=>{
data.counter++
},1000)
})
//什么时候移除
onUnmounted(()=>{
clearInterval(timer)
})
return toRefs(data)
}
</script>
- reactive的用法与ref的用法相似,也是将数据变成响应式数据,当数据发生变化时UI也会自动更新。不同的是ref用于基本数据类型,而reactive是用于复杂数据类型,比如对象和数组
- ef:用于给基本类型的数据添加响应式
- reactive用于给对象添加响应式
- computed这个计算属性方法,接收一个getter函数,返回一个默认不可手动修改的ref对象
- toRefs接收一个对象作为参数,它会遍历对象身上的所有属性,然后挨个调用toRef执行
- 为了访问到DOM元素的值,要用到ref属性
ref和reactive的区别
ref也可以传入对象,也可以实现响应式,其内部会自动调用reactive方法
reactive传入基本类型控制台会出警告,并且不会实现响应式
给ref的响应式对象赋值的时候要用.value的形式赋值
404
{
path: "/:catchAll(.*)",
component: NotFund
}
echarts
安装
npm install echarts --save
store.js
npm install vuex --save
创建vuex/store.js文件
import { createStore } from "vuex";
import { createApp } from 'vue'
const store =createStore({
state(){
return{
count:1
}
},
mutations:{
increment(state){
state.count++
}
},
actions:{
setcount(context,newvalue){
context.commit("increment",newvalue)
}
}
})
const app = createApp("#app")
app.use(store)
export default store
在组件中引入store
import store from "@/vuex/store";
JWT 登录验证
JSON Web Token ,通过数字签名方式,以Json对象为载体。
JWT由3部分组成
- Header
{
‘typ’ :'Jwt',
'alg': 'HS256'
}
- Payload
{
'sub':'1234567890',
'name':'john',
'admin':true
}
- Signature
var encodeString =base64UrlEncode(header)+'.'+base64urlEncode(payload);
var signature = HMACSHA256(encodedString,'secret');
依赖
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
JWTUtill
public class JWTUtill {
// token时效:24小时
public static final long EXPIRE = 1000 * 60 * 60 * 24;
// 签名哈希的密钥,对于不同的加密算法来说含义不同
public static final String APP_SECRET = "ukc8BDbRigUDaY6pZFfWus2jZWLPHO";
public static String getJwtToken(String username, String role){
String JwtToken = Jwts.builder()
.setHeaderParam("typ", "JWT")
.setHeaderParam("alg", "HS256")
.setSubject("admin-test")//主题
.setExpiration(new Date(System.currentTimeMillis() + EXPIRE))
.claim("username", username)
.claim("role", role)
.setId(UUID.randomUUID().toString())
// HS256算法实际上就是MD5加盐值,此时APP_SECRET就代表盐值
.signWith(SignatureAlgorithm.HS256, APP_SECRET)
.compact();
System.out.println(JwtToken);
parse(JwtToken);
return JwtToken;
}
//解析token
public static String parse(String token){
JwtParser jwtParser=Jwts.parser();
Jws<Claims> claimsJws = jwtParser.setSigningKey(APP_SECRET).parseClaimsJws(token);
Claims claims = claimsJws.getBody();
System.out.println(claims.get("username"));
return (String)claims.get("username");
}
}
新买的书
Vue基础语法
- 1.v-once指令插值
使用之后更新data属性时不需要在更新页面数据
<h1 v-once>{{message}}</h1>
- 2.v-html指令插值
双大括号会将数据解释为普通文本,而非html代码。使用v-html插值可以输出真正的HTML。
<h1 v-html="msg"><h1/>
data:{
msg:"<span style='color:blue'>BLUE</span>"
}
- 3.v-bind指令插值
开发阶段有些属性是动态的,可以使用v-bind动态绑定属性,”v-bind:“也可以简化为“:”
<img v-bind:src="imgUrl">
data:{
mgUrl:"img/1.jpg
}
v-bind也可以绑定其他属性例如class和style,也可以绑定多个style属性
<div :style="{styleA,styleB}">
data:{
styleA:{
color:'red',
fontSize:'14px'
},
styleB:{
width:100+'px'
}
}
- 4.插值中使用JavaScript表达式
每个绑定只能包含单个表达式
例如:
{{number+1}}
{{ok?'YES':'NO'}}
{{message.split('').reverse().join('')}}
<div v-bind:id="'list-' + id"></div>
3.1.2指令
- 动态参数
<a v-bind:[attributeName]='url'></a>
- 修饰符
<from v-on:submit.prevent="onSubmit"></from>
//提交表单不用刷新页面
3.1.3过滤器- 定义全局过滤器
Vue.filter('过滤器名称',function(value1,[,value2,...]){
//逻辑代码
})
2. 定义局部过滤器
new Vue({
filters:{
'过滤器名称':function(value1,[,value2,...]){
//逻辑代码
}
}
})
- 过滤器使用地方
<!--在双花括号中-->
<div>{{数据属性名称 | 过滤器名称}}</div>
<div>{{数据属性名称 | 过滤器名称(参数值)}}</div>
<!--在v-bind中-->
<div v-bind:id="数据属性名称 | 过滤器名称"></div>
<div v-bind:id="数据属性名称 | 过滤器名称(参数值)"></div>
3.2.1数据选项
data是Vue实例的数据对象,Vue使用递归法将data属性转换为getter/setter
<div id="app">{{message}}</div>
var values ={message: 'Hello Vue !'
_name:'beixi'
}
var vm = new Vue({
el:'#app',
data:values
})
console.log(vm._name) ;//undefined
console.log(vm.$data._name) ;//'beixi'
Vue实例创建之后,在控制台输入vm.$data即可访问原始数据
console.log(vm.$data.message)
以’_'和‘$’开头的属性不会被Vue代理
3.2.2属性选项
Vue为组件开发提供属性(props)选项,可以为组件注册动态属性,来处理业务之间的差异性。
3.2.3方法选项
可以通过选项属性methods对象来定义方法,并且使用v-on指令来监听DOM事件。
3.2.4计算属性
在{{ }}中进行一些计算再展示出来
<td>{{Math+English+Chinese}}</td>
- computed计算属性
var vm = new Vue({
el:'#app',
data:{
Math:66,
English:77,
Chinese
},
computed:{
sum:functuion(){
return this.Math+this.English+this.Chinese;
},
average:function(){
return Math.round(this.sum/3)};
}
})
计算属性好处是调用数据缓存,提高了程序的性能和数据提取的速度。如果将计算过程卸载methods中,数据不会缓存下来,需要重新计算。
3.2.5表单控件
v-model指令在表单上创建双向数据绑定
v-model会忽略所有表单元素的value、checked、selected attribute的初始值而总是将Vue实例数据作为数据来源,所以应该通过JavaScript在组件的data选项中声明初始值。
修饰符
- .lazy
默认情况下v-model每次在input事件触发后将输入框的值与数据进行同步,此时添加.lazy修饰符,从而转换为在change事件以后进行同步
<input v-model.lazy="msg">
- .number
将用户输入的值自动转换为数值类型,可以给v-model添加。
<input v-model.number="age" type=“number”>
- .trim自动过滤用户输入的首尾空白字符
<input v-model.trim="msg">
3.2.6生命周期
- beforereate实例初始化之后,数据观测(data observer)和event/watcher事件配置之前被调用
- created实例已经创建之后被调用,数据观测(data observer),属性和方法运算,以及event/watcher事件回调。挂载还没开始$el属性目前不可见。
- beforeMount,在挂载之前被调用,相关的render函数首次被调用
- Mounted,el被新创建的vm.$el替换,并挂载到实例上之后调用该钩子。
- beforeUpdate数据更新时调用,发生在虚拟DOM重新渲染和打补丁之前。可以在这个钩子中进一步更改状态,这不会触发附加的重新渲染过程。
- Updated由于数据更改导致虚拟DOM重新渲染和打补丁,在这之后会调用该钩子。大多数情况下避免在此期间更改状态,会导致无限循环。
- beforeDestory实例被摧毁之前调用。
- Destoryed Vue实例摧毁后调用
3.3模板渲染
- v-if
- v-else-if
- v-else
v-if、v-else-if、v-else之间需要紧挨着,如果他们之间插入一行新代码,会报错。 - v-show 当绑定事件符合条件时才会显示。
如果需要频繁的切换,则使用v-show;如果很少改变使用v-if - key 声明两个元素是独立的
例:
<div id="app">
<p v-f="ok">
<label>Username</label>
<input placeholder="Enter your username" v-key="username-input">
</p>
<p v-else>
<label>Email</label>
<input placeholder="Enter your email adress" v-key="email-input">
</p>
<button @click="ok=!ok">切换</button>
</div>
如果不加v-key的话,输入框内容不会清空
3.3.2列表渲染
- v-for ,items 是源数据组,而item是被迭代数组元素的别名
<li v-for="item in items">
{{item.name}}
</li>
<li v-for="(item,index) in items">
{{index}}--{{item.name}}
</li>
2v-for用于对象
<li v-for="value in object">
{{value}}
</li>
遍历对象属性的时候,有两个可选参数,分别是键名和索引
<li v-for="(value,key,index) in object">
{{index}}--{{key}}:{{value}}
</li>
2v-for用于数字
<li v-for="n in 10t">
{{n}}
</li>
3.3.3 template标签用法
Vue内置了<template>
可以将多个元素进行渲染。
<template v-for="item in items">
<template>
3.4事件绑定
3.4.1 基本用法
- v-on:事件名.修饰符 = 方法名() | 方法名 | 简单的JS表达式
简写:@事件名.修饰符 = 方法名() | 方法名 | 简单的JS表达式
事件名: click|keydown|keyup|mouseover|mouseout|自定义事件名
传入事件对象
<button @click="eventFn($event)" data-aid='123' >事件对象</button>
var vm = new Vue({
el:'#app',
methods:{
eventFn:function(e){
e.srcElement.style.background='red';
console.log(e.srcElement.dataset.aid);//获取自定义属性的值
}}
})
3.4.2 修饰符
- .stop:阻止事件继续传播
- .prevent:阻止默认事件
- .capture:添加事件监听器时使用事件捕获模式
- .self:当前元素自身时触发处理函数时才会触发函数
- .once:只触发一次。
- @keydown=‘show($event)’键盘事件
.stop :由于事件冒泡的机制,我们给元素绑定点击事件的时候,也会触发父级的点击事件,一键阻止事件冒泡,简直方便得不行。相当于调用了 event.stopPropagation() 方法。
.prevent:用于阻止事件的默认行为,例如当点击提交按钮时阻止对表单的提交。相当于调用了 event.preventDefault() 方法。
.capture默认的是事件触发是从目标开始往上冒泡,当我们加了这个 .capture 以后我们就反过来了,事件触发从包含这个元素的顶层开始往下触发。
.self当我 们加了这个 .self 以后,我们点击 button 不会触发父元素的点击事件 shout,只有当点击到父元素的时候(蓝色背景)才会触发 shout,从这个 self 的英文翻译过来就是自己、本身可以看出这个修饰符的用法。
.once这个修饰符的用法也是和名字一样简单粗暴,只能用一次,绑定了事件以后只能触发一次,第二次就不会触发。
@keydown=‘show($event)’
方式一:
methods:{
show : function(ev){
/* 在函数中获取ev.keyCode */
console.log(ev.keyCode)
if(ev.keyCode == 13)
alert('你按了回车')
}
}
方式二:
<input type="text" @keyup.enter="show()"> //回车执行
<input type="text" @keyup.up="show()"> //上键执行
<input type="text" @keyup.down="show()"> //下键执行
<input type="text" @keyup.left="show()"> //左键执行
<input type="text" @keyup.right="show()"> //右键执行
第四章 自定义指令
4.1 指令的注册
自定义指令分为全局注册和局部注册
语法:Vue.directive(id,definition)
id是唯一标识。
例如:
Vue.directive('focus',{
//定义对象
})
也可以注册局部指令,组件或Vue构造函数中接受一个directives的选项,格式如下:
var vm = new Vue({
el:'#app',
directives:{
focus:{
//定义对象}
}})
4.2 指令的定义对象
- bind:只调用一次,指令第一次绑定到元素时调用,在这里可以进行一次初始化设置。
- inserted:被绑定元素插入父节点时调用
- update:被绑定元素所在的模板更新时调用,而不论绑定值是否变化。通过比较更新前后绑定的值。
- componentUpdated:被绑定元素所在模板完成一次更新周期时调用
- unbing:只调用一次,指令与元素解绑时调用
例子:自定义v-focus指令
<div id="app">
<p>页面载入时,input自动获取焦点:</p>
<input v-focus>
</div>
<script>
//注册一个全局自定义指令 v-focus
/* Vue.directive("focus",{
//当绑定元素插入到DOM中
inserted:function(el){
//聚焦元素
el.focus()
}
}) */
//创建根实例
</script>
4.3指令实例属性
- el:指令所绑定的元素,可以用来直接操作DOM。
- binding:一个对象,包含以下property。
name :指令名,不包括v-前缀。
value:指令绑定值
oldValue:指令绑定的前一个值,仅在update和componentUpdated钩子中可用。
expression:字符串形式的指令表达式。
arg:传给指令的参数,可选。
modifiers:一个包含修饰符的对象。 - vnode:Vue编译生成的虚拟节点。(详细在VNode API)
- oldVnode:上一个虚拟节点,仅在update和componentUpdated钩子中可用