Vue基础
3.Vue模板语法
3.1指令
v-cloak防止抖动
先通过样式隐藏内容呢,然后在内存中进行替换,替换后显示最后的结果
[v-cloak]{
display: none;
}
<div v-cloak>
</div>
v-text指令
没有抖动
<div v-text="msg">
</div>
v-html指令
存在安全问题
本网站内部数据可以使用,来自第三方的数据不可用
<div v-html="msg">
</div>
v-pre指令,显示原始信息
不编译,显示原始信息
<div v-pre>
</div>
3.2双向数据绑定
<input type="text" v-model="msg">
3.3.数据响应式
数据改变了会影响页面内容
3.3.1v-once指令
显示的内容只编译一次,然后就不具备响应式的能力了,这样可以提高性能
<div v-once>
</div>
3.4事件绑定
3.4.1v-on指令及简写形式
<input type="button" v-on:click="num++">
<input type="button" @click="num++">
<input type="button" @click="handle">
<input type="button" @click="handle()">
methods属性中定义方法
methods: {
handle: function(){
//这里的this就是Vue的实例对象
this.num++;
}
}
3.4.2事件参数传递,事件对象必须放在最后一个参数的位置,且名称固定为$event,
1.如果事件绑定函数名称作为事件函数的第一个参数
2.如果事件绑定函数调用,name事件对象必须作为最后一个参数显示传递,并且事件对象的名称必须是$event
<button @click="handle("hi",$event)></button>
methods: {
handle: function(p1,event){
//这里的this就是Vue的实例对象
this.num++;
}
}
3.4.3事件修饰符
<div @click="handle0">
//.stop阻止冒泡
<button @click.stop="handle1">
点击1
</button>
<a href="http://baidu.com" @click.prevent="handle2">百度</a>
</div>
methods:{
handle0: function(){
this.num++;
},
handle1: function(event){
// 阻止冒泡
// event.stopPropagation();
},
handle2: function(event){
//阻止默认行为
//event.preventDefault();
}
}
3.4.4按键修饰符
<input type="button" v-on:click="handleSubmit" value="提交">
<input type="text" v-on:keyup.enter="handleSubmit">
<input type="text" v-on:keyup.delete="clearContent">
methods:{
handleSubmit: function(){
console.log(1);
},
clearContent: function(){
//按delete键调用该方法清空数据
}
}
3.4.5自定义按键修饰符
方式一:
Vue.config.keyCodes.f1 = 112
<input type="text" v-on:keyup.f1="handle">
方式二:
<input type="text" v-on:keyup.112="handle">
3.5属性绑定
v-bind指令及缩写用法
<a v-bind:href="url">跳转</a>
<a :href="url">跳转</a>
v-model
<input v-bind:value="msg" v-on:input="msg=$event.target.value">
<input type="text" v-model="msg">
3.6样式绑定
class样式处理
样式绑定相关语法细节:
1.对象绑定和数据绑定可以结合使用
2.class绑定的值可以简化操作
3.默认的class如何处理? 默认的class会保留
对象语法
<div v-bind:class="{ active:isActive }">
</div>
<div v-bind:class="classObj">
</div>
data: {
isActive:true,
classObj:{
active:true,
error:true
}
}
数组语法
<div v-bind:class="[activeClass, errorClass]">
</div>
<div v-bind:class="arrClasses">
</div>
data: {
activeClass: "active",
errorClass: "error",
arrClasses: ['active','error']
}
默认的class
<div class="base" v-bind:class="arrClasses">
</div>
style样式处理
对象语法
<div v-bind:style="{color: activeColor,fontSize:fontSize}">
</div>
<div v-bind:style="objStyles">
</div>
data: {
activeColor:"blue",
fontSize: "14px",
objStyles: {
color: "green",
width: "14px",
height: "300px"
}
}
数组语法
<div v-bind:style="[baseStyles, overridingStyles]">
</div>
3.7分支循环结构
分支结构
-
v-if
-
v-else
-
v-else-if
-
v-show
<div v-if="score >= 90">
优秀
</div>
<div v-else-if="score < 90 && score >= 80">
良好
</div>
<div v-else-if="score < 80 && score>60">
一般
</div>
<div v-else>
比较差
</div>
<div v-show="flag">
测试 v-show
</div>
data: {
score: 99,
flag: false
}
v-if 与 v-show的区别
-
v-if 控制元素是否渲染到页面
-
v-show 控制元素样式是否显示 ,已经渲染到页面 (display: none)
循环结构
- v-for遍历数组
<li v-for="item in list"></li>
<li v-for="(item,index) in list"> + "---" + </li>
- key的作用: 帮助Vue区分不同的元素,从而提高性能
<li :key="index" v-for="(item,index) in list"> + "---" + </li>
- v-for遍历对象
<div v-for="(value, key, index) in object">
</div>
- v-if和v-for结合使用
<div v-if="value==12" v-for="(value, key, index) in object">
</div>
5.常用特性
5.1常用特性概览
- 表单操作
- 自定义指令
- 计算属性
- 过滤器
- 侦听器
- 生命周期
5.2表单操作
- input单行文本
- textarea多行文本
- select下拉选
- radio单选框
- checkbox多选框
表单域修饰符
- number: 转化为数值
- trim: 去掉开始和结尾的空格
- lazy: 将input事件切换为change事件(change事件是失去焦点触发)
<input type="text" v-model.number="age">
<input type="text" v-model.trim="info">
<input type="text" v-model.lazy="msg">
自定义指令
<input type="text" v-focus>
Vue.directive('focus',{
inserted: function(el){
//el表示指令所绑定的元素
el.focus();
}
})
带参数的自定义指令
Vue.directive('color',{
inserted: function(el,binding) {
el.style.backgroundColor = binding.value.color;
}
})
<input type="text" v-color="{color:'orange'}">
局部指令
directives: {
focus: {
//指令的定义
inserted: function(el){
el.focus()
}
}
}
计算属性
表达式的计算逻辑可能会比较复杂,使用计算属性可以使模板内容更加简洁
<div>
</div>
data: {
msg: "hello"
},
computed: {
reversedMessage: function(){
return this.msg.split('').reverse().join('')
}
}
计算属性与方法的区别
- 计算属性是基于他们的依赖进行缓存的
- 方法不存在缓存
<div></div>
<div></div>
<div></div>
<div></div>
data: {
msg: "hello"
},
methods: {
reverseMessage: function(){
console.log("methods")
return this.msg.split('').reverse().join('')
}
},
computed: {
reverseString: function(){
console.log("computed")
return this.msg.split('').reverse().join('')
}
}
以上代码控制台将打印一次”computed”和两次”methods”.
侦听器
侦听器的应用场景
数据变化时执行异步或开销较大的操作
侦听器的用法
data: {
firstName: '',
lastName: '',
fullName: ''
},
watch: {
//方法名要和属性名保持一致
firstName: function(val){
//Val表示变化之后的值
this.fullName= val +'' + this.lastName;
},
lastName: function(val){
this.fullName = this.firstName + " " + val;
}
}
过滤器
过滤器的作用是什么
格式化数据,比如将字符串格式化为首字母大写,将日期格式化为指定的格式等
自定义过滤器
Vue.filter("upper", function(value){
// 过滤器业务逻辑
return value.charAt(0).toUpperCase() + value.slice(1);
})
过滤器的使用
<div>
</div>
<div>
</div>
<div v-bind:id = "id | upper">
</div>
局部过滤器
filters: {
upper: function(val){
// 过滤逻辑
return val.charAt(0).toUpperCase() + val.slice(1);
}
}
带参数的过滤器
Vue.filter('format', function(value,arg1){
//value就是过滤器传递过来的参数
})
<div>
</div>
生命周期
主要阶段
-
挂载(初始化相关属性)
beforeCreate
created
beforeMount
mounted
-
更新(元素或组件的变更操作)
beforeUpdate
updated
-
销毁(销毁相关属性)
beforeDestroy
destroyed

