Vue简介
条件渲染
v-if
- 简单条件渲染(其中v-if与v-else连用时中间不能出现其他元素)
<h3 v-if='isvip'>用户类型:VIP</h3>
<h3 v-else>用户类型:普通用户</h3>
- 复杂一点渲染()
<h3 v-if="age<=12">用户限制:允许登入2小时</h3>
<h3 v-else-if="age<=18">用户限制:允许登入4小时</h3>
<h3 v-else>用户限制:允许登入6小时</h3>
v-show
v-show的本质就是操纵元素的显示与隐藏
v-if与v-show的区别
- v-show适用于反复操作切换元素,性能损耗较小;
- v-if进行操作时性能损耗较大,可以视情况而定采取哪种方式进行条件渲染
关于this指向的问题
-
在事件函数中可以传入一个参数,习惯上我们设置为e,此时我们可以检验一下将其打印在控制台,此时的e就是被触发的函数事件对象的属性集合,当事件触发了之后我们将其展开进行相关属性的查看;
-
在元素里面设置data-id可以设置元素的id值,此时的id值是需要利用e.target.dataset.id进行获取
-
this实质上就是实例化的app
v-for
语法:
v-for="i,index in arr"
其中i为数组里的元素,index为索引值,两者之间以逗号隔开
计算属性
Vue对象里面还有一个computed属性,用于专门计算。可以通过{{}}的形式进行渲染。
生命周期
beforeCreate:初始化之前=>此时数据data还有方法mothods等还没有绑定到app对象上,获取不到相应的数据
created:初始化之后=>此时数据data还有方法mothods等已经绑定到app对象上,可以获取到相应的数据
beforeMount:挂载/渲染之前=>根据数据生成的DOM对象是获取不到的
mounted :挂载/渲染之后=>可以获取数据生成的DOM对象
beforeUpdate:更新之前=>数据更改,但内容未更改
updated:更新之后=>内容已更新完毕
beforeDestroy:
destroy:
组件化
- 为什么要使用组件化,主要原因就是有一些功能是反复利用,多次调用,为了实现代码的精简,便于维护,故有了组件化的思想;
- 所谓的组件就可以相当于一个迷你版的vue实例化的对象,不同的是组件里面的data属性是通过函数的形式进行表示的,同时组件里面也可以定义自身的方法methods;
简单示例
- 核心代码如下:
<body>
<!-- 在vue里面使用组件化首先必须要有一个挂载点,因为在vue里面就必须遵循vue的渲染方法 -->
<div id="app">
<div>
<button-counter></button-counter>
<button-counter></button-counter>
</div>
</div>
<!-- 实现html结构和js代码之间的分离,使用template标签并使用一个id名进行绑定,然后在组件里面使用id名就可以替代原有的html标签 -->
<template id="temp">
<button v-on:click="count++">You clicked me {{ count }} times.</button>
</template>
<script>
//定义一个组件
Vue.component("button-counter", {
// data函数用于组件直接访问组件内部的数据
data: function () {
return {
count: 0,
};
},
// 其中的template就是渲染模板,可自定义将其进行包装,注意用引号将其包裹
template: '#temp',
});
let app = new Vue({
el: "#app",
data: {},
methods: {},
});
</script>
</body>
- 运行结果如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QoHDcwfq-1607653093749)(C:\Users\hp\Desktop\vue\new_round\06组件化\截图\捕获.PNG)]
上述运行结果没有关联,可以进行单独使用,其结果互不干扰(得益于data函数的功劳)
组件之间的传值
背景
- 首先新的组件应该拥有属于自己的数据管理库,类似于实例化的Vue对象中的data;
- 其次如果组件想直接访问实例化中的data数据是行不通的(必须进行传值操作);
- 最后我们也提倡大多数情况下我们把数据定义在组件内部里面,以免实例化中的数据过于臃肿;
组件里面的data函数
- 为什么组件里面的data是一个函数?
- 组件里面的data是一个函数,他保证了每次调用组件里的数据时不共享data里的数据
父传子
<body>
<div id="app">
<div>
<!-- 为了告知父元素将要传入一个什么参数的话就必须为模板绑定一个属性 -->
<!-- 模板是进行html设计的,在这里只需进行一个简单的数据绑定即可 -->
<school :something="schoolName" :msgs='msg'>
</school>
</div>
</div>
<!-- 模板是进行html设计的,一切有关html的设计在这里进行设计 -->
<!-- 实现html结构和js代码之间的分离,使用template标签并使用一个id名进行绑定,然后在组件里面使用id名就可以替代原有的html标签 -->
<!-- 若果使用到了或涉及两个或两个以上的数据传值时,其内部必须要有一个根标签进行包裹,这里就是div标签-->
<template id="temp">
<div>
<li v-for="i,index in something">{{index+1}}{{i}}</li>
<h3>{{msgs}}</h3>
</div>
</template>
<script>
Vue.component("school", {
props: ['something', 'msgs'],
template: '#temp'
});
let app = new Vue({
el: "#app",
data: {
schoolName: ['清华', '北大', '北大青鸟', '复旦'],
msg: '今天是个好日子'
},
methods: {},
});
</script>
</body>
- 运行结果如下
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9mY1tx3s-1607653093751)(C:\Users\hp\Desktop\vue\new_round\06组件化\截图\获.PNG)]
- 如果props中的变量有驼峰式命名的变量,那么在绑定时必须讲其进行转换
- 例如myName必须将其改为my-name
- 更多关于props传入的数据类型可以继续参考b站视频P58
子传父
-
父传子的使用情景:
- 最简单的例子就是,当我们点击了一个子组件,但是我们希望将我们点击的子组件的相关信息传输给父组件,方便父组件将请求发送给服务器
-
传值的分析
- v-on指令不仅可以可以监听DOM事件,也可以用于组件间的自定义事件
-
传值的流程
- 在子组件中通过$emit()来触发事件
- 在父组件中通过v-bind来进行监听子组件事件
-
详细代码如下
-
<body> <div id="app"> <div> <!-- 此时的signal就相当于我们经常使用的click等事件,这里就是子组件向父组件发射的事件对象 --> <!-- 其中的getmsg应该由父组件进行定义,注意这里的参数传递十分经典,值得琢磨 --> <products @signal="getmsg"> </products> </div> </div> <template id="temp"> <div> <!-- 记得这里传值的时候i是必须是v-for里面的i,不然会报错 --> <button v-for="i,index in categories" @click="clickevent(i)">名称:{{i.name}}--价格:{{i.prices}}--索引值:{{i.id}} </button> </div> </template> <script> Vue.component("products", { data() { return { categories: [{ name: "衬衫", prices: '$30', id: 1 }, { name: "T桖", prices: '$40', id: 2 }, { name: "鞋子", prices: '$120', id: 3 }, { name: "棉袄", prices: '$300', id: 4 }] } }, template: '#temp', methods: { // 此时的传值就可以就行自定义一个参数用来接收点击事件的对象,这里使用e clickevent: function (e) { // console.log(e) //这里是一个自定义事件,第一个参数是发射出去的事件对象用于,第二个参数是传入的参数 this.$emit('signal', e) } } }); let app = new Vue({ el: "#app", methods: { getmsg: function (e) { console.log(e) } }, }); </script> </body>
- 运行结果如下:任意点击一个按钮就会输出相应的点击对象属性
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PFvTOelu-1607653093753)(C:\Users\hp\Desktop\vue\new_round\06组件化\截图\子传父.PNG)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j4atGlJS-1607653093755)(C:\Users\hp\Desktop\vue\new_round\06组件化\截图\字串符.PNG)]
-
父访问子组件的实例
<body>
<div id="app">
<div>
<button-counter ref="qqq"></button-counter>
<button-counter></button-counter>
<button-counter></button-counter>
<!-- 此时点击即可进行访问到子组件的对象,使用了子组件多少次就会有几个对象 ,但是绝大多数是不会这样使用的-->
<button @click="getmsg">点我进行访问子组件</button>
</div>
</div>
<template id="temp">
<h1>You clicked me</h1>
</template>
<script>
Vue.component("button-counter", {
data: function () {
return {
count: 12,
};
},
template: '#temp',
});
let app = new Vue({
el: "#app",
methods: {
getmsg: function () {
//这里可以直接访问到子组件中的属性/数据,这种用法不常用
console.log(this.$children[2].count)
//这里可以直接访问到子组件中的属性/数据=>记得这里是refs,而上面是ref
console.log(this.$refs.qqq.count)
}
},
});
</script>
</body>
插槽slot
插槽的使用背景
- 插槽的存在就是为了扩展,它应用于组件开发之中,当有些组件创建时为了不写死,灵活运用,就出现了插槽这个东西,预留了一定的空间,极大的方便了开发效率,注意插槽可以有定义有多个。
插槽的简单使用
<body>
<div id="app">
<div>
<button-counter></button-counter>
<button-counter><button>我可以挤掉预定义插槽内容</button></button-counter>
<button-counter>
<h4>插槽还可以定义好多个标签呢</h4>
<button>你看我和上面的h4标签还可以搭配呢,还可以定义好多标签</button>
</button-counter>
</div>
</div>
<template id="temp">
<div>
<h3>You clicked me</h3>
<button>click me</button>
<!-- 如果单独定义一个插槽的话且里面不保存内容,界面将没有任何有关插槽的身影,如果插槽里定义了标签的话,那么会将标签渲染在页面中 -->
<slot><button>我是插槽预定义内容</button></slot>
</div>
</template>
<script>
Vue.component("button-counter", {
data: function () {
return {
};
},
template: '#temp',
});
let app = new Vue({
el: "#app",
methods: {
},
});
</script>
</body>
- 运行结果如下
具名插槽的使用
- 部分核心代码如下
<div id="app">
<div>
<button-counter></button-counter>
<button-counter><button slot="center">我改变中间插槽的标签类型和内容了</button></button-counter>
<button-counter><h3 slot="right">我要改变右边插槽了</h3></button-counter>
</div>
</div>
<template id="temp">
<div>
<h3>我是插槽呀!</h3>
<slot name='left'><span>左边</span></slot>
<slot name="center"><span>中间</span></slot>
<slot name="right"><span>右边</span></slot>
</div>
</template>
- 运行结果如下
编译作用域
<body>
<!-- 这里是Vue实例的作用域,此时其数据指向的是Vue实例里的数据 -->
<div id="app">
<div>
<button-counter></button-counter>
<button-counter v-show="isshow"></button-counter>
<button-counter></button-counter>
</div>
</div>
<!-- 这里是组件的模板,这里的话组件应该寻找的是组件里面定义的数据 -->
<template id="temp">
<div>
<h3>组件玩意</h3>
<button v-show="isshow">click me</button>
</div>
</template>
<script>
Vue.component("button-counter", {
data: function () {
return {
isshow:true
};
},
template: '#temp',
});
let app = new Vue({
el: "#app",
data: {
isshow: false
},
methods: {},
});
</script>
</body>
作用域插槽
实现在父组件中能够改变插槽的展现形式,即实现父组件访问并使用子组件的数据
<body>
<div id="app">
<div>
<button-counter></button-counter>
<button-counter>
<!-- 使用v-slot:default="xxx"指令进行接收,其中的xxx可以自定义名字 -->
<template v-slot:default="newLanguage">
<span v-for="i,index in newLanguage.languages">--{{i}}--</span>
</template>
</button-counter>
</div>
</div>
<template id="temp">
<div>
<!-- 在子组件中进行绑定,将插槽的数据从子组件传入父组件 -->
<slot :languages="language">
<ul>
<li v-for="i in language">{{i}}</li>
</ul>
</slot>
</div>
</template>
<script>
Vue.component("button-counter", {
data: function () {
return {
language: ['python', 'c++', 'js', 'c#']
};
},
template: '#temp',
});
let app = new Vue({
el: "#app",
})
</script>
</body>
ES6的模块化
导入
- 首先要有一个主入口文件,这里可以对比后端中的app.js文件,只不过在前端中可以换成是index.html文件,这个文件就是前端的主入口文件,我们在这个html文件中可以引入需要的js文件;
- 需要引入文件的前提就是被引入的文件进行了暴露即进行了导出,其中导出的操作就是将导出的变量、函数、数组、类等存入一个对象里面;
- 导入方式:import {变量名/数组名/函数名……} from ‘被引文件的路径’
导出
- 导出方式:export {变量名/数组名/函数名……}
主入口文件
-
主入口文件和普通的文件并没有很大区别,无非就是引入了很多一些js代码,但是必须注意引入js代码时必须要注意以下问题
-
在script标签中引入时必须应该写上type属性,其值为module,其次就是src属性
-
<script src="./c.js" type="module"></script>
-
-
代码演示
- inde.html文件
<body>
<script src="./a.js" type="module"></script>
<script src="./b.js" type="module"></script>
<script src="./c.js" type="module"></script>
</body>
- a.js文件
var age = 23;
export { age };
//这就是导出一个函数,这样的话在进行导出时就可以自定义命名这个函数
export default function (num1, num2) {
return num1 / num2;
}
- b.js文件
import { age } from "./a.js";
//从a.js文件中使用default进行导出的函数,这里的话就可以自定义给这个函数命名=>必须单独引入
import lalalalala from "./a.js";
//统一导入
import * as mydata from "./c.js";
//统一导入时的传统方式
import { multify, decline } from "./c.js";
//这个就是c.js中的default进行导出的对象,这里可以使用任何变量名/对象名进行接收=>必须单独引入
import sssss from "./c.js";
console.log(age);
console.log(lalalalala(10, 3));
//注意统一导入时的写法(适用于需要导入很多数据时使用,此时并没有必要一一进行导入)
console.log(mydata.multify(19, 2));
console.log(mydata.decline(10, 3));
//也可以进行普通导入
console.log(multify(19, 2));
console.log(decline(10, 3));
console.log(sssss);
console.log(new Date());
- c.js文件
function multify(num1, num2) {
return num1 * num2;
}
const sex = "男";
// 导出方式1
export { multify };
// 导出方式2
export function decline(num1, num2) {
return num1 - num2;
}
//定义一个default,那么在导入的时候就可以随便进行命名,但是一个js文件中只有一个default,不能有多个default,不然会报错
export default sex;
- 运行主入口文件结果如下[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lTdxfOTu-1607653093756)(C:\Users\hp\Desktop\vue\new_round\08模块化\导入导出.PNG)]
webpack
- 主要功能:解决依赖,在前端主入口文件只需导入一个打包好的bundle.js文件即可。
基本介绍
- webpack的目的就是为了模块化开发,处理模块之间的依赖关系
- webpack出了把JS文件当成模块化进行开发,例如图片/CSS/JSON文件等也将进行模块化开发
- 使用webpack的实质就是在开发过程中使用CommonJS(应用ES6语法导入导出也可以)语法进行相关的导出导入
- 这里需要指出的是CommonJS底层做了很多的工作,具有较强的适应能力,能够轻易的被打包成浏览器能够识别的代码
- 使用webpack工具进行打包成一个浏览器能够识别的JS代码(打包完成的js代码只有一个文件,这一个文件经过了打包之后处理了其中的依赖关系,引入时只需引入这一个文件,十分便捷),最后直接将打包好的js文件进行导入到前端主入口html文件进行编译解析。
- 浏览器中只能识别ES6的导入导出方式(但是在大项目开发的时候不建议使用这种导入导出方式,不利于打包=>不利于处理模块之间的依赖关系)
简单使用
这里我们使用webpack3.6.0版本进行使用,在项目的根文件夹下建立一个名为dist的文件夹用于放置打包好的bundle.js文件,在根目录下再建立一个src的文件夹用于存放一些js文件,其中src目录下应该包含一个main.js主入口js文件(习惯命名法则),其导入其他js文件时应遵循commonJS的导入规则,然后前端的主入口index.html文件也应该放置于根目录下。如下图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HJprtbFb-1607653093758)
(C:\Users\hp\Desktop\vue\new_round\09webpack\01初识webpack\捕获.PNG)]
其中在跟目录下使用npm i webpack@3.6.0 --save–dev命令安装webpack,然后在根目录下使用webpack ./src/main.js 空格./dist/bundle.js命令来把js文件进行打包,并将进行打包的文件放置于dist文件夹下的bundle.js文件。这就完成了一次打包,然后在前端主入口文件index.html文件中使用
有关webpack中代码简写的设置
- 首先在根目录文件下新建一个名为"webpack.config.js"的文件,具体代码如下
//引入node.js中路径模块
const path=require('path')
module.exports={
//设置入口
entry:"./src/main.js",
//设置出口,实现动态获取
output:{
path:path.resolve(__dirname,"dist"),
filename:"bundle.js"
},
}
-
但凡涉及到Node.js的就一定要记得生成package.json文件,此时就要就得在webpack包下载完成之后或者之前就应该使用"npm init -y"进行初始化设置生成package.json文件;
- 此时使用"webpack"命令就可以完全取代上面的webpack ./src/main.js 空格./dist/bundle.js代码,从而实现进行相应的打包
-
此时如果想要进行简便设置(例如npm run xxx)的话,这时只需将package.json文件中的scripts中增加" ’build‘:’webpack‘"就可以实现使用用"npm run build"就可以实现打包任务了。也就是说取代了直接使用"webpack"命令了。
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", //这里加入以下语句就是为了能够优先加载本地的,在终端中使用的话优先就是使用全局的 "build":"webpack" },
-
有关为什么使用npm i webpack --save-dev中的’–dev‘命令,这代表是在开发阶段使用的,在实际运行阶段是不需要直接使用的,其实是在中间过程中使用到了,我们直接使用的是这个包加工后的文件
CSS打包机制
有关代码书写规范
- 在src目录下,应该把主入口js文件暴露在外面,其余的js或者css等文件应该单独建立一个文件夹,这样进行相关的开发会更加清晰。
- 使用这些东西的目的就是为了减少相关的导入导出,此时的css文件必须在主js文件中建立依赖关系,直接使用require将其引入到main.js文件中,
具体下载使用
由于webpack的主要功能就是打包js文件,所以有关css文件的打包webpack是单独完成不了的,此时必须依赖相关的插件进行相关的配置。首先进入webpack官网进行相关文档的阅读,找到loader进行阅读,首先使用npm命令下载
-
style-loader和css-loader配合使用,分别使用命令npm install --save-dev css-loader和npm install style-loader --save-dev进行相关下载。
-
然后在之配置过的webpack.config.js文件中进行相关配置(只需加入一个module对象)
-
const path = require("path"); module.exports = { entry: "./src/main.js", output: { path: path.resolve(__dirname, "dist"), filename: "bundle.js", }, module: { rules: [ { test: /\.css$/, use: ["style-loader", "css-loader"], }, ], }, };
-
此时只需输入npm run build即可将css文件导入到bundle.js文件中,即css文件生效了。
-
vueCLI
- 首先使用npm install -g @vue/cli命令全局安装
- 来到目标目录下使用命令 “vue create 项目名称”来进行创建新的项目,之后进行初始化
- 直接在终端(建议)用npm run serve进行项目的运行(开发阶段)
- 直接在终端(建议)用npm run build进行项目的运行(部署阶段)
- 在相应文件目录下输入cmd打开命令提示框(建议)用vue ui命令用来使用可视化工具创建项目(直接在vs中老是报错)
- 也可以直接在ui界面中直接打开相应的项目进行配置
网页的历史发展
- 早期的网页就是由后端直接根据用户的请求的url进行解析,然后间接分发一个渲染好的html文件返回给用户,就是后端渲染;
- 中期出现了前后端分离的模式,即随着Ajax等技术的兴起,前后端分离的趋势愈加明显;
- 现阶段SPA(单页面应用)=>即首先根据用户的请求地址将所有的资源下载下来,然后根据具体的路由地址抽取具体的html文件,这就是前端路由。
- SPA页面最大的优点就是在前后端分离的基础之上添加了前端路由,也就是由前端来维护一套路由规则
Vuex
简单介绍
官方解释:vuex实际上就是vue项目开发的状态管理模式,通俗的讲就是把需要全部组件共享的变量全部存储在一个对象里面,然后把这个对象放在顶层的Vue实例中,让其他组件可以使用
使用场景:比如购物车、位置共享、用户的登入状态、头像、用户名等
vue-router
基本使用
- 如果是在做练习的话,可以直接在vue-router官网直接进行下载,然后直接通过script标签进行引入
<body>
<div id="app">
<!-- 使用 router-link 组件来导航. -->
<!-- 通过传入 `to` 属性指定链接. -->
<!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
<router-link to="/user">Welcome to user</router-link>
<router-link to="/register">Welcome to register</router-link>
<!-- 路由出口 -->
<!-- 路由匹配到的组件将渲染在这里 -->
<router-view></router-view>
</div>
<script>
// 2.定义路由组件
const User = {
template: "<h1>hello users</h1>"
}
const Register = {
template: "<h1>hello registers</h1>"
}
// 3. 创建 router 实例,然后传 `routes` 配置
const router = new VueRouter({
routes: [{
// 和to属性保持一一对应
path: '/user',
//表示当前路由规则对应要展示的组件
component: User
}, {
path: '/register',
component: Register
}]
})
// 实例化vue对象
const app = new Vue({
el: "#app",
// 4.将实例化的router挂载到vue实例中
router: router,
})
</script>
</body>
路由重定向
路由重定向就是指:当用户在访问地址A的时候,强制用户跳转到地址C,从而展示特定的页面,见下一节代码
嵌套路由
<body>
<div id="app">
<router-link to="/user">Welcome to user</router-link>
<router-link to="/register">Welcome to register</router-link>
<router-view></router-view>
</div>
<script>
//定义路由组件
const User = {
template: "<h1>hello users</h1>",
};
const Register = {
template: `
<div>
<h1>hello registers</h1>
<router-link to="/register/Tab1">Tab1</router-link>
<router-link to="/register/Tab2">tab2</router-link>
<router-view></router-view>
</div>
`
};
const Tab1 = {
template: "<h1>hello tab1</h1>",
};
const Tab2 = {
template: "<h1>hello tab2</h1>",
};
//创建 router 实例
const router = new VueRouter({
routes: [
{
path: "/user",
component: User,
},
{
path: "/register",
component: Register,
//在register组件下再定义有关子组件的路由规则,由children属性进行存储
children: [
{
path: "/register/Tab1",
component: Tab1,
},
{
path: "/register/Tab2",
component: Tab2,
},
],
},
{
// 路由重定向
path: "/",
redirect: "/user",
},
],
});
// 实例化vue对象
const app = new Vue({
el: "#app",
// 将实例化的router挂载到vue实例中
router: router,
data: {
msg: "hello world",
},
});
</script>
</body>
动态路由
<body>
<div id="app">
<router-link to="/user/1">user1</router-link>
<router-link to="/user/2">user2</router-link>
<router-link to="/user/3">user3</router-link>
<router-link to="/register">Welcome to register</router-link>
<router-view></router-view>
</div>
<script>
// 定义路由组件
const User = {
// 利用$route.params.myid获取(其中myid可以随便取)
template: "<h1>hello users----用户id为{{$route.params.myid}}</h1>",
};
const Register = {
template: "<h1>hello registers</h1>",
};
// 3. 创建 router 实例
const router = new VueRouter({
routes: [{
//创建动态路由
path: "/user/:myid",
component: User,
},
{
path: "/register",
component: Register,
},
{
// 路由重定向
path: "/",
redirect: "/user",
},
],
});
// 实例化vue对象
const app = new Vue({
el: "#app",
// 将实例化的router挂载到vue实例中
router: router,
});
</script>
</body>
路由组件传递参数
-
第一种
- 如上节使用==$route.params.id===>不太建议使用
-
第二种
- 在route实例里面定义一个props参数(布尔值)
-
第三种
- 在route实例里面定义一个props参数(对象)
-
第四种
- 在route实例里面定义一个props参数(函数)
<body>
<div id="app">
<router-link to="/user/1">user1</router-link>
<router-link to="/user/2">user2</router-link>
<router-link to="/user/3">user3</router-link>
<router-link to="/register">Welcome to register</router-link>
<router-view></router-view>
</div>
<script>
// 定义路由组件
const User = {
//定义一个路由参数,用于传递参数1
// props:['myid']
// 直接进行参数的使用1
// template: "<h1>hello users----用户id为{{myid}}</h1>",
//定义一个路由参数,用于传递参数2
// props:['uname',"age"],
// 直接进行参数的使用2
// template: "<h1>姓名:{{uname}}---年龄:{{age}}</h1>"
//定义一个函数,用于传递参数3
props: ['id', 'uname', 'age'],
template: '<h3>姓名:{{uname}}---年龄:{{age}}---id:{{id}}</h3>'
};
const Register = {
template: "<h1>hello registers</h1>",
};
// 3. 创建 router 实例
const router = new VueRouter({
routes: [{
path: "/user/:myid",
component: User,
// 定义一个布尔值,用于路由传递参数1
// props:true
// 定义一个对象,用于路由传递参数2
// props:{uname:"lili",age:12}
//定义一个函数,用于路由传递参数3
props: route => {
return {
id: route.params.myid,
uname: "lili",
age: 12
}
}
},
{
path: "/register",
component: Register,
},
{
// 路由重定向
path: "/",
redirect: "/user",
},
],
});
// 实例化vue对象
const app = new Vue({
el: "#app",
// 将实例化的router挂载到vue实例中
router: router,
});
</script>
</body>
命名路由
- 有时候,通过一个名称来标识一个路由显得更方便一些,特别是在链接一个路由,或者是执行一些跳转的时候。你可以在创建 Router 实例的时候,在
routes
配置中给某个路由设置名称。
const router = new VueRouter({
routes: [
{
path: '/user/:userId',
name: 'user',
component: User
}
]
})
- 要链接到一个命名路由,可以给
router-link
的to
属性传一个对象:
<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>
路由编程式导航
- 声明式导航:常见的有,通过点击链接进行跳转
- 编程式导航
- this.$router.push(‘哈希地址’)
- this.$router.go(n) =>实现页面前进和回退功能(1为前进,-1为后退)
<body>
<div id="app">
<router-link to="/user">user</router-link>
<router-link to="/register">register</router-link>
<router-view></router-view>
</div>
<script>
// 定义路由组件
const User = {
template: `<div>
<h1>hello users</h1>
<button @click='switch1'>点击跳转到注册页面</button>
<button @click='switch3'>点击进行回退或者前进</button>
</div>`,
methods: {
switch1: function () {
this.$router.push('/register')
},
switch3:function(){
this.$router.go(-1)
}
}
};
const Register = {
template: `
<div>
<h1>hello register</h1>
<button @click='switch2'>点击跳转到用户页面</button>
<button @click='switch4'>点击进行回退或者前进</button>
</div>`,
methods: {
switch2: function () {
this.$router.push("/user")
},
switch4:function(){
this.$router.go(1)
}
}
};
// 3. 创建 router 实例
const router = new VueRouter({
routes: [{
path: "/user",
component: User,
},
{
path: "/register",
component: Register,
},
{
// 路由重定向
path: "/",
redirect: "/user",
},
],
});
// 实例化vue对象
const app = new Vue({
el: "#app",
// 将实例化的router挂载到vue实例中
router: router,
});
</script>
</body>
Promise
Promise就是解决异步编程的一种方案,由于某些调用或者函数是异步的,执行顺序并不是固定的,假如我们想要控制代码执行顺序,此时就会涉及到回调地狱,为了解决这个问题,Promise为我们解决了这个回调地狱,可以方便的控制代码执行顺序。
首先应该明确Promise是一个函数(也是一个对象),
const fs=require('fs');
var p1=new Promise(
(resolve,reject)=>{
fs.readFile('./1.txt',
(err,data)=>{
if(err){reject(err)}
else{resolve(data)}
})
}
)
var p2=new Promise(
(resolve,reject)=>{
fs.readFile('./2.txt',
(err,data)=>{
if(err){reject(err)}
else{resolve(data)}
})
}
)
var p3=new Promise(
(resolve,reject)=>{
fs.readFile('./3.txt',
(err,data)=>{
if(err){reject(err)}
else{resolve(data)}
})
}
)
//then 里面接收函数就是resolve函数
p1.then(
//成功时执行的函数
function(data){console.log(data.toString())
return p2
},
//失败时调用的函数
function(err){console.log(err)}
)
.then(
function(data){console.log(data.toString())
return p3
},
function(err){console.log(err)}
)
.then(
function(data){console.log(data.toString())},
function(err){console.log(err)}
)
axios
axios的简单使用(针对练习时使用)
//html代码
<script src="./axios.js"></script>
<script>
axios.get('http://localhost:3000/index').then(
// data属性是固定用法,用于获取后台的实际数据
function(ref){
console.log(ref)
console.log(ref.data)}
)
</script>
//app.js代码
//引入express
const express = require('express');
const app = express();
//引入以及配置bady-parser
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(bodyParser.json())
//配置静态web目录
app.use(express.static('static'));
//解决跨域
app.all('*', function (req, res, next) {
// 解决跨域问题
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
res.header("Access-Control-Allow-Headers", "Content-Type,Content-Length, Authorization, Accept,X-Requested-With");
next();
//渲染1
app.get('/index',
(req, res) => {
res.send('hello axios')
})
axios的参数传递
-
get传递参数
- 通过url传递参数(传统形式)
//html代码 <script> axios.get('http://localhost:3000/axios?id=123').then( // data属性是固定用法,用于获取后台的实际数据 function (ref) { console.log(ref) console.log(ref.data) } ) </script>
//app.js代码 //渲染2 app.get('/axios', (req, res) => { res.send('hello axios'+req.query.id) })
输出结果如下 hello axios123
- 通过url传递参数(restful形式)=>略
- 通过params选项传递参数
axios.get('http://localhost:3000/admin', {
// 前端如果用params,那么后台就用query进行接收
params: {
id: 123,
name:"张三"
}
}).then(ref => {
console.log(ref.data)
})
app.get('/admin',
(req, res) => {
res.send('hello axios(params形式传参)'+req.query.id+req.query.name)
})
-
delete传参=>与get形式传参基本一样
-
post传参
<script src="./axios.js"></script> <script> // post-----json格式传参 axios.post('http://localhost:3000/admin', { id: 123, name: "张三" }).then(ref => { console.log(ref.data) }) // post-----表单形式传参 var params = new URLSearchParams(); params.append("name", "zhangsan") params.append("age", "20") axios.post('http://localhost:3000/axios', params).then(ref => { console.log(ref.data) }) </script>
//post请求1 app.post('/admin', (req, res) => { res.send('post传参1----' + req.body.id + req.body.name) }) //post请求2 app.post('/axios', (req, res) => { res.send('post传参2----' + req.body.age + req.body.name) })
-
put传参=>与post类似
-
axios.put('http://localhost:3000/admin/321', { age: 22, name: "张三" }).then(ref => { console.log(ref.data) })
-
app.put('/admin/:id', (req, res) => { res.send('put传参1----' + req.params.id +'----' +req.body.name+'----'+req.body.age) })
-
终极代码之html
<script src="./axios.js"></script>
<script>
// url形式传参之传统形式传参
axios.get("http://localhost:3000/axios?id=123").then(
// data属性是固定用法,用于获取后台的实际数据
function (ref) {
console.log(ref.data);
}
);
// url形式传参之restful形式传参
axios.get("http://localhost:3000/axios/123").then(
// data属性是固定用法,用于获取后台的实际数据
function (ref) {
console.log(ref.data);
}
);
// params形式传参
axios
.get("http://localhost:3000/admin", {
// 前端如果用params,那么后台就用query进行接收
params: {
id: 123,
name: "张三",
},
})
.then((ref) => {
console.log(ref.data);
});
// delete----params形式传参
axios
.delete("http://localhost:3000/deletes", {
params: {
id: 123,
name: "张三",
},
})
.then((ref) => {
console.log(ref.data);
});
// post-----json格式传参
axios
.post("http://localhost:3000/admin", {
id: 123,
name: "张三",
})
.then((ref) => {
console.log(ref.data);
});
// post-----表单形式传参
var params = new URLSearchParams();
params.append("name", "zhangsan");
params.append("age", "20");
axios.post("http://localhost:3000/axios", params).then((ref) => {
console.log(ref.data);
});
// put-----json格式传参
axios
.put("http://localhost:3000/admin/321", {
age: 22,
name: "张三",
})
.then((ref) => {
console.log(ref.data);
});
</script>
//引入express
const express = require("express");
const app = express();
//引入以及配置bady-parser
var bodyParser = require("body-parser");
app.use(
bodyParser.urlencoded({
extended: false,
})
);
app.use(bodyParser.json());
//配置静态web目录
app.use(express.static("static"));
//解决跨域
app.all("*", function (req, res, next) {
// 解决跨域问题
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
res.header(
"Access-Control-Allow-Headers",
"Content-Type,Content-Length, Authorization, Accept,X-Requested-With"
);
next();
if (req.method == "OPTIONS") {
res.send(200);
} else {
next();
}
});
//渲染1(基本使用)
app.get("/index", (req, res) => {
res.send("get(基本使用)");
});
//渲染2(url形式传参之传统形式传参)
app.get("/axios", (req, res) => {
res.send("get(url形式传参之传统形式传参)" + req.query.id);
});
//渲染3(url形式传参之restful形式传参)
app.get("/axios/:id", (req, res) => {
res.send("get(url形式传参之restful形式传参)" + req.params.id);
});
//渲染4(params形式传参)
app.get("/admin", (req, res) => {
res.send("get(params形式传参)" + req.query.id + req.query.name);
});
//渲染5 delete例子(params形式传参)
app.delete("/deletes", (req, res) => {
res.send("delete(params形式传参)" + req.query.id + req.query.name);
});
//post请求1
app.post("/admin", (req, res) => {
res.send("post传参1----" + req.body.id + req.body.name);
});
//post请求2
app.post("/axios", (req, res) => {
res.send("post传参2----" + req.body.age + req.body.name);
});
//put请求1
app.put("/admin/:id", (req, res) => {
res.send(
"put传参1----" +
req.params.id +
"----" +
req.body.name +
"----" +
req.body.age
);
});
//绑定端口
app.listen(3000, function () {
console.log("running successful");
});
axios的响应结果
-
响应结果主要属性
- data 实际响应回来的数据
- headers 响应头
- status响应状态码
-
Axios中全局配置
- 配置公共的请求头 axios.defaults.baseURL
- 配置 超时时间 axios.defaults.timeout
- 配置公共的请求头 axios.defaults.headers.common[‘Authorization’]
axios拦截器
-
请求拦截器
-
请求拦截器的作用是在请求发送前进行一些操作
-
例如在每个请求体里加上token,统一做了处理,如果以后要改也非常容易
-
-
响应拦截器
- 响应拦截器的作用是在接收到响应后进行一些操作
- 例如在服务器返回登录状态失效,需要重新登录的时候,跳转到登录页
<script>
//响应拦截器
axios.interceptors.response.use(
function (res) {
//直接进行设置,从而直接使用data
var data = res.data;
return data;
},
function (error) {
console.log(error);
}
);
async function bbb() {
const a = await axios.get("http://localhost:3000/one");
return a;
}
bbb().then((b) => {
console.log(b);
});
</script>
app.get("/one", (req, res) => {
res.send("响应拦截器");
});
async和await的使用
- async和await是ES7引入的新语法,可以更加方便的进行异步操作
- async关键字用于函数上=>async函数的返回值是一个Promise实例对象
- await关键字用于async函数中=>await可以得到异步的结果
<script>
// axios之全局配置默认地址
axios.defaults.baseURL='http://localhost:3000/';
//await 和async的使用
async function aaa(){
// 这里可以直接拿到异步结果
const a=await axios.get("pages?id=12")
return a.data
}
// 调用函数时直接使用then进行使用
aaa().then(b=>{console.log(b)})
</script>
async和await处理多个异步请求
<script>
axios.defaults.baseURL = "http://localhost:8888";
async function getAxios() {
const info = await axios.get("async1");
// 传统形式传参=>利用第一个异步函数返回的值作为下一个异步函数执行的参数
const ret = await axios.get("async2?info=" + info.data);
return ret.data;
}
getAxios().then(function (s) {
console.log(s);
});
</script>
//多个await和async的使用
app.get("/async1", (req, res) => {
res.send("hello1");
});
app.get("/async2", (req, res) => {
if (req.query.info == "hello") {
res.send("world");
} else {
res.send("error");
}
res.send("error");
});
g(error);
}
);
async function bbb() {
const a = await axios.get("http://localhost:3000/one");
return a;
}
bbb().then((b) => {
console.log(b);
});
```
app.get("/one", (req, res) => {
res.send("响应拦截器");
});
async和await的使用
- async和await是ES7引入的新语法,可以更加方便的进行异步操作
- async关键字用于函数上=>async函数的返回值是一个Promise实例对象
- await关键字用于async函数中=>await可以得到异步的结果
<script>
// axios之全局配置默认地址
axios.defaults.baseURL='http://localhost:3000/';
//await 和async的使用
async function aaa(){
// 这里可以直接拿到异步结果
const a=await axios.get("pages?id=12")
return a.data
}
// 调用函数时直接使用then进行使用
aaa().then(b=>{console.log(b)})
</script>
async和await处理多个异步请求
<script>
axios.defaults.baseURL = "http://localhost:8888";
async function getAxios() {
const info = await axios.get("async1");
// 传统形式传参=>利用第一个异步函数返回的值作为下一个异步函数执行的参数
const ret = await axios.get("async2?info=" + info.data);
return ret.data;
}
getAxios().then(function (s) {
console.log(s);
});
</script>
//多个await和async的使用
app.get("/async1", (req, res) => {
res.send("hello1");
});
app.get("/async2", (req, res) => {
if (req.query.info == "hello") {
res.send("world");
} else {
res.send("error");
}
res.send("error");
});