Vue入门学习(2)
1.组件的生命周期
每个组件创建都要经过一系列初始化过程,如需要设置监听、编译模板、将实例挂载到Dom并在数据变化时更新Dom等。在这个过程中会运行一些叫做生命周期钩子的函数。用户可以在不同阶段添加自己的代码。
可以简单记下四个状态,然后就是分别对应的前后。
//创建前
beforeCreate(){
},
// 创建后
created(){
},
// 渲染前
beforeMount(){
},
//渲染后
mounted(){
alert('把网络请求放在这里');
},
//更新前
beforeUpdate(){
//在组件的数据发生变化之前
},
//更新后
updated(){
},
//卸载前
beforeUnmount(){
//卸载前把消耗性能的计时器等处理清除。
},
//卸载后
unmounted(){
}
2.Vue引入第三方
第三方提供服务,生态越强大,第三方服务也越多,越能节约时间。
Swiper开源免费强大触摸滑动插件。
官方文档地址:swiperjs.com/vue
在命令行安装:
npm install --save swiper
在package.json中可以看见安装好的swiper版本。
需要安装指定版本:
npm install --save swiper@8.1.6
安装完成后导入进来:
<script>
import {Swiper,SwiperSlide} from 'swiper/vue';
import 'swiper/css';
export default {
name: 'HelloWorld',
//组件注入的形式注入
components:{
Swiper,
SwiperSlide
},
}
添加指示器:
import {Pagination } from ‘swiper’
在script中添加引用:
//引入Swiper
import {Swiper,SwiperSlide} from 'swiper/vue';
//引入指示器
import {Pagination} from 'swiper';
import 'swiper/css';
import 'swiper/css/pagination';
在页面中使用:
<swiper :modules="modules" :pagination="{ clickable: true }">
<swiper-slide> <img src="../assets/cat.jpg" alt="..."> </swiper-slide>
<swiper-slide> <img src="../assets/dogwitharmor.jpg" alt="..."> </swiper-slide>
<swiper-slide> <img src="../assets/logo.png" alt="..."> </swiper-slide>
实现了基本的轮播图。
3.Axios网络请求
Axios是一个基于promise的网络请求库。
安装:
npm install --save axios
导入:
import axios from ‘axios’
//渲染后请求
mounted(){
axios({
method:"get",
//这里是从一个地址获取数据
url:"http://iwenwiki.com/api/blueberrypai/getChengpinDetails.php"
}).then(res=>{
this.chenpin =res.data.chengpinDetails[0]
})
结果:
post请求时, 传递参数,这里是data对象数据,要转换格式,安装querystring第三方包,用QueryString.queryfy方法来转换。
data:{
user_id :"iwen@qq.com",
password:"iwen123",
verification_code:"crfvw"
}
npm install --save querystring
导入后转换格式。
this.$axios.post("http://iwenwiki.com/api/blueberrypai/getChengpinDetails.php", QueryString.stringify({
user_id: "iwen@qq.com",
password: "iwen123",
varification_Code: "crfvw"
})
在全局引入:
main.js中引入。
import { createApp } from 'vue'
import App from './App.vue'
import './registerServiceWorker'
// 挂载到全局
import axios from 'axios'
const app = createApp(App)
app.config.globalProperties.$axios = axios
app.mount('#app')
全局引入后就不用在插件中一个一个引用了。
<template>
<div class="hello">
<div>
<p>{{ chenpin.title }}</p>
</div>
</div>
</template>
<script>
//引入Swiper
import { Swiper, SwiperSlide } from 'swiper/vue';
//引入指示器
import { Pagination } from 'swiper';
import 'swiper/css';
import 'swiper/css/pagination';
//转换格式的包
import qureystring from "querystring";
import QueryString from 'qs';
export default {
name: 'HelloWorld',
//组件注入的形式注入
components: {
Swiper,
SwiperSlide
},
data() {
return {
modules: [Pagination],
chenpin: [],
}
},
mounted() {
this.$axios.get("http://iwenwiki.com/api/blueberrypai/getChengpinDetails.php").then(res => {
this.chenpin = res.data.chengpinDetails[0]
})
this.$axios.post("http://iwenwiki.com/api/blueberrypai/getChengpinDetails.php", QueryString.stringify({
user_id: "iwen@qq.com",
password: "iwen123",
varification_Code: "crfvw"
})
).then(res => {
console.log(res.data)
})
}
}
</script>
4.网络请求的封装
使用率比较高,将网络请求封装起来,易于维护使用。
utils文件夹下创建request.js 文件,封装请求方法。
import axios from "axios";
import querystring from 'querystring'
const instance = axios.create({
//网络请求的公共配置
timeout: 5000
})
//最常用的拦截器
//1.发送数据之前:
instance.interceptors.request.use(
//成功的函数,config包含网络请求的所有信息。
config => {
if (config.method === "post") {
config.data = querystring.stringify(config.data)
}
return config;
},
//失败的函数
error => {
//请求拒绝,返回错误
Promise.reject(error)
}
)
//2.获取数据之前的拦截器
instance.interceptors.response.use(
response=>{
return response.status == 200 ? Promise.resolve(response):Promise.reject(response)
},
error => {
const{ response } = error;
}
)
export default instance;
网络请求放到Api文件夹中,创建api文件夹,创建index.js文件。
import axios from "axios";
import path from "./path"
const api = {
getChenpin(){
return axios.get(path.baseUrl + path.chengpin)
}
}
export default api
创建path.js封装保存路径:
const base = {
baseUrl:"http://iwenwiki.com",
chengpin:"/api/blueberrypai/getChengpinDetails.php"
}
封装后调用api就可以访问.
mounted() {
api.getChenpin().then(res =>{
console.log(res.data);
})
5.网络请求的跨域解决
网络请求经常会产生跨域,是因为js采取同源策略。
同源策略是一项安全策略,只允许js代码请求和当前所在服务器的域名、端口、协议相同的数据接口上的数据。
协议、域名端口任意一个不相同时都会产生跨域问题。
一般都不能对后台其他端口进行跨域处理,因此我们往往在前端解决跨域问题。
实例:
<template>
<div class="hello">
<h1>跨域解决方案:proxy</h1>
</div>
</template>
<script>
import axios from 'axios';
export default {
name: 'HelloWorld',
mounted(){
axios.get("http://iwenwiki.com/api/FingerUnion/list.php").then(res=>{
console.log(res.data) ;
})
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
报错:
发生了四个错误,可以看到发生了跨域访问被blocked:
- Failed to load resource: the server responded with a status of 404 (Not Found)
- Access to XMLHttpRequest at ‘url’ from origin ‘http://localhost:8080’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
- Failed to load resource: net::ERR_FAILED
- Uncaught (in promise)
解决跨域问题
在vue.config.js中加入这段代码:
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
//解决跨域问题代码:
devServer:{
proxy:{
'/api':{
target:'<url>',
changeOrigin:true
}
}
}
})
这里的 target 要指定 协议、域名、端口才可以,否则会报错。
ERROR TypeError [ERR_INVALID_URL]: Invalid URL
解决完跨域的配置后,要重启服务器才会生效。
拿到数据:
6.Vue引入路由配置
vue中可以通过vue-router路由管理页面之间的关系
Vue Router是Vue.js的官方路由。它与Vue.js核心深度集成,用vue.js构建单页很容易实现。
在Vue中引入路由:
1.安装路由
npm install vue-router --save
2.创建配置文件
创建router文件夹
创建index.js 路由配置文件
import {createRouter,createWebHashHistory} from 'vue-router';
import HomeView from "../views/HomeView";
import AboutView from "../views/AboutView";
//配置信息中需要页面相关配置:
const routers= [
{
path:'/',
component:HomeView
},
{
path:'/about',
component:AboutView
}
]
const router = createRouter({
history: createWebHashHistory(),
routes: routers
})
//导出router
export default router;
createWebHashHistory:
不需要后台重定向
原理 :a标签的锚点连接
createWebHistory:
需要后台配合做重定向,否则会出现404报错.
原理 :H5 pushStatu()
3.在main.js中导入,并明确使用功能:使用use(router)
import { createApp } from 'vue';
import App from './App.vue';
import './registerServiceWorker';
import router from './router';
// 通过use的方式来应用,明确路由功能
createApp(App).use(router).mount('#app')
4.在app.vue组件中设置显示入口:<router-view
>,制定路由跳转的导航
<template>
<!-- 导航链接 -->
<router-link to="/">首页||</router-link>
<router-link to="/About">关于</router-link>
<!-- 路由的显示入口 -->
<router-view></router-view>
</template>
<script>
export default {
name: 'App',
}
</script>
tip:return
用于函数的返回值,而export default
用于模块的默认导出。
7.路由传递参数
创建项目时,如果选择了vue自带的Router就不用再下载安装。
需要添加新的页面时,直接在View文件夹下创建页面。
打开默认配置文件 index.js,加入新页面的路径。
{
path:"/news",
name:"news",
//这是异步加载方式,如果页面没有显示出来,代码就不会执行。
component:() => import ('../views/NewsView.vue')
}
在nav导航栏中加入新的链接地址。
<router-link
to=“/news”>News
就可以直接点击跳转了。
如果要实现参数传递:
1.在路由配置中指定参数的key
{ //加入/: 代表要传参的key值
path:"/newsdetails/:name",
name:"newsdetails",
//这是异步加载方式,如果页面没有显示出来,代码就不会执行。
component:() => import ('../views/NewsDetailsView.vue')
}
2.在跳转过程中携带参数
<ul>
<li><router-link to="/newsdetails/百度">百度新闻</router-link></li>
<li> <router-link to="/newsdetails/网易">网易新闻</router-link></li>
<li> <router-link to="/newsdetails/新浪">新浪新闻</router-link></li>
</ul>
3.在详情页读取路由携带过来的参数
<template>
<h3>新闻详情</h3>
//读取key
<p>{{ $route.params.name }}</p>
</template>
创建项目时,如果选择了vue自带的Router就不用再下载安装。
需要添加新的页面时,直接在View文件夹下创建页面。
打开默认配置文件 index.js,加入新页面的路径。
{
path:"/news",
name:"news",
//这是异步加载方式,如果页面没有显示出来,代码就不会执行。
component:() => import ('../views/NewsView.vue')
}
在nav导航栏中加入新的链接地址。
<router-link
to=“/news”>News
就可以直接点击跳转了。
如果要实现参数传递:
1.在路由配置中指定参数的key
{ //加入/: 代表要传参的key值
path:"/newsdetails/:name",
name:"newsdetails",
//这是异步加载方式,如果页面没有显示出来,代码就不会执行。
component:() => import ('../views/NewsDetailsView.vue')
}
2.在跳转过程中携带参数
<ul>
<li><router-link to="/newsdetails/百度">百度新闻</router-link></li>
<li> <router-link to="/newsdetails/网易">网易新闻</router-link></li>
<li> <router-link to="/newsdetails/新浪">新浪新闻</router-link></li>
</ul>
3.在详情页读取路由携带过来的参数
<template>
<h3>新闻详情</h3>
//读取key
<p>{{ $route.params.name }}</p>
</template>
8.嵌套路由配置
配置路由导航,属于谁就在谁下面加children:[ ]
{
path: '/about',
name: 'about',
component: () => import('../views/AboutView.vue'),
children:[
{ //二级导航的路径不要加斜杠 /
path:"us",
component:() =>import("../views/AboutSub/AboutUs.vue")
},
{
path:"info",
component:() => import("../views/AboutSub/AboutInfo.vue")
}
]
}
添加子路由跳转链接
<template>
<div class="about">
<router-link to="/about/us">关于我们 </router-link> |
<router-link to="/about/info">关于信息 </router-link>
<!-- 显示入口 -->
<router-view></router-view>
</div>
</template>
添加重定向,设置默认打开页面。
path: '/about',
name: 'about',
redirect:'/about/us',