尤雨溪
vue:渐进式 JavaScript 框架
声明式渲染 => 组件系统 => 客户端路由 => 集中式状态管理 => 项目构建
https://cn.vuejs.org/v2/api/
<body>
<div id="app">
<div>{{msg}}div>
<div>{{1+2}}div>
<div>{{msg+'---'+123}}div>
div>
<script src="./js/vue.js">script>
<script>
/*
vue的使用步骤
1、需要提供标签用于填充数据
2、引入 vue.js 库文件
3、使用vue的语法做功能
4、把 vue 提供的数据,填充到标签里面
*/
var vm = new Vue({
// 创建一个vue实例
// el 表示 那个容器,里面写的是选择器
// data 填充数据
el: '#app',
data: {
msg: 'Hello world'
}
})
script>
body>
插值表达式
vue代码运行原理分析
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XYsdaJps-1620387784164)(vue基础.assets/image-20201018122455568.png)]
前端渲染方式
vue 模块语法
- 插值表达式
- 指令
- 事件绑定
- 属性绑定
- 样式绑定
- 分支循环结构
什么是指令:指令的本质就是自定义属性
v-cloak指令用法
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<style>
[v-cloak] {
display: none;
}
style>
head>
<body>
<div id="app">
<div v-cloak>{{msg}}div>
<div v-cloak>{{1+2}}div>
<div v-cloak>{{msg+'---'+123}}div>
div>
<script src="./js/vue.js">script>
<script>
/*
v-cloak 指令的用法
1、提供样式
[v-cloak]{
display:none;
}
2、在插值表达式所在的标签中,添加 v-cloak指令
原理:先通过样式隐藏内容,然后在内存中进行值的替换,替换好之后在显示最终的结果
*/
var vm = new Vue({
el: '#app',
data: {
msg: 'Hello world'
}
})
script>
body>
html>
1、v-text 填充纯文本
相比插值表达式更加简洁
2、v-html 填充HTML片段
存在安全问题
本网站内部数据可以使用,来自第三方的数据不可以用
3、v-pre 填充原始信息
显示原始信息,跳过编译过程(分析编译过程)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zGfCHDSy-1620387784166)(vue基础.assets/image-20201018125344603.png)]
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<style>
[v-cloak] {
display: none;
}
style>
head>
<body>
<div id="app">
<div>{{msg}}div>
<div v-text="msg">div>
<div v-html="msg1">div>
<div v-pre>{{msg}}div>
div>
<script src="./js/vue.js">script>
<script>
var vm = new Vue({
el: '#app',
data: {
msg: 'Hello world',
msg1: '你好
'
}
})
script>
body>
html>
如何理解响应式
- html5中的响应式(屏幕尺寸的变化导致样式的变化)
- 数据的响应式(数据的变化导致页面内容的变化),数据驱动页面内容的变化。
数据绑定:将数据填充到标签中
v-once:只显示一次,显示内容之后不再具有响应式功能
<div v-once>{{msg}}div>
v-model 指令在表单 元素上
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VXeUMw4E-1620387784168)(vue基础.assets/image-20201018131417691.png)]
双向:
1、用户修改页面内容,数据会变 2、数据发生变化,插值表达式也会跟着发生变化
<body>
<div id="app">
<div>{{msg}}div>
<div>
<input type="text" v-model="msg">
div>
div>
<script src="./js/vue.js">script>
<script>
var vm = new Vue({
el: '#app',
data: {
msg: 'Hello world',
msg1: '你好
'
}
})
script>
body>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YUE1wTtK-1620387784172)(vue基础.assets/image-20201018132213553.png)]
v-on 指令用法
<input type="button" v-on:click='num++'>
v-on 简写形式
<input type="button" @click='num++'>
在Vue中,方法定义在 vue的实例对象中,和data同一级,值是一个对象
事件函数的调用方式:
<button v-on:click='handle'>点击button>
<button @click='handle()'>点击2button>
<body>
<div id="app">
<div>{{num}}div>
<div>
<button v-on:click='num++'>点击button>
<button @click='num++'>点击2button>
div>
<div>
<button v-on:click='handle'>点击button>
<button @click='handle()'>点击2button>
div>
div>
<script src="./js/vue.js">script>
<script>
var vm = new Vue({
el: '#app',
data: {
num: 0,
},
methods: {
handle: function () {
// 注意:这里不能直接写 num++
// this 就是 vue的实例vm
console.log(this);
this.num++;
}
}
})
script>
body>
<body>
<div id="app">
<div>{{num}}div>
<div>
<button v-on:click='handle1'>点击button>
<button @click='handle(123,456,$event)'>点击2button>
div>
div>
<script src="./js/vue.js">script>
<script>
var vm = new Vue({
el: '#app',
data: {
num: 0,
},
methods: {
handle: function (p, p1, event) {
// 注意:这里不能直接写 num++
// this 就是 vue的实例vm
//console.log(this);
console.log(event.target);
this.num++;
},
handle1: function (event) {
console.log(event.target);
}
}
})
script>
body>
<a href="" @click.stop="handle">跳转a>
<a href="" @click.prevent="handle">跳转a>
<a href="" @click.prevent.stop="handle">跳转a>
<a href="" @click.self="handle">跳转a>
<div style="width: 100px;height: 100px;background: #000;" @click.self='handle'>
<a href="" @click='handle'>跳转a>
div>
<body>
<div id="app">
<div style="width: 100px;height: 100px;background: #000;" @click='handle'>
<a href="" @click.stop='handle'>跳转a>
div>
<a href="" @click.stop="handle">跳转a>
<a href="" @click.prevent="handle">跳转a>
div>
<script src="./js/vue.js">script>
<script>
var vm = new Vue({
el: '#app',
data: {
num: 0,
},
methods: {
handle: function (p, p1, event) {
alert('11')
},
}
})
script>
body>
<input type="text" @keyup.65='handle'>
<input type="text" @keyup.s='handle'>
<input type="text" v-model="msg" @keyup.aaa="handle">
Vue.config.keyCodes.aaa = 65
// 这个后面的值,代表按键的ASII码,前面的值就是一个名字
// 这样表示只有按 a(65 对应的就是a) 的时候,并且绑定 @keyup.aaa 事件才会触发后面的函数
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<style>
[v-cloak] {
display: none;
}
style>
head>
<body>
<div id="app">
<div>
数值A:<input type="text" v-model="num1">
div>
<div>
数值A:<input type="text" v-model="num2">
div>
<div>
<button @click="handle">计算button>
div>
<div>
计算结果<span>{{sum}}span>
div>
div>
<script src="./js/vue.js">script>
<script>
var vm = new Vue({
el: '#app',
data: {
num1: '',
num2: '',
sum: '',
},
methods: {
handle: function () {
this.sum = parseInt(this.num1) + parseInt(this.num2)
},
}
})
script>
body>
html>
不能直接在后面写地址
<body>
<div id="app">
<a v-bind:href='url'>跳转a>
<button v-on:click='handle'>切换button>
div>
<script src="./js/vue.js">script>
<script>
var vm = new Vue({
el: '#app',
data: {
url: 'http://www.baidu.com'
},
methods: {
handle: function () {
// 修改url
this.url = 'http://itcast.cn'
}
}
})
script>
body>
<body>
<div id="app">
<div>{{msg}}div>
<div>
<input type="text" @input="handle" v-bind:value="msg">
div>
div>
<script src=" ./js/vue.js">script>
<script>
var vm = new Vue({
el: '#app',
data: {
msg: ''
},
methods: {
handle: function (e) {
this.msg = e.target.value
}
}
})
script>
body>
<div :class="{active:isActive}">div>
<style>
.active {
border: 1px solid red;
width: 100px;
height: 100px;
}
.error {
background: orange;
}
style>
head>
<body>
<div id="app">
<div class="one" :class="{active:isActive,error:isError}">div>
<button @click="handle">切换button>
div>
<script src=" ./js/vue.js">script>
<script>
var vm = new Vue({
el: '#app',
data: {
isActive: true,
isError: true
},
methods: {
handle: function () {
this.isActive = !this.isActive
}
}
})
script>
body>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<style>
.active {
border: 1px solid red;
width: 100px;
height: 100px;
}
.error {
background: orange;
}
style>
head>
<body>
<div id="app">
<div class="one" :class="[activeClass,errorClass]">div>
<button @click="handle">切换button>
div>
<script src=" ./js/vue.js">script>
<script>
var vm = new Vue({
el: '#app',
data: {
activeClass: 'active',
// 左边是变量,右边是类名
errorClass: 'error'
},
methods: {
handle: function () {
this.isActive = !this.isActive
}
}
})
script>
body>
html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<style>
.active {
border: 1px solid red;
width: 100px;
height: 100px;
}
.error {
background: orange;
}
style>
head>
<body>
<div id="app">
<div class="one" :class="[activeClass,{error:isError}]">div>
<button @click="handle">切换button>
<div :class="arrClasses">div>
<div :class="objClasses">div>
div>
<script src=" ./js/vue.js">script>
<script>
var vm = new Vue({
el: '#app',
data: {
activeClass: 'active',
// 左边是变量,右边是类名
isError: true,
arrClasses: ['active'],
objClasses: {
active: true,
error: true
}
},
methods: {
handle: function () {
this.isActive = !this.isActive
}
}
})
script>
body>
html>
和 class 类似
<div :style="{color:activeColor}">div>
<div :style="[baseStyles]">div>
<body>
<div id="app">
<div :style="{color:isColor}">2222div>
<div :style="objStyle">2222div>
<div>数组类型控制stylediv>
<div :style="[objStyle,overrideStyles]">div>
div>
<script src=" ./js/vue.js">script>
<script>
var vm = new Vue({
el: '#app',
data: {
isColor: 'red',
objStyle: {
border: '1px solid green',
width: '200px',
height: '200px'
},
overrideStyles: {
border: '5px solid orange',
backgroundColor: 'blue'
}
},
methods: {
}
})
script>
body>
前三个指令渲染出来,只会有一个div
<body>
<div id="app">
<div v-if="score>=90">优秀div>
<div v-else-if="score>=80">良好div>
<div v-else-if="score>=60">一般div>
<div v-else>比较差的div>
<div v-show="flag">测试v-showdiv>
div>
<script src="./js/vue.js">script>
<script>
var vm = new Vue({
el: '#app',
data: {
score: 99,
flag: false,
}
})
script>
body>
<li v-for="item in list ">{{item}}li>
<li v-for="(item,index) in list">{{item}}+'---'+{{index}}li>
<li :key="item.id" v-for="(item,index) in list">{{item}}+'---'+{{index}}li>
<body>
<div id="app">
<ul>
<li v-for='item in fruits'>{{item}}li>
<li v-for='(item,index) in fruits'>{{item}}+'---'+{{index}}li>
ul>
div>
<script src="./js/vue.js">script>
<script>
var vm = new Vue({
el: '#app',
data: {
fruits: ['apple', 'orange', 'banana']
}
})
script>
body>
<body>
<div id="app">
<ul>
<li :key="index" v-for="(value,key,index) in obj">{{value}}+'--'{{key}}+'--'{{index}}li>
ul>
div>
<script src="./js/vue.js">script>
<script>
var vm = new Vue({
el: '#app',
data: {
obj: {
uname: '呆呆狗',
age: 20,
gender: '前端开发工程师'
}
}
})
script>
body>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<style type="text/css">
.tab ul {
overflow: hidden;
padding: 0;
margin: 0;
}
.tab ul li {
box-sizing: border-box;
padding: 0;
float: left;
width: 100px;
height: 45px;
line-height: 45px;
list-style: none;
text-align: center;
border-top: 1px solid blue;
border-right: 1px solid blue;
cursor
}
.tab ul li:nth-child(1) {
border-left: 1px solid blue;
}
.tab ul li.active {
background-color: orange;
}
.tab div {
width: 500px;
height: 300px;
display: none;
text-align: center;
font-size: 30px;
line-height: 300px;
border: 1px solid blue;
border-top: 0px;
}
.tab div.current {
display: block;
}
style>
head>
<body>
<div id="app">
<div class="tab">
<ul>
<li v-for='(item,index) in list' @click="handle(index)" :class="hoverIndex==index?'active':''">
{{item.title}}li>
ul>
<div v-for='(item, index) in list' :class="hoverIndex==index?'current':''">
<img :src="item.path">
div>
div>
div>
<script src="./js/vue.js">script>
<script>
var vm = new Vue({
el: '#app',
data: {
hoverIndex: 0,
list: [
{
id: 1,
title: 'apple',
path: 'img/apple.png'
},
{
id: 2,
title: 'orange',
path: 'img/orange.png'
},
{
id: 3,
title: 'lemon',
path: 'img/lemon.png'
}]
},
methods: {
handle: function (index) {
this.hoverIndex = index
console.log(this.hoverIndex);
}
}
})
script>
body>
html>
表单操作
基于vue 的表单操作:input 单行文本、textarea 多行文本 、select 下拉多选 、 radio 单选框 、 checkbox 多选框
<input type="text" v-model="uname">
<div>
<span>性别:span>
<span>
<input type="radio" id="male" value="1" name="xm" v-model="gender">
<label for="male">男label>
<input type="radio" id="female" value="2" name="xm" v-model="gender">
<label for="female" id="female">女label>
span>
div>
<div>
<span>爱好:span>
<input type="checkbox" id="ball" value="1" v-model="habit">
<label for="ball">篮球label>
<input type="checkbox" id="sing" value="2" v-model="habit">
<label for="sing">唱歌label>
<input type="checkbox" id="code" value="3" v-model="habit">
<label for="code">写代码label>
div>
<script>
var vm = new Vue({
el: ' #app',
data: {
uname: "呆呆狗",
gender: 1,// 若是1 则会找绑定v-model gender的输入框,找到value等于1的,2则找到2
habit: [1, 2],
},
methods: {
handle: function () {
console.log(this.uname);
console.log(this.gender);
console.log(this.habit.join(''));// 12
}
}
})
script>
<select v-model="selectAnser">
<option value="0">请选择职业...option>
<option value="1">教师option>
<option value="2">软件工程师option>
<option value="3">律师option>
select>
<div>
<span>个人简介:span>
<textarea v-model="textMore">textarea>
div>
<script>
var vm = new Vue({
el: ' #app',
data: {
uname: "呆呆狗",
gender: 1,// 若是1 则会找绑定v-model gender的输入框,找到value等于1的,2则找到2
habit: [1, 2],
selectAnser: 2, // 单选是一个数,多选是数组
textMore: '请输入内容'
},
methods: {
handle: function () {
console.log(this.uname);
console.log(this.gender);
console.log(this.habit.join(''));// 12
}
}
})
script>
<input v-model.trim="msg">input>
v-model 默认是捆绑着 input事件的
<div id="app">
<input type="text" v-focus>
div>
<script src="./js/vue.js">script>
<script>
// 第一个参数是指令的名称,自定义的
Vue.directive('focus', {
inserted: function (el) {
// 第一个参数就是元素,就是指令所绑定的元素
// 获取元素的焦点
el.focus()
}
})
var vm = new Vue({
el: ' #app',
data: {
},
methods: {
}
})
script>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ffhaVaGo-1620387784174)(vue基础.assets/image-20201019163344281.png)]
<div id="app">
<input type="text" v-color="msg">
div>
<script src="./js/vue.js">script>
<script>
// 第一个参数是指令的名称,自定义的
Vue.directive('color', {
inserted: function (el, binding) {
// 第一个参数就是元素,就是指令所绑定的元素
el.style.backgroundColor = binding.value
}
})
var vm = new Vue({
el: ' #app',
data: {
msg: 'red'
},
methods: {
}
})
script>
<div id="app">
<input type="text" v-color="msg">
div>
<script src="./js/vue.js">script>
<script>
var vm = new Vue({
el: ' #app',
data: {
msg: 'red'
},
methods: {
},
directives: {
color: {
inserted: function (el, binding) {
// 第一个参数就是元素,就是指令所绑定的元素
el.style.backgroundColor = binding.value
}
}
}
})
script>
把复杂的表达式抽取出来,使模板内容更加简洁
<div id="app">
<div>{{msg}}div>
<div>{{reverseString}}div>
div>
<script src="./js/vue.js">script>
<script>
var vm = new Vue({
el: ' #app',
data: {
msg: 'red'
},
methods: {
},
computed: {
// 第一个参数是自定义的名字
reverseString: function () {
return this.msg.split("").reverse().join("")
}
}
})
script>
<div id="app">
<div>{{msg}}div>
<div>{{reverseString}}div>
<div>{{reverseString}}div>
div>
<script src="./js/vue.js">script>
<script>
var vm = new Vue({
el: ' #app',
data: {
msg: 'red'
},
methods: {
},
computed: {
// 第一个参数是自定义的名字
reverseString: function () {
console.log('执行了')
return this.msg.split("").reverse().join("")
}
}
})
script>
上面的代码,只会输出一次 ‘执行了’,因为执行完以后,缓存中有,所以不会再执行那个函数。计算属性的值,没有发生变化的时候,是先访问缓存的值
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3njUR25M-1620387784176)(vue基础.assets/image-20201019170218502.png)]
应用场景:数据变化时执行异步或开销较大的操作
<div id="app">
<div>
<span>名:span>
<span>
<input type="text" v-model="firstName">
span>
div>
<div>
<span>姓:span>
<span>
<input type="text" v-model="lastName">
span>
div>
<div>{{fullName}}div>
div>
<script src="./js/vue.js">script>
<script>
var vm = new Vue({
el: ' #app',
data: {
firstName: "Jim",
lastName: "Green",
fullName: "Jim Green"
},
methods: {
},
watch: {
firstName: function (val) {
// fullName 要和变量名字一致
// val表示 firstName 最新值
this.fullName = val + ' ' + this.lastName
},
lastName: function (val) {
this.fullName = this.firstName + ' ' + val
}
}
})
script>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
head>
<body>
<div id="app">
<div>
<span>用户名:span>
<span>
<input type="text" v-model.lazy='uname'>
span>
<span>
{{tip}}
span>
div>
div>
<script src="./js/vue.js">script>
<script>
/*
1、采用侦听器监听用户名的变化
2、如果变化,调用后台接口进行验证
3、根据验证的结果调整提示信息
*/
var vm = new Vue({
el: '#app',
data: {
uname: '',
tip: '',
},
methods: {
checkname: function (uname) {
// 调用接口,但是可以使用定时任务的方式模拟接口调用
// 定时器中的this指向的是window
var that = this;
setTimeout(function () {
// 模拟接口调用
if (uname == 'admin') {
that.tip = '用户名已经存在,请更换用户名'
}
else {
that.tip = '用户名可以使用'
}
}, 2000)
}
},
watch: {
uname: function (val) {
// 调用后台接口进行验证用户名的合法性
this.checkname(val);
// 修改提示信息
this.tip = '正在验证'
}
}
})
script>
body>
html>
格式化数据,比如将字符串格式首字母大写、日期格式化等
一个插值表达式,一个属性绑定
<div>{{msg | 过滤器名称}}</div>
<div v-bind:id="id | 过滤器名称"></div>
Vue.filter('过滤器名称',function(value){
// 过滤器业务逻辑
})
//也可以局部定义
<div id="app">
<input type="text" v-model="msg">
<div>{{msg|upper}}div>
div>
<script src="./js/vue.js">script>
<script>
Vue.filter('upper', function (val) {
// 获取到的值
return val.charAt(0).toUpperCase() + val.slice(1)
})
var vm = new Vue({
el: ' #app',
data: {
msg: ''
},
filters: {
upper: function (val) {
// 名称,
return val.charAt(0).toUpperCase() + val.slice(1)
}
}
})
script>
Vue.filter('过滤器名称',function(val,arg1,arg2){
// val 必须是第一个,他表示传递过来的要处理的参数
// arg 是其他的参数
})
<div id="app">
<div>{{date | format('yyyy-MM-dd')}}div>
div>
<script src="./js/vue.js">script>
<script>
Vue.filter('format', function (val, arg) {
// 这里的arg 指的就是 'yyyy-MM-dd'
if (arg == 'yyyy-MM-dd') {
var ret = ''
ret += val.getFullYear() + '-' + (val.getMonth() + 1) + '-' + val.getDate()
return ret
}
})
var vm = new Vue({
el: ' #app',
data: {
date: new Date()
},
filters: {
}
})
script>
创造前后 => 安装前后 =>更新前后 =>销毁前后
挂载包括:创造和安装
vue实例的产生过程
<body>
<div id="app">
<div>{{msg}}div>
<button @click='update'>更新button>
<button @click='destroy'>销毁button>
div>
<script src="./js/vue.js">script>
<script type="text/javascript">
/*
Vue实例的生命周期
*/
var vm = new Vue({
el: '#app',
data: {
msg: '生命周期'
},
methods: {
update: function () {
this.msg = 'hello world';
},
destroy: function () {
this.$destroy();
}
},
// 挂载阶段 初始化相关属性,例如 watch ,methods
beforeCreate: function () {
console.log('beforeCreate');
},
created: function () {
console.log('created');
},
beforeMount: function () {
console.log('beforeMount');
},
mounted: function () {
// 这个函数 执行 就表示初始化已经完成
// 最常用的就是,调用后台接口,
console.log('mounted');
},
// 更新阶段 元素或组件的变更操作
beforeUpdate: function () {
console.log('beforeUpdate');
},
updated: function () {
console.log('updated');
},
// 销毁阶段 销毁相关属性
beforeDestroy: function () {
console.log('beforeDestroy');
},
destroyed: function () {
console.log('destroyed');
}
});
script>
body>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ltLunJrQ-1620387784177)(file://F:/web%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91/%E9%BB%91%E9%A9%AC%E8%87%AA%E5%AD%A6/vue/B%E7%AB%99/B%E7%AB%99vue%E7%AC%94%E8%AE%B0.assets/image-20200801140707017.png?lastModify=1603112008)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TmlOXKXI-1620387784178)(vue基础.assets/image-20200801141548596.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R56otYHh-1620387784179)(vue基础.assets/image-20200801142355344.png)]
在VUE中用索引修改的数据不是响应式变化 的,上面的两个方法,可以用在数组和对象身上
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Documenttitle>
<style type="text/css">
.grid {
margin: auto;
width: 530px;
text-align: center;
}
.grid table {
border-top: 1px solid #C2D89A;
width: 100%;
border-collapse: collapse;
}
.grid th,
td {
padding: 10;
border: 1px dashed #F3DCAB;
height: 35px;
line-height: 35px;
}
.grid th {
background-color: #F3DCAB;
}
.grid .book {
padding-bottom: 10px;
padding-top: 5px;
background-color: #F3DCAB;
}
.total {
height: 30px;
line-height: 30px;
background-color: orangered;
}
style>
head>
<body>
<div id="app">
<div class="grid">
<div>
<h1>图书管理h1>
<div class="book">
<div>
<label for="id">
编号:
label>
<input type="text" id="id" v-model='id' :disabled="flag" v-focus>
<label for="name">
名称:
label>
<input type="text" id="name" v-model='name'>
<button @click='handle' :disabled='submitFlag'>提交button>
div>
div>
div>
<div class="total">
<span>图书总数:span>
<span>{{total}}span>
div>
<table>
<thead>
<tr>
<th>编号th>
<th>名称th>
<th>时间th>
<th>操作th>
tr>
thead>
<tbody>
<tr :key='item.id' v-for='item in books'>
<td>{{item.id}}td>
<td>{{item.name}}td>
<td>{{item.date | format('yyyy-MM-dd hh:mm:ss')}}td>
<td>
<a href="" @click.prevent='toEdit(item.id)'>修改a>
<span>|span>
<a href="" @click.prevent='deleteBook(item.id)'>删除a>
td>
tr>
tbody>
table>
div>
div>
<script type="text/javascript" src="js/vue.js">script>
<script type="text/javascript">
Vue.directive('focus', {
inserted: function (el) {
el.focus();
}
})
Vue.filter('format', function (value, arg) {
function dateFormat(date, format) {
if (typeof date === "string") {
var mts = date.match(/(\/Date\((\d+)\)\/)/);
if (mts && mts.length >= 3) {
date = parseInt(mts[2]);
}
}
date = new Date(date);
if (!date || date.toUTCString() == "Invalid Date") {
return "";
}
var map = {
"M": date.getMonth() + 1, //月份
"d": date.getDate(), //日
"h": date.getHours(), //小时
"m": date.getMinutes(), //分
"s": date.getSeconds(), //秒
"q": Math.floor((date.getMonth() + 3) / 3), //季度
"S": date.getMilliseconds() //毫秒
};
format = format.replace(/([yMdhmsqS])+/g, function (all, t) {
var v = map[t];
if (v !== undefined) {
if (all.length > 1) {
v = '0' + v;
v = v.substr(v.length - 2);
}
return v;
} else if (t === 'y') {
return (date.getFullYear() + '').substr(4 - all.length);
}
return all;
});
return format;
}
return dateFormat(value, arg);
})
var vm = new Vue({
el: '#app',
data: {
submitFlag: false,
flag: false,
id: '',
name: '',
books: [{
id: 1,
name: '三国演义',
date: 2525609975000
}, {
id: 2,
name: '水浒传',
date: 2525609975000
}, {
id: 3,
name: '红楼梦',
date: 2525609975000
}, {
id: 4,
name: '西游记',
date: 2525609975000
}]
},
methods: {
handle: function () {
if (this.flag) {
// 编辑图书
// 就是根据当前的ID去更新数组中对应的数据
this.books.some((item) => {
if (item.id == this.id) {
item.name = this.name;
// 完成更新操作之后,需要终止循环
return true;
}
});
this.flag = false;
} else {
// 添加图书
var book = {};
book.id = this.id;
book.name = this.name;
book.date = '';
this.books.push(book);
// 清空表单
this.id = '';
this.name = '';
}
// 清空表单
this.id = '';
this.name = '';
},
toEdit: function (id) {
// 禁止修改ID
this.flag = true;
console.log(id)
// 根据ID查询出要编辑的数据
var book = this.books.filter(function (item) {
return item.id == id;
});
console.log(book)
// 把获取到的信息填充到表单
this.id = book[0].id;
this.name = book[0].name;
},
deleteBook: function (id) {
// 1、根据ID 查找元素的索引
var index = this.books.findIndex(function (item) {
return item.id == id;
});
this.books.splice(index, 1);
/* var book = this.books.filter(function (item) {
return item.id != id;
})
console.log(book); */
}
},
computed: {
total: function () {
return this.books.length
}
},
watch: {
name: function (val) {
var flag = this.books.some(function (item) {
return item.name == val
})
if (flag) {
this.submitFlag = true;
}
else {
this.submitFlag = false
}
}
}
});
script>
body>
html>
组件化规范 web conmponents
Vue.component(组件名称,{
data:组件数组,
template:组件模板内容
})
<div id="app">
<button-counter></button-counter>
</div>
<script src="./js/vue.js"></script>
<script>
/* Vue.component(组件名称,{
data:组件数组,
template:组件模板内容
}) */
Vue.component('button-counter', {
data: function () {
// data 里面放的是 组件的数据,是一个函数,return 返回一个对象,把数据放在这个对象里面
return {
count: 0
}
},
template: ' ',
methods: {
handle: function () {
this.count++
}
}
})
var vm = new Vue({
el: '#app',
data: {
}
})
</script>
组件命名的方式
1、短横线方式
Vue.component('my-component',{……})
2、驼峰方式
Vue.component('MyComponent',{……})
<div id="app">
<button-counter></button-counter>
<!-- 上面的写法 正确 -->
<HelloContent></HelloContent>
<!-- 上面的写法就是错误 -->
</div>
局部组件只能再注册它的父组件中使用,不能在全局组件中使用
<div id="app">
<hello-world></hello-world>
<hello-tom></hello-tom>
<hello-jerry></hello-jerry>
<!--
hello world
hello tom
hello jerry
-->
</div>
<script src="./js/vue.js"></script>
<script>
var HelloWorld = {
data: function () {
return {
msg: 'hello world'
}
},
template: `{{msg}} `
}
var HelloTom = {
data: function () {
return {
msg: 'hello tom'
}
},
template: `{{msg}} `
}
var HelloJerry = {
data: function () {
return {
msg: 'hello Jerry'
}
},
template: `{{msg}} `
}
var vm = new Vue({
el: '#app',
data: {
},
components: {
'hello-world': HelloWorld,
'hello-tom': HelloTom,
'hello-jerry': HelloJerry,
}
})
</script>
props 是单项数据流,只允许 父组件给子组件传值
子组件通过 props 接收父组件传递过来的值
父组件通过 属性值 将值传递给子组件
Vue.component('menu-item',{
props:['title'],
template:'{{title}}'
})
<menu-item title="来自父组件的数据"></menu-item>
<menu-item :title="title"></menu-item>
<body>
<div id="app">
<!-- 在这里,app 就相当于是 父组件 menu-item 就是子组件-->
<div>{{pmsg}}</div>
<menu-item title="来自父组件的值"></menu-item>
<menu-item :title="ptitle"></menu-item>
<div>传多个值</div>
<menu-item :title="ptitle" content="hello"></menu-item>
<!--
父组件的内容
子组件本身的数据---来自父组件的值-- - undefined
子组件本身的数据---动态绑定属性-- - undefined
传多个值
子组件本身的数据---动态绑定属性-- - hello
-->
</div>
<script src="./js/vue.js"></script>
<script>
Vue.component('menu-item', {
props: ['title', 'content'],
data: function () {
return {
msg: '子组件本身的数据',
}
},
template: '{{msg +"---"+title+"-- - "+content}}'
})
var vm = new Vue({
el: '#app',
data: {
pmsg: '父组件的内容',
ptitle: '动态绑定属性'
},
})
</script>
</body>
//在html中是短横线方式的
<menu-item menu-title="你好"></menu-item>
Vue.conponents('menu-item',{
// 在 JavaScript 中是驼峰形式的
props:['menuTitle'],
template:'{{menuTitle}}'
})
<body>
<div id="app">
<div>{{pmsg}}div>
<menu-item my-title="来自父组件的值">menu-item>
div>
<script src="./js/vue.js">script>
<script>
Vue.component('menu-item', {
props: ['MyTitle', 'content'],
data: function () {
return {
msg: '子组件本身的数据',
}
},
template: '{{msg +"---"+MyTitle}}'
})
var vm = new Vue({
el: '#app',
data: {
pmsg: '父组件的内容',
ptitle: '动态绑定属性'
},
})
script>
body>
布尔和数值 通过 v-bind 绑定 得到到都是对应的类型,不是通过v-bind 则得到的都是字符串类型
建议传值采用 v-bind进行传值,并且等号右边加引号
<body>
<div id="app">
<div>{{pmsg}}div>
<menu-item :pstr='pstr' :pnum='12' :pboo='true' :parr='parr' :pobj='pobj'>menu-item>
div>
<script src="./js/vue.js">script>
<script>
Vue.component('menu-item', {
props: ['pstr', 'pnum', 'pboo', 'parr', 'pobj'],
data: function () {
return {
msg: '子组件本身的数据',
}
},
template: `
{{pstr}}
{{pnum}}
{{pboo}}
- {{item}}
{{pobj.name}}
{{pobj.age}}
`
})
var vm = new Vue({
el: '#app',
data: {
pmsg: '父组件的内容',
pstr: 'hello',
parr: ['apple', 'orange', 'banner'],
pobj: {
name: 'lisi',
age: 12,
}
},
})
script>
body>
<body>
<div id="app">
<div :style="{fontSize:fontsize+'px'}">{{msg}}div>
<menu-item @click-fontsize="handle">menu-item>
div>
<script src="./js/vue.js">script>
<script>
Vue.component('menu-item', {
template: `
`
})
var vm = new Vue({
el: '#app',
data: {
msg: '我是父组件内容',
fontsize: 14
},
methods: {
handle: function () {
this.fontsize += 5
}
}
})
script>
body>
<body>
<div id="app">
<div :style="{fontSize:fontsize+'px'}">{{msg}}div>
<menu-item @click-fontsize="handle($event)">menu-item>
div>
<script src="./js/vue.js">script>
<script>
Vue.component('menu-item', {
template: `
`
// $emit('第一个参数是事件名称','第二个参数是值')
})
var vm = new Vue({
el: '#app',
data: {
msg: '我是父组件内容',
fontsize: 14
},
methods: {
handle: function (val) {
this.fontsize += val
}
}
})
script>
body>
{{msg}}
1、单独的事件中心管理组件间的通信
var eventHub = new Vue()
2、监听事件与销毁事件
eventHub.$on('add-todo',addTodo)
eventHub.$off('add-todo')
3、触发事件
eventHub.$emit('add-todo',id)
<body>
<div id="app">
<div>{{msg}}div>
<test-tom>test-tom>
<test-jerry>test-jerry>
<div @click='handle'>销毁div>
div>
<script src="./js/vue.js">script>
<script>
// 提供事件中心
var hub = new Vue();
Vue.component('test-tom', {
data: function () {
return {
num: 0
}
},
template: `
TOM:{{num}}
`,
mounted: function () {
// 监听事件
hub.$on('tom-event', (val) => {
// val 是 兄弟组件传过来的
this.num += val
})
},
methods: {
handle: function () {
// 触发兄弟组件的事件
// 要传给兄弟 组件 2
hub.$emit('jerry-event', 2)
}
}
})
Vue.component('test-jerry', {
data: function () {
return {
num: 0
}
},
template: `
JERRY:{{num}}
`,
mounted: function () {
// 监听事件
hub.$on('jerry-event', (val) => {
// val 是 兄弟组件传过来的
this.num += val
})
},
methods: {
handle: function () {
// 触发兄弟组件的事件
hub.$emit('tom-event', 1)
}
}
})
var vm = new Vue({
el: '#app',
data: {
msg: '我是父组件内容',
},
methods: {
handle: function () {
hub.$off('tom-event')
hub.$off('jerry-event')
}
}
})
script>
body>
父组件向子组件传递 内容
<body>
<div id="app">
<test-item>插槽的内容test-item>
div>
<script src="./js/vue.js">script>
<script>
Vue.component('test-item', {
template: `
报错
222
`
})
var vm = new Vue({
el: '#app',
data: {
}
})
script>
body>
<body>
<div id="app">
<test-item>
<p slot="header">标题信息p>
<p>主体信息1p>
<p>主体信息2p>
<p slot="footer">底部信息p>
test-item>
<test-item>
<template slot="header">
<p>标题信息1p>
<p>标题信息2p>
template>
<p>主体信息1p>
<p>主体信息2p>
<template slot="footer">
<p>底部信息1p>
<p>底部信息2p>
template>
test-item>
div>
<script src="./js/vue.js">script>
<script>
Vue.component('test-item', {
template: `
`
})
var vm = new Vue({
el: '#app',
data: {
}
})
script>
body>
父组件对子组件的内容进行加功处理
<body>
<div id="app">
<test-item :list='list'>
<template slot-scope='slotProps'>
<b v-if='slotProps.info.id==2'>{{slotProps.info.name}}b>
<span v-else>{{slotProps.info.name}}span>
template>
test-item>
div>
<script src="./js/vue.js">script>
<script>
Vue.component('test-item', {
props: ['list'],
template: `
{{item.name}}
`
})
var vm = new Vue({
el: '#app',
data: {
list: [{
id: 1,
name: 'apple'
}, {
id: 2,
name: 'orange'
}, {
id: 3,
name: 'banner'
},]
}
})
script>
body>
组件化开发
1、标题组件(展示文本)
2、列表组件(列表展示、商品数量变更、商品删除)
3、结算组件(计算商品总额)
1、功能实现步骤
<body>
<div id="app">
<div class="container">
<my-cart>my-cart>
div>
div>
<script type="text/javascript" src="./js/vue.js">script>
<script type="text/javascript">
var CartTile = {
template: `
我的商品
`
}
var CartList = {
template: `
`
}
var CartTotal = {
template: `
总价:123
`
}
Vue.component('my-cart', {
template: `
`,
components: {
'cart-title': CartTile,
'cart-list': CartList,
'cart-total': CartTotal,
}
})
var vm = new Vue({
el: '#app',
data: {
}
});
script>
实现的功能 标题 和 总价计算
<script type="text/javascript">
var CartTile = {
// 得到父组件传递来的数据
props: ['username'],
template: `
{{username}}的商品
`
}
var CartList = {
template: `
`
}
var CartTotal = {
props: ['list'],
// 获取父组件传来的 list 列表
template: `
总价:{{returnPrice}}
`,
methods: {
},
computed: {
returnPrice: function () {
var sum = 0
this.list.forEach((value, index) => {
sum += value.price * value.num
});
return sum
}
}
}
Vue.component('my-cart', {
data: function () {
return {
username: '张三',
list: [{
id: 1,
name: 'TCL彩电',
price: 1000,
num: 1,
img: 'img/a.jpg'
}, {
id: 2,
name: '机顶盒',
price: 1000,
num: 1,
img: 'img/b.jpg'
}, {
id: 3,
name: '海尔冰箱',
price: 1000,
num: 1,
img: 'img/c.jpg'
}, {
id: 4,
name: '小米手机',
price: 1000,
num: 1,
img: 'img/d.jpg'
}, {
id: 5,
name: 'PPTV电视',
price: 1000,
num: 2,
img: 'img/e.jpg'
}]
// list 商品列表
}
},
template: `
`,
components: {
'cart-title': CartTile,
'cart-list': CartList,
'cart-total': CartTotal,
}
})
var vm = new Vue({
el: '#app',
data: {
}
});
script>
var CartList = {
props: ['list'],
methods: {
del: function (id) {
// 把 id 传递给父组件
this.$emit('cart-del', id)
}
},
template: `
`
}
Vue.component('my-cart', {
data: function () {
return {
username: '张三',
list: [{
id: 1,
name: 'TCL彩电',
price: 1000,
num: 1,
img: 'img/a.jpg'
}, {
id: 2,
name: '机顶盒',
price: 1000,
num: 1,
img: 'img/b.jpg'
}, {
id: 3,
name: '海尔冰箱',
price: 1000,
num: 1,
img: 'img/c.jpg'
}, {
id: 4,
name: '小米手机',
price: 1000,
num: 1,
img: 'img/d.jpg'
}, {
id: 5,
name: 'PPTV电视',
price: 1000,
num: 2,
img: 'img/e.jpg'
}]
// list 商品列表
}
},
template: `
`,
components: {
'cart-title': CartTile,
'cart-list': CartList,
'cart-total': CartTotal,
},
methods: {
delCart: function (id) {
// 根据 id 删除 list对应的数据
// 1、根据 id 找到对应的索引
var index = this.list.findIndex(item => {
return item.id == id
})
// 2、根据 索引 删除
this.list.splice(index, 1)
}
}
})
注意 当 emit 需要传递多个参数的时候,可以用对象的形式
var CartList = {
props: ['list'],
methods: {
del: function (id) {
// 把 id 传递给父组件
this.$emit('cart-del', id)
},
changeNum: function (id, event) {
// event.target.value 可以获取当前项输入的值
this.$emit('input-num', {
id: id,
num: event.target.value,
})
}
},
template: `
`
Vue.component('my-cart', {
data: function () {
return {
username: '张三',
list: [{
id: 1,
name: 'TCL彩电',
price: 1000,
num: 1,
img: 'img/a.jpg'
}, {
id: 2,
name: '机顶盒',
price: 1000,
num: 1,
img: 'img/b.jpg'
}, {
id: 3,
name: '海尔冰箱',
price: 1000,
num: 1,
img: 'img/c.jpg'
}, {
id: 4,
name: '小米手机',
price: 1000,
num: 1,
img: 'img/d.jpg'
}, {
id: 5,
name: 'PPTV电视',
price: 1000,
num: 2,
img: 'img/e.jpg'
}]
// list 商品列表
}
},
template: `
`,
components: {
'cart-title': CartTile,
'cart-list': CartList,
'cart-total': CartTotal,
},
methods: {
delCart: function (id) {
// 根据 id 删除 list对应的数据
// 1、根据 id 找到对应的索引
var index = this.list.findIndex(item => {
return item.id == id
})
// 2、根据 索引 删除
this.list.splice(index, 1)
},
inputChange: function (numObj) {
var index = this.list.findIndex(item => {
return item.id == numObj.id
})
this.list[index].num = numObj.num
}
}
})
一个事件,包含三个处理程序
完整代码
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Documenttitle>
<style type="text/css">
.container {}
.container .cart {
width: 300px;
/*background-color: lightgreen;*/
margin: auto;
}
.container .title {
background-color: lightblue;
height: 40px;
line-height: 40px;
text-align: center;
/*color: #fff;*/
}
.container .total {
background-color: #FFCE46;
height: 50px;
line-height: 50px;
text-align: right;
}
.container .total button {
margin: 0 10px;
background-color: #DC4C40;
height: 35px;
width: 80px;
border: 0;
}
.container .total span {
color: red;
font-weight: bold;
}
.container .item {
height: 55px;
line-height: 55px;
position: relative;
border-top: 1px solid #ADD8E6;
}
.container .item img {
width: 45px;
height: 45px;
margin: 5px;
}
.container .item .name {
position: absolute;
width: 90px;
top: 0;
left: 55px;
font-size: 16px;
}
.container .item .change {
width: 100px;
position: absolute;
top: 0;
right: 50px;
}
.container .item .change a {
font-size: 20px;
width: 30px;
text-decoration: none;
background-color: lightgray;
vertical-align: middle;
}
.container .item .change .num {
width: 40px;
height: 25px;
}
.container .item .del {
position: absolute;
top: 0;
right: 0px;
width: 40px;
text-align: center;
font-size: 40px;
cursor: pointer;
color: red;
}
.container .item .del:hover {
background-color: orange;
}
style>
head>
<body>
<div id="app">
<div class="container">
<my-cart>my-cart>
div>
div>
<script type="text/javascript" src="./js/vue.js">script>
<script type="text/javascript">
var CartTile = {
// 得到父组件传递来的数据
props: ['username'],
template: `
{{username}}的商品
`
}
var CartList = {
props: ['list'],
methods: {
del: function (id) {
// 把 id 传递给父组件
this.$emit('cart-del', id)
},
changeNum: function (id, event) {
// event.target.value 可以获取当前项输入的值
this.$emit('change-num', {
type: 'change',
id: id,
num: parseInt(event.target.value),
})
},
numAdd: function (id) {
this.$emit('change-num', {
id: id,
type: 'add'
})
},
numSub: function (id) {
this.$emit('change-num', {
id: id,
type: 'sub'
})
},
},
template: `
`
}
var CartTotal = {
props: ['list'],
// 获取父组件传来的 list 列表
template: `
总价:{{returnPrice}}
`,
methods: {
},
computed: {
returnPrice: function () {
var sum = 0
this.list.forEach((value, index) => {
sum += value.price * value.num
});
return sum
}
}
}
Vue.component('my-cart', {
data: function () {
return {
username: '张三',
list: [{
id: 1,
name: 'TCL彩电',
price: 1000,
num: 1,
img: 'img/a.jpg'
}, {
id: 2,
name: '机顶盒',
price: 1000,
num: 1,
img: 'img/b.jpg'
}, {
id: 3,
name: '海尔冰箱',
price: 1000,
num: 1,
img: 'img/c.jpg'
}, {
id: 4,
name: '小米手机',
price: 1000,
num: 1,
img: 'img/d.jpg'
}, {
id: 5,
name: 'PPTV电视',
price: 1000,
num: 2,
img: 'img/e.jpg'
}]
// list 商品列表
}
},
template: `
`,
components: {
'cart-title': CartTile,
'cart-list': CartList,
'cart-total': CartTotal,
},
methods: {
delCart: function (id) {
// 根据 id 删除 list对应的数据
// 1、根据 id 找到对应的索引
var index = this.list.findIndex(item => {
return item.id == id
})
// 2、根据 索引 删除
this.list.splice(index, 1)
},
inputChange: function (numObj) {
// 我们要区别这三种类型
// 输入域变更
if (numObj.type == 'change') {
var index = this.list.findIndex(item => {
return item.id == numObj.id
})
this.list[index].num = numObj.num
}
else if (numObj.type == 'sub') {
var index = this.list.findIndex(item => {
return item.id == numObj.id
})
this.list[index].num -= 1
}
else if (numObj.type == 'add') {
var index = this.list.findIndex(item => {
return item.id == numObj.id
})
this.list[index].num += 1
}
// 加号 变更
// 减号变更
}
}
})
var vm = new Vue({
el: '#app',
data: {
}
});
script>
body>
html>
1、接口调用方式
2、 url地址格式
协议、端口、域名、地址、查询参数、锚点
$.ajax({
ulr:'http://www1',
success:function(res){
console.log('1')
}
})
$.ajax({
ulr:'http://www1',
success:function(res){
console.log('1')
}
})
$.ajax({
ulr:'http://www1',
success:function(res){
console.log('1')
}
})
// 他们三个的输出 顺序不会固定,若请求的慢,则输出的 相对而言比较晚
Promise 是异步编程的一种解决方案,从语法上将,Promise 是一个对象,从它可以获取异步操作的消息
var p = new Promise(function(resolve,reject){
// 成功 调用 resolve()
// 失败 调用 reject()
})
p.then(function(ret){
// 从 resolve 得到的 成功的结果
},function(ret){
// 从 reject 得到的 失败的结果
})
var p = new Promise(function (resolve, reject) {
// 成功 调用 resolve()
// 失败 调用 reject()
// 这里用于实现 异步任务
setTimeout(function () {
var flag = true
if (flag) {
// 正常情况
resolve('Hello')
}
else {
reject('出错了')
}
}, 1000)
})
p.then(function (ret) {
// 从 resolve 得到的 成功的结果
console.log(ret);
}, function (ret) {
// 从 reject 得到的 失败的结果
console.log(ret);
})
// 最后输出的结果是 hello
function queryData(url) {
var p = new Promise(function (resolve, reject) {
// 成功 调用 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)
})
return p
}
queryData('http://127.0.0.1:3000/data')
.then(function (ret) {
// 从 resolve 得到的 成功的结果
console.log(ret);
return queryData('http://127.0.0.1:3000/data1')
}, function (ret) {
// 从 reject 得到的 失败的结果
console.log(ret);
})
.then(function (ret) {
console.log(ret); // data1 的返回结果
})
then 参数中的函数返回值
1、返回 Promise 实例对象
返回的该实例对象会调用 下一个then
2、返回普通值
返回的普通值 会直接传递给 下一个then,通过 then 参数中函数的参数接收该值
function queryData(url) {
var p = new Promise(function (resolve, reject) {
// 成功 调用 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)
})
return p
}
queryData('http://127.0.0.1:3000/data')
.then(function (ret) {
// 从 resolve 得到的 成功的结果
console.log(ret);
return queryData('http://127.0.0.1:3000/data1')
}, function (ret) {
// 从 reject 得到的 失败的结果
console.log(ret);
})
.then(function (ret) {
console.log(ret); // data1 的返回结果
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve(111111)
}, 1000)
})
})
.then(function (data) {
console.log(data);// 111
return 'Hello'
// 返回普通值,默认的 promise 实例对象 继续调用
})
.then(function (data) {
console.log(data); // Hello
})
1、实例方法 都在 Promise的原型中
catch 是可以扑捉到 resolve reject 的异常; reject 只能扑捉到 reject的异常
function queryData(url) {
var p = new Promise(function (resolve, reject) {
// 成功 调用 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)
})
return p
}
queryData('http://127.0.0.1:3000/data11')
.then(function (ret) {
// 从 resolve 得到的 成功的结果
console.log(ret);
})
.catch(function (ret) {
// 获取异常信息
// catch 是可以扑捉到 resolve reject 的异常
// reject 只能扑捉到 reject的异常
console.log(ret);
})
.finally(function () {
// 不论执行失败还是成功,都会执行
console.log('执行完毕');
})
直接通过函数名称调用的,在Promise 里面的
function queryData(url) {
var p = new Promise(function (resolve, reject) {
// 成功 调用 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)
})
return p
}
var p1 = queryData('http://localhost:3000/a1')
var p2 = queryData('http://localhost:3000/a2')
var p3 = queryData('http://localhost:3000/a3')
Promise.all([p1, p2, p3]).then(function (results) {
console.log(results);
// ["Hello TOM!", "Hello JERRY!", "Hello SPIKE!"]
})
Promise.race([p1, p2, p3]).then(function (results) {
console.log(results);
// Hello Tom
// 请求都发出去了,只会得到 最先返回的结果
})
语法结构
fetch(url).then(fn2).then(fn3)…….catch(fn)
<script>
fetch('http://localhost:3000/fdata').then(function (data) {
// 这里的data 不能直接拿到数据
// text 方法 是 fetchAPI 的一部分
// text 用户获取后台返回的数据
return data.text()
// data.text() 返回的是 Promise实例对象
}).then(function (data) {
console.log(data);
})
script>
1、常用配置选项
delete 和 get 请求方式,大体一样,只是 method 不同
fetch('http://localhost:3000/books?id=123', {
method: 'get',
}).then(function (data) {
// 这里的data 不能直接拿到数据
return data.text()
// data.text() 返回的是 Promise实例对象
}).then(function (data) {
console.log(data);
})
// 第二种方式
fetch('http://localhost:3000/books/123', {
method: 'get',
}).then(function (data) {
// 这里的data 不能直接拿到数据
return data.text()
// data.text() 返回的是 Promise实例对象
}).then(function (data) {
console.log(data);
})
post put 需要设置额外的 body 和 headers
fetch('http://localhost:3000/books', {
method: 'post',
body: 'uname=lisi&pwd=123',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
// 也可以设置成 json 格式,前提是 把body的内容转化为 json的数据
}
}).then(function (data) {
// 这里的data 不能直接拿到数据
return data.text()
// data.text() 返回的是 Promise实例对象
}).then(function (data) {
console.log(data);
})
fetch('http://localhost:3000/json', {
}).then(function (data) {
// 这里的data 不能直接拿到数据
return data.json()
// 不写 json 写 text 返回的是字符串
// data.text() 返回的是 Promise实例对象
}).then(function (data) {
console.log(data);
//{uname: "lisi", age: 13, gender: "male"}
})
axios(官网:https://github.com/axios/axios/)是一个基于 Promise 用于浏览器 和 node.js 的 HTTP客户端
axios.get('http://localhost:3000/adata').then(function (ret) {
// ret.data 才是后台接口返回的数据,data 是固定的属性,用于获取接口返回的实际数据
console.log(ret);
console.log(ret.data);
})
get
axios.get('http://localhost:3000/axios', {
params: {
id: 789
}
}).then(function (ret) {
// ret.data 才是后台接口返回的数据,data 是固定的属性,用于获取接口返回的实际数据
console.log(ret);
console.log(ret.data);
})
axios.get('http://localhost:3000/axios/345').then(function (ret) {
// ret.data 才是后台接口返回的数据,data 是固定的属性,用于获取接口返回的实际数据
console.log(ret);
console.log(ret.data);
})
axios.get('http://localhost:3000/axios?id=2', {
params: {
id: 789
}
}).then(function (ret) {
// ret.data 才是后台接口返回的数据,data 是固定的属性,用于获取接口返回的实际数据
console.log(ret);
console.log(ret.data);
})
// 默认传递的是 json 格式的数据
axios.post('/adara',{
uname:'tom',
pwd:123
}).then(ret=>{
console.log(ret.data)
})
axios.post('http://localhost:3000/axios', {
uname: 'lisis',
pwd: '123'
}).then(function (ret) {
// ret.data 才是后台接口返回的数据,data 是固定的属性,用于获取接口返回的实际数据
console.log(ret.data);
})
传递 表单形式的数据
const params = new URLSearchParams();
params.append('uname', 'zhang')
params.append('pwd', '111')
axios.post('http://localhost:3000/axios', params).then(ret => {
console.log(ret.data)
})
响应结果
全局配置
axios.defaults.headers['mytoken'] = 'hello' // 配置请求头
axios.defaults.timeout = 3000 // 设置超时
axios.defaults.baseURL = 'http://localhost:3000/' // 设置基准URL地址,再写请求的时候,只需要写请求路径就行了
axios.post('axios', {
uname: 'lisis',
pwd: '123'
}).then(function (ret) {
// ret.data 才是后台接口返回的数据,data 是固定的属性,用于获取接口返回的实际数据
console.log(ret.data);
})
1、请求拦截器
再发请求之前设置一些信息,常用于判断是否添加请求头
axios.interceptors.request.use(function (config) {
config.headers.mytoken = 'nihao'
// 必须要 return出去
return config
}, function (err) {
console.log(err);
})
2、响应拦截器
axios.interceptors.response.use(function (res) {
// res 就是响应回来的东西 ,res.data 才是响应回来的数据
var data = res.data
// 这样设置表示,接口响应回来的res 都是 直接的数据,不需要再通过 .data 获取数据了
// 必须要 return出去
return data
}, function (err) {
console.log(err);
})
<script src="./js/axios.js">script>
<script>
async function queryData() {
var ret = await axios.get('http://localhost:3000/adata')
return ret.data
}
queryData().then(function (data) {
console.log(data);
})
script>
async function queryData() {
var info = await axios.get('http://localhost:3000/async1')
var ret = await axios.get('http://localhost:3000/async2?info=' + info.data)
return ret.data
}
queryData().then(function (res) {
console.log(res);
})
// 给 axios 设置响应 拦截器,把返回的数据,直接修改成真正的数据
axios.defaults.baseURL = 'http://localhost:3000/';
axios.interceptors.response.use(function (res) {
return res.data;
}, function (error) {
console.log(error)
});
// vue data 里面的方法
queryData: async function () {
// 调用后台接口获取图书列表数据
// var ret = await axios.get('books');
// this.books = ret.data;
this.books = await axios.get('books');
}
建议vue种data的methods对象种的,方法都采用 async、await的形式,这样写更加简洁
路由的本质就是对应关系
路由分为 后端路由 和 前端路由
1、后端路由
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1ZCl7DT5-1620387784181)(vue基础.assets/image-20201025181259535.png)]
2、SPA
3、前端路由
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q6JnSNwb-1620387784182)(vue基础.assets/image-20201025183610619.png)]
// 监听 window 的 onhashchange 事件,根据获取到的最新的 hash值,切换要显示的组件的名称
window.onhashchange=function(){
// 通过 location.hash 获取到最新的 hash值
}
component标签就是一个组件的占位符,:is 就是指定那个组件渲染到此处,注意is里面的值如果是写死的,必须是一个字符串才行
<body>
<div id="app">
<a href="#/zhuye">主页a>
<a href="#/keji">科技a>
<a href="#/caijing">财经a>
<a href="#/yule">娱乐a>
<component :is="comName">component>
div>
<script>
// 主页组件
const zhuye = {
template: '主页信息
'
}
// 科技组件
const keji = {
template: '科技信息
'
}
// 财经组件
const caijing = {
template: '财经信息
'
}
// 娱乐组件
const yule = {
template: '娱乐信息
'
}
const vm = new Vue({
el: '#app',
data: {
comName: 'zhuye'
},
// 注册私有组件
components: {
'zhuye': zhuye,
'keji': keji,
'caijing': caijing,
'yule': yule
}
})
// 监听 window 的 onhashchange 事件,根据获取到的最新的 hash 值,切换要显示的组件的名称
window.onhashchange = function () {
// 通过 location.hash 获取到最新的 hash 值
console.log(location.hash);
switch (location.hash.slice(1)) {
case '/zhuye':
vm.comName = 'zhuye'
break
case '/keji':
vm.comName = 'keji'
break
case '/caijing':
vm.comName = 'caijing'
break
case '/yule':
vm.comName = 'yule'
break
}
}
script>
body>
官网 https://router.vuejs.org/zh/ 是 vue.js 的路由管理器
功能
# 添加路由链接
# router-link 是 vue 中提供的标签,默认会被渲染为 标签
# to 属性 默认会被渲染为 href 属性
# to 属性的值默认会被渲染为 # 开头的 hash 地址
<router-link to='/user'> user </router-link>
# 添加路由填充位,也叫路由占位符
# 将来通过路由规则匹配到的组件,将会被渲染到 router-view 所在的位置
<router-view></router-view>
源代码
<body>
<div id="app">
<router-link to='/user'>User router-link>
<router-link to="/Register">Register router-link>
<router-view>router-view>
div>
<script src="./js/vue.js">script>
<script src="./js/vue-router.js">script>
<script>
// 3、定义路由组件
var user = {
template: ' user 组件
'
}
var Register = {
template: 'Register 组件
'
}
var router = new VueRouter({
// routes 是路由规则数组
routes: [
// 每个路由规则都是一个配置对象,其中至少包括 path 和component 两个属性
// path 表示当前路由规则匹配的 hash地址
// component 表示当前路由规则对应要展示的组件,它只接受组件对象,不接受字符串
{ path: '/user', component: user },
{ path: '/Register', component: Register },
]
})
var vm = new Vue({
el: '#app',
data: {},
// 挂载路由实例对象
router: router,
})
// 4、创建路由实例对象
script>
body>
用户再访问 地址 A 的时候,强制用户跳转到地址 C,从而展示特点的组件页面
通过路由规则的 redirect 属性,指定一个新的路由地址,可以很方便的设置路由的定向
var router = new VueRouter({
// routes 是路由规则数组
routes: [
// 每个路由规则都是一个配置对象,其中至少包括 path 和component 两个属性
// path 表示当前路由规则匹配的 hash地址
// component 表示当前路由规则对应要展示的组件,它只接受组件对象,不接受字符串
// '/' 表示需要被重定向的源地址,redirect 表示将要被重定向到的新地址
{ path: '/', redirect: '/user' },
{ path: '/user', component: user },
{ path: '/Register', component: Register },
]
})
点击 父级路由链接显示模板内容,模板内容中又有子级路由链接,点击子级路由链接显示子级模板内容
<body>
<div id="app">
<router-link to='/user'>User router-link>
<router-link to="/Register">Register router-link>
<router-view>router-view>
div>
<script src="./js/vue.js">script>
<script src="./js/vue-router.js">script>
<script>
// 3、定义路由组件
var user = {
template: ' user 组件
'
}
var Register = {
template: `
Register 组件
Register/tab1
Register/tab2
`
}
var tab1 = {
template: 'tab1 子组件
'
}
var tab2 = {
template: 'tab2 子组件
'
}
var router = new VueRouter({
// routes 是路由规则数组
routes: [
// 每个路由规则都是一个配置对象,其中至少包括 path 和component 两个属性
// path 表示当前路由规则匹配的 hash地址
// component 表示当前路由规则对应要展示的组件,它只接受组件对象,不接受字符串
// '/' 表示需要被重定向的源地址,redirect 表示将要被重定向到的新地址
{ path: '/', redirect: '/user' },
{ path: '/user', component: user },
{
path: '/Register',
component: Register,
// children 表示 子路由规则
children: [
{ path: '/Register/tab1', component: tab1 },
{ path: '/Register/tab2', component: tab2 },
]
},
]
})
var vm = new Vue({
el: '#app',
data: {},
// 挂载路由实例对象
router: router,
})
// 4、创建路由实例对象
script>
body>
路由规则,有一部分是一样的,另一部分是动态的、变化的
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FmCe7FOa-1620387784183)(vue基础.assets/image-20201026201701456.png)]
<body>
<div id="app">
<router-link to='/user/1'>User router-link>
<router-link to='/user/2'>User router-link>
<router-link to='/user/3'>User router-link>
<router-link to="/Register">Register router-link>
<router-view>router-view>
div>
<script src="./js/vue.js">script>
<script src="./js/vue-router.js">script>
<script>
// 3、定义路由组件
var user = {
template: ' user 组件--用户id为{{$route.params.id}}
'
}
var Register = {
template: `
Register 组件
`
}
var router = new VueRouter({
// routes 是路由规则数组
routes: [
// 每个路由规则都是一个配置对象,其中至少包括 path 和component 两个属性
// path 表示当前路由规则匹配的 hash地址
// component 表示当前路由规则对应要展示的组件,它只接受组件对象,不接受字符串
// '/' 表示需要被重定向的源地址,redirect 表示将要被重定向到的新地址
{ path: '/', redirect: '/user' },
// :id 表示动态的参数
{ path: '/user/:id', component: user },
{ path: '/Register', component: Register, },
]
})
var vm = new Vue({
el: '#app',
data: {},
// 挂载路由实例对象
router: router,
})
// 4、创建路由实例对象
script>
body>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EtR79QkF-1620387784183)(vue基础.assets/image-20201026203125350.png)]
<body>
<div id="app">
<router-link to='/user/1'>User router-link>
<router-link to='/user/2'>User router-link>
<router-link to='/user/3'>User router-link>
<router-link to="/Register">Register router-link>
<router-view>router-view>
div>
<script src="./js/vue.js">script>
<script src="./js/vue-router.js">script>
<script>
// 3、定义路由组件
var user = {
props: ['id'],// 使用props 接收路由参数
template: ' user 组件--用户id为{{id}}
'
}
var Register = {
template: `
Register 组件
`
}
var router = new VueRouter({
// routes 是路由规则数组
routes: [
// 每个路由规则都是一个配置对象,其中至少包括 path 和component 两个属性
// path 表示当前路由规则匹配的 hash地址
// component 表示当前路由规则对应要展示的组件,它只接受组件对象,不接受字符串
// '/' 表示需要被重定向的源地址,redirect 表示将要被重定向到的新地址
{ path: '/', redirect: '/user' },
// :id 表示动态的参数
// props true 表示 route.params 将会被设置为组件属性
{ path: '/user/:id', component: user, props: true },
{ path: '/Register', component: Register, },
]
})
var vm = new Vue({
el: '#app',
data: {},
// 挂载路由实例对象
router: router,
})
// 4、创建路由实例对象
script>
body>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Kt4mu4bs-1620387784184)(vue基础.assets/image-20201026204401796.png)]
<body>
<div id="app">
<router-link to='/user/1'>User router-link>
<router-link to='/user/2'>User router-link>
<router-link to='/user/3'>User router-link>
<router-link to="/Register">Register router-link>
<router-view>router-view>
div>
<script src="./js/vue.js">script>
<script src="./js/vue-router.js">script>
<script>
// 3、定义路由组件
var user = {
props: ['id', 'uname', 'age'],// 使用props 接收路由参数
// 其实这里 是 获取不到 id 的,因为你没有传递过来id
template: ' user 组件--用户id为{{id}}--{{uname}}---{{age}}
'
}
var Register = {
template: `
Register 组件
`
}
var router = new VueRouter({
// routes 是路由规则数组
routes: [
// 每个路由规则都是一个配置对象,其中至少包括 path 和component 两个属性
// path 表示当前路由规则匹配的 hash地址
// component 表示当前路由规则对应要展示的组件,它只接受组件对象,不接受字符串
// '/' 表示需要被重定向的源地址,redirect 表示将要被重定向到的新地址
{ path: '/', redirect: '/user' },
// :id 表示动态的参数
// props true 表示 route.params 将会被设置为组件属性
{ path: '/user/:id', component: user, props: { uname: 'zs', age: 12 } },
{ path: '/Register', component: Register, },
]
})
var vm = new Vue({
el: '#app',
data: {},
// 挂载路由实例对象
router: router,
})
// 4、创建路由实例对象
script>
body>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NDSRCyXg-1620387784185)(vue基础.assets/image-20201026205729207.png)]
<body>
<div id="app">
<router-link to='/user/1'>User router-link>
<router-link to='/user/2'>User router-link>
<router-link to='/user/3'>User router-link>
<router-link to="/Register">Register router-link>
<router-view>router-view>
div>
<script src="./js/vue.js">script>
<script src="./js/vue-router.js">script>
<script>
// 3、定义路由组件
var user = {
props: ['id', 'uname', 'age'],// 使用props 接收路由参数
// 其实这里 是 获取不到 id 的,因为你没有传递过来id
template: ' user 组件--用户id为{{id}}--{{uname}}---{{age}}
'
}
var Register = {
template: `
Register 组件
`
}
var router = new VueRouter({
// routes 是路由规则数组
routes: [
// 每个路由规则都是一个配置对象,其中至少包括 path 和component 两个属性
// path 表示当前路由规则匹配的 hash地址
// component 表示当前路由规则对应要展示的组件,它只接受组件对象,不接受字符串
// '/' 表示需要被重定向的源地址,redirect 表示将要被重定向到的新地址
{ path: '/', redirect: '/user' },
// :id 表示动态的参数
// props true 表示 route.params 将会被设置为组件属性
{
path: '/user/:id',
component: user,
// route 是一个对象
// 箭头函数 左边是 单表达式,要返回一个对象,需要加括号
props: route => ({
uname: 'zs',
age: 20,
id: route.params.id
})
},
{ path: '/Register', component: Register, },
]
})
var vm = new Vue({
el: '#app',
data: {},
// 挂载路由实例对象
router: router,
})
// 4、创建路由实例对象
script>
body>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0hWcHY1V-1620387784186)(vue基础.assets/image-20201026210546160.png)]
<body>
<div id="app">
<router-link to='/user/1'>User router-link>
<router-link to='/user/2'>User router-link>
<router-link :to="{name:'user',params:{id:3}}">User router-link>
<router-link to="/Register">Register router-link>
<router-view>router-view>
div>
<script src="./js/vue.js">script>
<script src="./js/vue-router.js">script>
<script>
// 3、定义路由组件
var user = {
template: ' user 组件--用户id为{{$route.params.id}}
'
}
var Register = {
template: `
Register 组件
`
}
var router = new VueRouter({
// routes 是路由规则数组
routes: [
{ path: '/', redirect: '/user' },
// :id 表示动态的参数
// name 起个别名,命名路由
{ path: '/user/:id', component: user, name: 'user' },
{ path: '/Register', component: Register, },
]
})
var vm = new Vue({
el: '#app',
data: {},
// 挂载路由实例对象
router: router,
})
// 4、创建路由实例对象
script>
body>
声明式导航:通过点击链接实现导航的方式,比如 a标签,router-link 标签
编程式导航:通过调用 JavaScript 形式的 api 实现导航的方式,如 location.href
常用的编程式导航基本用法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aAFAtXoF-1620387784187)(vue基础.assets/image-20201026211712173.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sxugfNqZ-1620387784188)(vue基础.assets/image-20201026212707374.png)]
<body>
<div id="app">
<router-link to='/user/1'>User router-link>
<router-link to='/user/2'>User router-link>
<router-link :to="{name:'user',params:{id:3}}">User router-link>
<router-link to="/Register">Register router-link>
<router-view>router-view>
div>
<script src="./js/vue.js">script>
<script src="./js/vue-router.js">script>
<script>
// 3、定义路由组件
var user = {
template: `
user 组件--用户id为{{$route.params.id}}
`,
methods: {
handle: function () {
this.$router.push('/Register')
}
}
}
var Register = {
template: `
Register 组件
`
}
var router = new VueRouter({
// routes 是路由规则数组
routes: [
{ path: '/', redirect: '/user' },
// :id 表示动态的参数
// name 起个别名,命名路由
{ path: '/user/:id', component: user, name: 'user' },
{ path: '/Register', component: Register, },
]
})
var vm = new Vue({
el: '#app',
data: {},
// 挂载路由实例对象
router: router,
})
// 4、创建路由实例对象
script>
body>
<body>
<div id="app">
<router-view>router-view>
div>
<script>
// 定义 根组件 APP
const App = {
template: `
传智后台管理系统
- 用户管理
- 权限管理
- 商品管理
- 订单管理
- 系统设置
添加用户表单
`
}
// 创建路由对象
var router = new VueRouter({
routes: [
{ path: '/', component: App },
]
})
var vm = new Vue({
el: '#app',
// 将路由挂载到 vm 实例身上
router,
})
script>
body>
<head>
<meta charset="UTF-8" />
<title>基于vue-router的案例title>
<style type="text/css">
html,
body,
#app {
margin: 0;
padding: 0px;
height: 100%;
}
.header {
height: 50px;
background-color: #545c64;
line-height: 50px;
text-align: center;
font-size: 24px;
color: #fff;
}
.footer {
height: 40px;
line-height: 40px;
background-color: #888;
position: absolute;
bottom: 0;
width: 100%;
text-align: center;
color: #fff;
}
.main {
display: flex;
position: absolute;
top: 50px;
bottom: 40px;
width: 100%;
}
.content {
flex: 1;
text-align: center;
height: 100%;
}
.left {
flex: 0 0 20%;
background-color: #545c64;
}
.left a {
color: white;
text-decoration: none;
}
.right {
margin: 5px;
}
.btns {
width: 100%;
height: 35px;
line-height: 35px;
background-color: #f5f5f5;
text-align: left;
padding-left: 10px;
box-sizing: border-box;
}
button {
height: 30px;
background-color: #ecf5ff;
border: 1px solid lightskyblue;
font-size: 12px;
padding: 0 20px;
}
.main-content {
margin-top: 10px;
}
ul {
margin: 0;
padding: 0;
list-style: none;
}
ul li {
height: 45px;
line-height: 45px;
background-color: #a0a0a0;
color: #fff;
cursor: pointer;
border-bottom: 1px solid #fff;
}
table {
width: 100%;
border-collapse: collapse;
}
td,
th {
border: 1px solid #eee;
line-height: 35px;
font-size: 12px;
}
th {
background-color: #ddd;
}
style>
<script src="./js/vue.js">script>
<script src="./js/vue-router.js">script>
head>
<body>
<div id="app">
<router-view>router-view>
div>
<script>
// 定义 根组件 APP
const App = {
template: `
传智后台管理系统
用户管理
权限管理
商品管理
订单管理
系统设置
`
}
var users = {
data: function () {
return {
userlist: [
{ id: 1, name: '张三', age: 10 },
{ id: 2, name: '李四', age: 20 },
{ id: 3, name: '呆呆狗', age: 30 },
{ id: 4, name: '张柳', age: 40 },
]
}
},
methods: {
handle: function (id) {
this.$router.push('/userinfo/' + id)
}
},
template: `
用户管理区域
编号
姓名
年龄
操作
{{item.id}} {{item.name}} {{item.age}} 详情
`
}
var rigths = { template: `权限管理区域
` }
var goods = { template: `商品管理区域
` }
var orders = { template: `订单管理区域
` }
var settings = { template: `系统设置区域
` }
var userinfo = {
props: ['id'],
template: `
用户详情页{{id}}
`,
methods: {
houtui: function () {
this.$router.go(-1)
}
}
}
// 创建路由对象
var router = new VueRouter({
routes: [
{
path: '/',
component: App,
children: [
{ path: '/users', component: users },
{ path: '/userinfo/:id', component: userinfo, props: true },
{ path: '/rigths', component: rigths },
{ path: '/goods', component: goods },
{ path: '/orders', component: orders },
{ path: '/settings', component: settings },
],
redirect: '/users',
},
]
})
var vm = new Vue({
el: '#app',
// 将路由挂载到 vm 实例身上
router,
})
script>
body>