6.组件化开发
组件注册
全局组件注册语法
Vue.component('button-counter', {
data: function(){
return {
count: 0
}
},
template:'<button v-on:click="count++">点击了8次</button>'
})
组件的用法
<div>
<button-counter></button-counter>
</div>
组件注册注意事项
-
data必须是一个函数
-
组件模板内容必须是单个根元素
-
组件模板内容可以是模板字符串
组件命名方式
- 短横线方式
Vue.component('my-component',{/* ... */})
- 驼峰方式
Vue.component('MyComponent',{/* ... */})
总结: 如果使用驼峰式命名组件,那么在使用组件的时候,只能在字符串模板中使用驼峰的方式使用组件,但是在普通的标签模板中,必须使用短横线的方式使用组件
局部组件注册
局部组件只能在注册它的父组件中使用
var ComponentA = { /* ... */ }
var ComponentB = { /* ... */ }
var ComponentC = { /* ... */ }
new Vue({
el: '#app',
components: {
'component-a': ComponentA,
'component-b': ComponentB,
'component-c': ComponentC,
}
})
Vue调试工具
组件间数据交互
父组件向子组件传值
组件内部通过props接收传递过来的值
Vue.component('menu-item', {
props: ['title'],
template: '<div></div>'
})
父组件通过属性将值传递给子组件
<menu-item title="来自父组件的数据"></menu-item>
<menu-item :title="title"></menu-item>
props属性名规则
- 在props中使用驼峰形式,模板中需要使用短横线的形式
- 字符串形式的模板中没有这个限制
Vue.component('menu-item', {
//在JavaScript中是驼峰式的
props: ['menuTitle'],
template: '<div> </div>'
})
在HTML中是短横线方式的
<menu-item menu-title="nihao"></menu-item>
props属性值类型
属性值的类型是数值和布尔值时,使用v-bind得到的值的类型为对应类型
props传递数据的原则: 单向数据流
- 字符串String
- 数值 Number
- 布尔值 Boolean
- 数组Array
- 对象 Object
子组件向父组件传值
子组件通过自定义事件向父组件传递信息
<button v-on:click='$emit("enlarge-text")'>
扩大字体
</button>
<button v-on:click='$emit("enlarge-text", 0.1)'>
扩大字体
</button>
父组件监听子组件的事件
<menu-item v-on:enlarge-text='fontSize += 0.1'></menu-item>
<menu-item v-on:enlarge-text='fontSize += $event'></menu-item>
非父子组件间传值
单独的事件中心管理组件间的通信
var eventHub = new Vue()
监听事件与销毁事件
eventHub.$on('add-todo', addTodo)
eventHub.$off('add-todo')
触发事件
eventHub.$emit('add-todo', id)
组件插槽
- 父组件向子组件传递内容
插槽位置
Vue.component('alert-box', {
template: `
<div class="demo-alert-box">
<strong>Error!</strong>
<slot></slot>
</div>
`
})
插槽内容
<alert-box>Something bad happened.</alert-box>
具名插槽
插槽定义
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
插槽内容
<base-layout>
<h1 slot="header">
标题内容
</h1>
<p>
主要内容1
</p>
<p>
主要内容2
</p>
<p slot="footer">
底部内容
</p>
</base-layout>
作用域插槽
插槽定义
<ul>
<li v-for="item in list" v-bind:key="item.id">
<slot v-bind:item="item">
</slot>
</li>
</ul>
插槽内容
<fruit-list v-bind:list="list">
<template slot-scope="slotProps">
<strong v-if="slotProps.item.current">
</strong>
</template>
</fruit-list>
7.前后端交互
前后端交互模式
接口调用方式
- 原生ajax
- 基于jQuery的ajax
- fetch
- axios
Promise用法
异步调用
异步效果分析
- 定时任务
- Ajax
- 事件函数
多次异步调用的依赖分析
- 多次异步调用的结果顺序不确定
- 异步调用结果如果存在依赖需要嵌套
Promise用法
Promise是异步编程的一种方案,从语法上讲,Promise是一个对象,从它可以获取异步操作的消息
使用Promise主要有以下好处:
- 可以避免多层异步调用嵌套问题(回调地狱)
-
Promise对象提供了简洁的API,使得控制异步操作更加容易
- 实例化Promise对象,构造函数中传递函数,该函数中用于处理异步任务
- resolve和reject两个参数用于处理成功和失败两种情况,并通过p.then获取处理结果
var p = new Promise(function(resolve, reject){
//成功时调用 resolve()
//失败时调用 reject()
})
p.then(function(ret){
//从resolve得到正常结果
},function(ret){
//从reject得到错误信息
});
基于Promise处理Ajax请求
function queryData(url){
var p = new Promise(function(resolve,reject){
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if (xhr.readyState != 4) {
return;
}
if (xhr.readyState == 4 && xhr.status == 200){
//处理正常的情况
resolve(xhr.responseText);
}else {
reject('服务器错误');
}
};
xhr.open('get', url);
xhr.send(null);
})
}
queryData('http://localhost:3000/data').then(function(data){
console.log(data);
},function(info){
console.log(info);
})
发送多次ajax请求
queryData()
.then(function(){
return queryData();
})
.then(function(){
return queryData();
})
.then(function(){
return queryData();
})
then参数中的函数返回值
返回Promise实例对象
- 返回的该实例对象会调用下一个then
返回普通值
- 返回的普通值会直接传递给下一个then,通过then参数中函数的参数接收该值
Promise常用的API
实例方法
- p.then() 得到异步任务的正确结果
- p.catch() 获取异常信息
- p.finally() 成功与否都会执行(尚且不是正式标准)
queryData()
.then(function(data){
console.log(data);
})
.catch(function(data){
console.log(data);
})
.finally(function(){
console.log('finished');
})
queryData()
.then(function(data){
console.log(data);
},function(data){
console.log(data);
})
.finally(function(){
console.log('finished');
})
对象方法
- Promise.all() 并发处理多个异步任务,所有任务都执行完成才能得到结果
- Promise.race() 并发处理多个异步任务,只要有一个任务完成就能得到结果
Promise.all([p1,p2,p3]).then((result) => {
console.log(result);
})
Promise.race([p1,p2,p3]).then((result) => {
console.log(result);
})
fetch用法
fetch概述
基本特性
- 更加简单的数据获取方式,功能更强大,更灵活,可以看做是xhr的升级版
- 基于Promise实现
语法结构
fetch(url).then(fn2)
.then(fn3)
...
.catch(fn)
fetch的基本用法
fetch('/abc').then(data => {
//text() 方法属于fetchAPI的一部分,它返回一个Promise实例对象,用于获取后台返回的数据
return data.text();
}).then(ret => {
//注意这里得到的才是最终的数据
console.log(ret);
})
fetch请求参数
常用配置选项
- method(String): HTTP请求方法,默认为GET(GET/POST/PUT/DELETE)
- body(String): HTTP的请求参数
- headers(Object): HTTP的请求头,默认为{}
fetch('/abc',{
method: 'get'
}).then(data => {
return data.text();
}).then(ret => {
//注意这里得到的才是最终的数据
console.log(ret);
});
GET请求方式的参数传递
fetch('/abc?id=123').then(data => {
return data.text();
}).then(ret => {
//注意这里得到的才是最终的数据
console.log(ret);
});
fetch('/abc/123',{
method: 'get'
}).then(data => {
return data.text();
}).then(ret => {
//注意这里得到的才是最终的数据
console.log(ret);
});
DELETE请求方式的参数传递
fetch('/abc/123',{
method: 'delete'
}).then(data => {
return data.text();
}).then(ret => {
//注意这里得到的才是最终的数据
console.log(ret)
})
POST请求方式的参数传递
fetch('/books', {
method: 'post',
body: 'uname=lisi&pwd=123',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
}
}).then(data => {
return data.text();
}).then(ret => {
//注意这里得到的才是最终的数据
console.log(ret)
})
fetch('/books', {
method: 'post',
body: JSON.stringify({
uname: 'lisi',
age: 12
}),
headers: {
'Content-Type': 'application/json',
}
}).then(data => {
return data.text();
}).then(ret => {
//注意这里得到的才是最终的数据
console.log(ret)
})
PUT请求方式的参数传递
fetch('/books', {
method: 'put',
body: JSON.stringify({
uname: 'lisi',
age: 12
}),
headers: {
'Content-Type': 'application/json',
}
}).then(data => {
return data.text();
}).then(ret => {
//注意这里得到的才是最终的数据
console.log(ret)
})
fetch响应结果
响应数据格式
- text(): 将返回体处理成字符串类型
- json(): 返回结果和JSON.parse(responseText)一样
fetch('/abc').then(data => {
// return data.text();
return data.json();
}).then(ret=>{
console.log(ret);
})
axios用法
axios的基本特性
- 支持浏览器和node.js
- 支持promise
- 能拦截请求和响应
- 自动转换JSON数据
axios的基本用法
axios.get('/adata').then(ret => {
//data属性名称是固定的,用于获取后台响应的数据
console.log(ret.data);
})
axios的常用API
- get: 查询数据
- post: 添加数据
- put: 修改数据
- delete: 删除数据
axios的参数传递
GET传递参数
- 通过URL传递参数
- 通过params选项传递参数
axios.get('/adata?id=123')
.then(ret => {
console.log(ret.data)
})
axios.get('/adata/123')
.then(ret => {
console.log(ret.data)
})
axios.get('/adata', {
params: {
id: 123
}
})
.then(ret => {
console.log(ret.data)
})
DELETE传递参数
- 参数传递方式与GET类似
axios.delete('/adata?id=123')
.then(ret => {
console.log(ret.data)
})
axios.delete('/adata/123')
.then(ret => {
console.log(ret.data)
})
axios.delete('/adata', {
params: {
id: 123
}
})
.then(ret => {
console.log(ret.data)
})
POST传递参数
- 通过选项传递参数(默认传递的是json格式的数据)
axios.post('/adata',{
uname: 'tom',
pwd: 123
}).then(ret => {
console.log(ret.data)l
})
- 通过URLSearchParams传递参数 (application/x-www-form-urlencoded)
const params = new URLSearchParams();
params.append('param1','value1');
params.append('param2','value2');
axios.post('/api/test',params).then(ret => {
console.log(ret.data);
})
PUT传递参数
- 参数传递方式与POST类似
axios.put('/adata/123',{
uname: 'tom',
pwd: 123
}).then(ret => {
console.log(ret.data);
})
axios的响应结果
响应结果的主要属性
- data: 实际响应回来的数据
- headers: 响应头信息
- status: 响应状态码
- statusText: 响应状态信息
axios的全局配置
- axios.defaults.timeout = 3000; //超时时间
- axios.defaults.baseURL = ‘http://localhost:3000/app’; //默认地址
- axios.defaults.headers[‘mytoken’] = ‘231532414’; //设置请求头
axios拦截器
请求拦截器
axios.interceptors.request.use(function(config){
//再请求发出之前进行一些信息设置
return config;
},function(err){
//处理响应的错误信息
})
响应拦截器
axios.interceptors.response.use(function(res){
//再这里对返回的数据进行处理
return res;
},function(err){
//处理响应的错误信息
})
接口调用-async/await
async/await的基本用法
- async/await是ES7引入的新语法,可以更加方便的进行异步操作
- async关键字用于函数上(async函数的返回值是Promise实例对象)
- await关键字用于async函数当中(await可以得到异步的结果)
async function queryData(){
const ret = await axios.get('/data');
return ret;
}
queryData().then(ret=>{
console.log(ret);
})
async/await处理多个异步请求
async function queryData(id){
const info = await axios.get("/async1");
const ret = await axios.get("/async2?info="+info.data);
return ret.data;
}
queryData.then(ret => {
console.log(ret);
})
8.前端路由
路由的基本概念与原理
路由
路由是一个比较广义和抽象的概念,路由的本质就是对应关系
在开发中,路由分为:
- 后端路由
- 前端路由
后端路由
- 概念: 根据不同的用户URL请求,返回不同的内容
- 本质: URL请求地址与服务器资源之间的对应关系
SPA (Single Page Application)
- 后端渲染(存在性能问题)
- Ajax前端渲染(前端渲染提高性能,但是不支持浏览器的前进后退操作)
- SPA(Single Page Application)单页面应用程序: 整个网站只有一个页面, 内容的变化通过Ajax局部更新实现,同时支持浏览器地址栏的前进和后退操作
- SPA实现原理之一: 基于URL地址的hash (hash的变化会导致浏览器记录访问历史的变化,但是hash的变化不会触发新的URL请求)
- 再实现SPA的过程中,最核心的技术点就是前端路由
前端路由
- 概念: 根据不同的用户事件,显示不同的页面内容
- 本质: 用户事件与事件处理函数之间的对应关系
实现简易前端路由
- 基于URL中的hash实现(点击菜单的时候改变URL的hash, 根据hash的变化控制组件的切换)
Vue Router
Vue Router包含的功能有:
- 支持HTML5历史模式或hash模式
- 支持嵌套路由
- 支持路由参数
- 支持编程式路由
- 支持命名路由
vue-router的基本使用
基本使用步骤
- 引入相关的库文件
- 添加路由链接
- 添加路由填充位
- 定义路由组件
- 配置路由规则并创建路由实例
- 把路由挂载到Vue根实例中
添加路由链接
<!-- router-link 是vue中提供的标签,默认会被渲染为 a 标签 -->
<!-- to 属性默认会被渲染为href属性 -->
<!-- to属性的值默认会被渲染为 # 开头的hash地址 -->
<router-link to="/user">User</router-link>
<router-link to="/register">Register</router-link>
添加路由填充位
<!-- 路由填充位 (也叫作路由占位符) -->
<!-- 将来通过路由规则匹配到的组件,将会被渲染到 router-view 所在的位置 -->
<router-view></router-view>
定义路由组件
var User = {
template: '<div>User</div>'
}
var Register = {
template: '<div>Register</div>'
}
配置路由规则并创建路由实例
var router = new VueRouter({
//routes 是路由规则数组
routes: [
//每个路由规则都是一个配置对象,其中至少包含path和component两个属性
//path表示当前路由规则匹配的hash地址
// component表示当前路由规则对应要展示的组件
{path:'/user',component: User},
{path:'/register',component: Register}
]
})
把路由挂载到Vue根实例中
new Vue({
el: '#app',
// 为了能够让路由规则生效,必须把路由对象挂载到vue实例对象上
//router: router
router
})
路由重定向
路由重定向指的是: 用户在访问地址A的时候,强制用户跳转到地址C,从而展示特定的组件页面;
通过路由规则的redirect属性,指定一个新的路由地址,可以很方便地设置路由的重定向
var router = new VueRouter({
routes: [
//其中,path表示需要被重定向的原地址, redirect表示将要被重定向的新地址
{path:'/', redirect:'/user'},
{path:'/user', component:User},
{path:'/register', component:Register}
]
})
嵌套路由用法
嵌套路由功能分析
- 点击父级路由链接显示模板内容
- 模板内容中又有子级路由链接
- 点击子级路由链接显示子级模板内容
动态匹配路由的基本用法
var router = new VueRouter({
routes: [
//动态路径参数 以冒号开头
{path:'/user/:id',component:User}
]
})
const User = {
//路由组件中通过$route.params获取路由参数
template: '<div> User </div>'
}
路由组件传递参数
$route与对应路由形成高度耦合,不够灵活,所以可以使用props将组件和路由解耦
props的值为布尔类型
const router = new VueRouter({
routes: [
//如果props被设置为true, route.params将会被设置为组件属性
{path:'/user/:id',component:User,props:true}
]
})
const User = {
props: ['id'], //使用props接收路由参数
template: '<div>用户id: </div>' //使用路由参数
}
props的值为对象类型
const router = new VueRouter({
routes: [
{path:'/user/:id',component:User,props:{uname:'lisi',age:12}}
]
})
const User = {
props: ['uname','age'],
template: '<div>用户信息: </div>'
}
props的值为函数类型
const router = new VueRouter({
routes: [
{path:'/user/:id',component:User,props:route=>({uname:'zs',age:20,id:route.params.id})}
]
})
const User = {
props: ['uname','age','id'],
template: '<div>用户信息: </div>'
}
命名路由的配置规则
为了更加方便的表示路由的路径,可以给路由规则起一个别名,即为”命名路由”
const router = new VueRouter({
routes: [
{
path: '/user/:id',
name: 'user',
component: User
}
]
})
<router-link :to="{name:‘user’,params: {id:123}}">User</router-link>
router.push({name:'user',params:{id:123})
vue-router编程式导航
页面导航的两种方式
- 声明式导航
- 编程式导航
常用的编程式导航API如下
- this.$router.push(“hash地址”)
- this.$router.go(n)
编程式导航参数规则
router.push()方法的参数规则
//字符串(路径名称)
router.push('/home')
//对象
router.push({path:'/home'})
//命名的路由(传递参数)
router.push({name:'/user',params:{userId:123}})
//带查询参数,变成 /register?uname=lisi
router.push({path:'/register',query: {uname:'lisi'}})