可以发送aja请求的几种方式
跨域
协议名,主机名,端口号须一致,才是同源的,否则。。
解决跨域的方法
- 后端人员用cors,配置响应头
- jsonp,前后端共同解决,且只能解决get类型的
- 配置代理服务器——因为两台服务器之间,只受协议有关
开代理服务器
- nginx
- vue-cli
// App.vue
<template>
<div>
<button @click="getStu">获取学生信息</button>
</div>
</template>
<script>
import axios from "axios";
export default {
name: "App",
methods: {
getStu() {
axios.get("http://localhost:8080/students").then(
//成功的回调
(response) => {
console.log("请求成功!", response.data);
},
(error) => {
console.log("请求失败了,失败的原因是:", error.message);
}
);
},
},
};
</script>
//vue.config.js
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
lintOnSave: false,
devServer: {
proxy: 'http://localhost:5000'
}
})
缺点:1. 不能配置多个服务器
2. 原服务器有的,不会向新服务器请求
//App.vue
methods: {
getStu() {
//注意前缀的位置
axios.get("http://localhost:8080/fang/students").then(
//成功的回调
(response) => {
console.log("请求成功!", response.data);
},
(error) => {
console.log("请求失败了,失败的原因是:", error.message);
}
);
},
},
//vue.config.js
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
lintOnSave: false,
devServer: {
proxy:{
//请求前缀
'/fang': {
target: 'http://localhost:5000',
// 重写路径
// 匹配以/fang开头的,并将/fang转换为空
pathRewrite: {
'^/fang': ''
},
//欺骗5000服务器,说自己来自5000
//用于控制请求头中的host值
changeOrigin: true
}
}
}
})
//App.vue
<template>
<div>
<button @click="getStu">获取学生信息</button>
<button @click="getCar">获取车辆信息</button>
</div>
</template>
<script>
import axios from "axios";
export default {
name: "App",
methods: {
getStu() {
axios.get("http://localhost:8080/fang/students").then(
//成功的回调
(response) => {
console.log("请求成功!", response.data);
},
//失败的回调
(error) => {
console.log("请求失败了,失败的原因是:", error.message);
}
);
},
getCar() {
axios.get("http://localhost:8080/hai/cars").then(
//成功的回调
(response) => {
console.log("请求成功!", response.data);
},
//失败的回调
(error) => {
console.log("请求失败了,失败的原因是:", error.message);
}
);
},
},
};
</script>
//vue.config.js
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
lintOnSave: false,
devServer: {
proxy:{
'/fang': {
target: 'http://localhost:5000',
pathRewrite: {
'^/fang': ''
},
changeOrigin: true
},
'/hai':{
target:'http://localhost:5001',
pathRewrite:{'^/hai': ''}
}
}
}
})
不加前缀就不走代理
<template>
<div>
<button @click="getStu">获取学生信息</button>
</div>
</template>
<script>
import axios from "axios";
export default {
name: "App",
methods: {
getStu() {
//不加前缀就不走代理
axios.get("http://localhost:8080/students").then(
//成功的回调
(response) => {
console.log("请求成功!", response.data);
},
//失败的回调
(error) => {
console.log("请求失败了,失败的原因是:", error.message);
}
);
},
},
};
</script>
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
lintOnSave: false,
devServer: {
proxy:{
'/fang': {
target: 'http://localhost:5000',
pathRewrite: {
'^/fang': ''
},
},
}
}
})
引入方式1:
在src下的assets里创建css文件,放入bootstrap.css文件
在App.vue中引入
import './assets/css/bootstrap.css'
引入方式2:
文件放置在public下的css里的bootstrap.css文件
在index.html文件里引入
//Search.vue
<template>
<section class="jumbotron">
<h3 class="jumbotron-heading">Search Github Users</h3>
<div>
<input
type="text"
placeholder="enter the name you search"
v-model="keyWord"
/>
<button @click="searchUser">Search</button>
</div>
</section>
</template>
<script>
import axios from 'axios'
export default {
name:'Search',
data(){
return {
keyWord:''
}
},
methods:{
searchUser(){
axios.get(`https://api.github.com/search/users?q=${this.keyWord}`).then(
response=>{
console.log('请求成功',response.data)
console.log('请求成功',response.data.items)
},
error=>{}
)
}
}
}
</script>
<style>
</style>
<template>
<section class="jumbotron">
<h3 class="jumbotron-heading">Search Github Users</h3>
<div>
<input
type="text"
placeholder="enter the name you search"
v-model="keyWord"
/>
<button @click="searchUser">Search</button>
</div>
</section>
</template>
<script>
import axios from "axios";
export default {
name: "Search",
data() {
return {
keyWord: "",
};
},
methods: {
searchUser() {
axios.get(`https://api.github.com/search/users?q=${this.keyWord}`).then(
(response) => {
console.log("请求成功");
this.$bus.$emit("UsersList", response.data.items);
},
(error) => {
console.log("请求失败");
}
);
},
},
};
</script>
<style>
</style>
//List.vue
<template>
<div class="row">
<div class="card">
<a href="https://github.com/xxxxxx" target="_blank">
<img style="width: 100px" />
</a>
<p class="card-text">xxxxxx</p>
</div>
<div class="card">
<a href="https://github.com/xxxxxx" target="_blank">
<img style="width: 100px" />
</a>
<p class="card-text">xxxxxx</p>
</div>
<div class="card">
<a href="https://github.com/xxxxxx" target="_blank">
<img style="width: 100px" />
</a>
<p class="card-text">xxxxxx</p>
</div>
<div class="card">
<a href="https://github.com/xxxxxx" target="_blank">
<img style="width: 100px" />
</a>
<p class="card-text">xxxxxx</p>
</div>
<div class="card">
<a href="https://github.com/xxxxxx" target="_blank">
<img style="width: 100px" />
</a>
<p class="card-text">xxxxxx</p>
</div>
</div>
</template>
<script>
export default {
name: "List",
data() {
return {
users: [],
};
},
//接收数据的组件
mounted() {
this.$bus.$on("UsersList", (users) => {
console.log("我是list组件,我收到数据:", users);
this.users = users;
});
},
};
</script>
<style>
.album {
min-height: 50rem; /* Can be removed; just added for demo purposes */
padding-top: 3rem;
padding-bottom: 3rem;
background-color: #f7f7f7;
}
.card {
float: left;
width: 33.333%;
padding: 0.75rem;
margin-bottom: 2rem;
border: 1px solid #efefef;
text-align: center;
}
.card > img {
margin-bottom: 0.75rem;
border-radius: 100px;
}
.card-text {
font-size: 85%;
}
</style>
//App.vue
import Search from "./components/Search.vue";
//main.js
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
beforeCreate(){
//安装全局事件总线
Vue.prototype.$bus=this
}
}).$mount('#app')
//List.vue
<template>
<div class="row">
<div class="card" v-for="user in users" :key="user.login">
<a :href="user.html_url" target="_blank">
<img
:src="user.avatar_url"
style="width: 100px" />
</a>
<p class="card-text">{{ user.login }}</p>
</div>
</div>
</template>
//list.vue
<template>
<div class="row">
<!-- 展示用户列表 -->
<div
class="card"
v-for="user in info.users"
:key="user.login"
v-show="info.users.length"
>
<a :href="user.html_url" target="_blank">
<img :src="user.avatar_url" style="width: 100px" />
</a>
<p class="card-text">{{ user.login }}</p>
</div>
<!-- 展示欢迎词 -->
<h1 v-show="info.isFirst">欢迎!</h1>
<!-- 展示加载中 -->
<h1 v-show="info.isloading">加载中</h1>
<!-- 展示错误信息 -->
<h1 v-show="info.errorMsg">{{ info.errorMsg }}</h1>
</div>
</template>
<script>
export default {
name: "List",
data() {
return {
info: {
isFirst: true,
isloading: false,
errorMsg: "",
users: [],
},
};
},
//接收数据的组件
mounted() {
this.$bus.$on("updateList", (dataObj) => {
this.info=dataObj
});
},
};
</script>
<style>
.album {
min-height: 50rem; /* Can be removed; just added for demo purposes */
padding-top: 3rem;
padding-bottom: 3rem;
background-color: #f7f7f7;
}
.card {
float: left;
width: 33.333%;
padding: 0.75rem;
margin-bottom: 2rem;
border: 1px solid #efefef;
text-align: center;
}
.card > img {
margin-bottom: 0.75rem;
border-radius: 100px;
}
.card-text {
font-size: 85%;
}
</style>
//search.vue
<template>
<section class="jumbotron">
<h3 class="jumbotron-heading">Search Github Users</h3>
<div>
<input
type="text"
placeholder="enter the name you search"
v-model="keyWord"
/>
<button @click="searchUser">Search</button>
</div>
</section>
</template>
<script>
import axios from "axios";
export default {
name: "Search",
data() {
return {
keyWord: '',
};
},
methods: {
searchUser() {
//请求前更新list数据
this.$bus.$emit("updateList",{isFirst:false,isloading:true,errorMsg:'',users:[]});
axios.get(`https://api.github.com/search/users?q=${this.keyWord}`).then(
(response) => {
console.log("请求成功");
//请求成功后
this.$bus.$emit("updateList",{isloading:false,errorMsg:'',users:response.data.items});
},
(error) => {
console.log("请求失败");
//请求失败后
this.$bus.$emit("updateList",{isloading:false,errorMsg:error.message,users:[]});
}
);
},
},
};
</script>
<style>
</style>
在search.vue的更改部分
// axios.get(`https://api.github.com/search/users?q=${this.keyWord}`).then(
this.$http.get(`https://api.github.com/search/users?q=${this.keyWord}`).then(
(response) => {...
在main.js部分
import Vue from 'vue'
import App from './App.vue'
import vueResource from 'vue-resource'
Vue.config.productionTip = false
Vue.config.productionTip=false
Vue.use(vueResource)
new Vue({
render: h => h(App),
beforeCreate(){
//安装全局事件总线
Vue.prototype.$bus=this
}
}).$mount('#app')
app中的子组件的内容都是先在app中解析,再放到子组件中(category.vue)
//app.vue
<template>
<div class="container">
<Category title="美食" >
<img src="./assets/monkey.png" alt="">
</Category>
<Category title="书籍" >
<ul>
<li v-for="(g,index) in books" :key="index">{{ g }}</li>
</ul>
</Category>
<Category title="城市" >
<video controls src="./vedio/1.mp4"></video>
</Category>
</div>
</template>
<script>
import Category from ".//components/Category.vue";
export default {
name: "App",
components: {
Category,
},
data(){
return {
foods:['包子','豆奶','蛋糕'],
books:['a书','b书','c书'],
cities:['徐州','铜山','鼓楼']
}
}
};
</script>
<style>
.container{
display: flex;
}
</style>
//category.vue
<template>
<div class="category">
<h3>{{ title }}分类</h3>
<slot></slot>
</div>
</template>
<script>
export default {
name: "Category",
props:['title'],
};
</script>
<style>
.category {
text-align: center;
background-color: rgb(187, 245, 245);
width: 200px;
height: 300px;
margin-right: 15px;
}
h3 {
text-align: center;
background-color: orange;
}
video{
width: 100px;
height: 200px;
}
</style>
一种是
slot=' '
另一种是v-slot=' '
(只能在template标签上使用)
//app.vue
<template>
<div class="container">
<Category title="美食" >
<img slot="1" src="./assets/monkey.png" alt="">
<a href="#" slot="3">更多美食...</a>
<p slot="2">~~~~~~~</p>
</Category>
<Category title="书籍" >
<ul slot="2">
<li v-for="(b,index) in books" :key="index">{{ b }}</li>
</ul>
<p slot="1">~~~~~~~</p>
<a href="#" slot="3">更多书籍...</a>
</Category>
</div>
</template>
<script>
import Category from ".//components/Category.vue";
export default {
name: "App",
components: {
Category,
},
data(){
return {
foods:['包子','豆奶','蛋糕'],
books:['a书','b书','c书'],
cities:['徐州','铜山','鼓楼']
}
}
};
</script>
<style>
.container{
display: flex;
}
</style>
//category.vue
<template>
<div class="category">
<h3>{{ title }}分类</h3>
<slot name="1"></slot>
<slot name="2"></slot>
<slot name="3"></slot>
</div>
</template>
<script>
export default {
name: "Category",
props:['title'],
};
</script>
<style>
.category {
text-align: center;
background-color: rgb(244, 216, 187);
width: 200px;
height: 300px;
margin-right: 15px;
}
h3 {
text-align: center;
background-color: orange;
}
video{
width: 100px;
height: 200px;
}
</style>
//count.vue
<template>
<div>
<h2>当前和为{{ sum }}</h2>
<select v-model="n">
<!-- 注意要给value前加上:否则将是字符串形式 -->
<option :value="1">n=1</option>
<option :value="2">n=2</option>
<option :value="3">n=3</option>
</select>
<button @click="rise">+n</button>
<button @click="down">-n</button>
<button @click="odd">sum为奇数时+n</button>
<button @click="delay">延迟1秒+n</button>
</div>
</template>
<script>
export default {
name: "Count",
data() {
return {
sum: 0,
n: 1,//当前要加的数字
};
},
methods: {
rise() {
this.sum+=this.n
},
down() {
this.sum-=this.n
},
odd() {
if(this.sum%2){
this.sum+=this.n
}
},
delay() {
setTimeout(()=>{
this.sum+=this.n
},500)
},
},
};
</script>
<style>
</style>
引入项目时,注意顺序,所有import都要比js中的源代码,先执行
报错:vuex要在store之前引入
按如下代码写,即可解决问题
// src/main.js
import Vue from 'vue'
import App from './App.vue'
import store from './store/index'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
store,
}).$mount('#app')
// console.log(vm)
// src/store/index.js
//创建Vuex的核心store
//引入Vuex
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
//创建actions对象 用于响应组件中的动作
const actions={}
//创建mutations对象,用于存储对象
const mutations={}
//准备state用于存储数据
const state={}
//创建store
export default new Vuex.Store({
// actions:actions
//重名可以省略
actions,
mutations,
state
})
//暴露store
// export default store
const actions={
//配置与count组件中对应的add
// add:function(){
add(context,value){
console.log('因为rise被点击了,所有actions上的add被触发了',context,value)
//上下文对象
// context.commit('add',value)
}
}
// count.vue
<template>
<div>
<h2>当前和为{{ $store.state.sum }}</h2>
<select v-model="n">
<!-- 注意要给value前加上:否则将是字符串形式 -->
<option :value="1">n=1</option>
<option :value="2">n=2</option>
<option :value="3">n=3</option>
</select>
<button @click="rise">+n</button>
<button @click="down">-n</button>
<button @click="odd">sum为奇数时+n</button>
<button @click="delay">延迟1秒+n</button>
</div>
</template>
<script>
export default {
name: "Count",
data() {
return {
n: 1,//当前要加的数字
};
},
methods: {
rise() {
// this.sum+=this.n
this.$store.dispatch('add',this.n)
},
down() {
// this.sum-=this.n
this.$store.dispatch('cut',this.n)
},
odd() {
if(this.$store.state.sum%2){
// this.sum+=this.n
this.$store.dispatch('add',this.n)
}
},
delay() {
setTimeout(()=>{
// this.sum+=this.n
this.$store.dispatch('add',this.n)
},500)
},
},
};
</script>
<style>
</style>
// store/index.js
//创建Vuex的核心store
//引入Vuex
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
//创建actions对象 用于响应组件中的动作
const actions={
//配置与count组件中对应的add
// add:function(){
add(context,value){
// console.log('因为rise被点击了,所有actions上的add被触发了',context,value)
//上下文对象
context.commit('ADD',value)
},
cut(a,b){
a.commit('CUT',b)
},
}
//创建mutations对象,用于存储对象
const mutations={
ADD(state,value){
// console.log('mutations上的add被触发了',states,b)
state.sum+=value
},
CUT(c,d){
c.sum-=d
}
}
//准备state用于存储数据
const state={
sum: 11,
}
//创建store
export default new Vuex.Store({
// actions:actions
//重名可以省略
actions,
mutations,
state
})
//暴露store
// export default store
另一版
//index.js
//创建Vuex的核心store
//引入Vuex
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
//创建actions对象 用于响应组件中的动作
const actions = {
//配置与count组件中对应的add
// add:function(){
add(context, value) {
// console.log('因为rise被点击了,所有actions上的add被触发了',context,value)
//上下文对象
context.commit('ADD', value)
},
cut(a, b) {
a.commit('CUT', b)
},
addOdd(a, b) {
a.commit('ADDODD', b)
},
addDelay(a, b) {
a.commit('ADDDELAY', b)
}
}
//创建mutations对象,用于存储对象
const mutations = {
ADD(state, value) {
// console.log('mutations上的add被触发了',states,b)
state.sum += value
},
CUT(c, d) {
c.sum -= d
},
ADDODD(c, d) {
if (c.sum % 2) {
c.sum += d
}
},
ADDDELAY(e, f) {
setTimeout(()=>{
e.sum += f
},500)
}
}
//准备state用于存储数据
const state = {
sum: 11,
}
//创建store
export default new Vuex.Store({
// actions:actions
//重名可以省略
actions,
mutations,
state
})
//暴露store
// export default store
//count.vue
<template>
<div>
<h2>当前和为{{ $store.state.sum }}</h2>
<select v-model="n">
<!-- 注意要给value前加上:否则将是字符串形式 -->
<option :value="1">n=1</option>
<option :value="2">n=2</option>
<option :value="3">n=3</option>
</select>
<button @click="rise">+n</button>
<button @click="down">-n</button>
<button @click="odd">sum为奇数时+n</button>
<button @click="delay">延迟1秒+n</button>
</div>
</template>
<script>
export default {
name: "Count",
data() {
return {
n: 1,//当前要加的数字
};
},
methods: {
rise() {
// this.sum+=this.n
this.$store.dispatch('add',this.n)
},
down() {
// this.sum-=this.n
this.$store.dispatch('cut',this.n)
},
odd() {
// if(this.$store.state.sum%2){
// // this.sum+=this.n
// this.$store.dispatch('add',this.n)
// }
this.$store.dispatch('addOdd',this.n)
},
delay() {
// setTimeout(()=>{
// // this.sum+=this.n
// this.$store.dispatch('add',this.n)
// },500)
this.$store.dispatch('addDelay',this.n)
},
},
};
</script>
<style>
</style>
把业务逻辑写在actions中更好
//创建Vuex的核心store
//引入Vuex
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
//创建actions对象 用于响应组件中的动作
const actions = {
//配置与count组件中对应的add
// add:function(){
add(context, value) {
// console.log('因为rise被点击了,所有actions上的add被触发了',context,value)
//上下文对象
context.commit('ADD', value)
},
cut(a, b) {
a.commit('CUT', b)
},
addOdd(a, b) {
if (a.state.sum % 2) {
a.commit('ADDODD', b)
}
},
addDelay(a, b) {
setTimeout(() => {
a.commit('ADDDELAY', b)
}, 500)
}
}
//创建mutations对象,用于存储对象
const mutations = {
ADD(state, value) {
// console.log('mutations上的add被触发了',states,b)
state.sum += value
},
CUT(c, d) {
c.sum -= d
},
ADDODD(c, d) {
c.sum += d
},
ADDDELAY(e, f) {
e.sum += f
}
}
//准备state用于存储数据
const state = {
sum: 11,
}
//创建store
export default new Vuex.Store({
// actions:actions
//重名可以省略
actions,
mutations,
state
})
//暴露store
// export default store
业务逻辑没有的,就不写dispatch,直接写mutations。
<template>
<div>
<h2>当前和为{{ $store.state.sum }}</h2>
<select v-model="n">
<!-- 注意要给value前加上:否则将是字符串形式 -->
<option :value="1">n=1</option>
<option :value="2">n=2</option>
<option :value="3">n=3</option>
</select>
<button @click="rise">+n</button>
<button @click="down">-n</button>
<button @click="odd">sum为奇数时+n</button>
<button @click="delay">延迟1秒+n</button>
</div>
</template>
<script>
export default {
name: "Count",
data() {
return {
n: 1,//当前要加的数字
};
},
methods: {
rise() {
// this.$store.dispatch('add',this.n)
this.$store.commit('ADD',this.n)
},
down() {
// this.$store.dispatch('cut',this.n)
this.$store.commit('CUT',this.n)
},
odd() {
// if(this.$store.state.sum%2){
// // this.sum+=this.n
// this.$store.dispatch('add',this.n)
// }
this.$store.dispatch('addOdd',this.n)
},
delay() {
// setTimeout(()=>{
// // this.sum+=this.n
// this.$store.dispatch('add',this.n)
// },500)
this.$store.dispatch('addDelay',this.n)
},
},
};
</script>
<style>
</style>
//index.js
//创建Vuex的核心store
//引入Vuex
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
//创建actions对象 用于响应组件中的动作
const actions = {
//配置与count组件中对应的add
// add:function(){
addOdd(a, b) {
if (a.state.sum % 2) {
a.commit('ADDODD', b)
}
},
addDelay(a, b) {
setTimeout(() => {
a.commit('ADDDELAY', b)
}, 500)
}
}
//创建mutations对象,用于存储对象
const mutations = {
ADD(state, value) {
// console.log('mutations上的add被触发了',states,b)
state.sum += value
},
CUT(c, d) {
c.sum -= d
},
ADDODD(c, d) {
c.sum += d
},
ADDDELAY(e, f) {
e.sum += f
}
}
//准备state用于存储数据
const state = {
sum: 11,
}
//创建store
export default new Vuex.Store({
// actions:actions
//重名可以省略
actions,
mutations,
state
})
//暴露store
// export default store
//index.js
//创建Vuex的核心store
//引入Vuex
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
//创建mutations对象,用于存储对象
const mutations = {
ADD_PERSON(state, personObj) {
state.personList.unshift(personObj)
}
}
//准备state用于存储数据
const state = {
sum: 0,
personList: [
{ id: '001', name: 'lucy' }
]
}
//创建store
export default new Vuex.Store({
// actions:actions
//重名可以省略
mutations,
state,
})
//暴露store
// export default store
//Person.vue
<template>
<div>
<h2>人员列表</h2>
<input type="text" v-model="name" placeholder="请输入名字" />
<button @click="add">添加</button>
<ul>
<!-- <li v-for="p in $store.state.personList" :key="p.id">*****</li> -->
<li v-for="p in personList" :key="p.id">{{ p.name }}</li>
</ul>
</div>
</template>
<script>
import { nanoid } from "nanoid";
export default {
name: "Person",
computed: {
personList() {
return this.$store.state.personList;
},
},
data() {
return {
name: "",
};
},
methods: {
add() {
const personObj = { id: nanoid(), name: this.name };
this.$store.commit("ADD_PERSON", personObj);
this.name = "";
},
},
};
</script>
//count.vue
<template>
<div style="color:red">下方组件的总人数是{{ personList.length }}</div>
</template>
<script>
import { mapState } from "vuex";
export default {
name: "Count",
computed: {
...mapState(["personList"]),
},
};
</script>
hhhhjjjjLMalscjmdlk
vue的一个插件库
key-value
路径-组件
使用vue2只能安装vue-router@3
使用vue3只能安装vue-router@4
- 在
src\router\index.js
路径下创建路由
//该文件专门用于创建整个应用的路由
import VueRouter from "vue-router";
import About from '../components/About.vue'
import Home from '../components/Home.vue'
//创建一个路由
export default new VueRouter({
routes:[
{
path:'/about',
component:About
},
{
path:'/home',
component:Home
}
]
})
- 在
src\main.js
下应用路由插件,加入路由配置项
import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router'
//引入路由器
import router from './router/index'
Vue.config.productionTip = false
Vue.use(VueRouter)
new Vue({
render: h => h(App),
router:router
}).$mount('#app')
- 在
src\App.vue
下,实现切换(active-class
),展示指定位置(router-view
)
<router-link class="list-group-item" active-class="active" to="/about">About</router-link>
<router-link class="list-group-item" active-class="active" to="/home">Home</router-link>
<router-view></router-view>
整体视图
*注意点
//该文件专门用于创建整个应用的路由
import VueRouter from "vue-router";
import About from '../pages/About.vue'
import Home from '../pages/Home.vue'
import Message from '../pages/Message.vue'
import News from '../pages/News.vue'
//创建一个路由
export default new VueRouter({
routes:[
{
path:'/about',
component:About
},
{
path:'/home',
component:Home,
//二级路由
children:[
{
//不加 / 符号
path:'news',
component:News
},
{
path:'message',
component:Message
},
]
}
]
})
// src/pages/Home.vue
<template>
<div>
<ul class="nav nav-tabs">
<li>
<router-link class="list-group-item" active-class="active" to="/home/news" href="./home-news.html">News</router-link>
</li>
<li>
<router-link class="list-group-item" active-class="active" to="/home/message" href="./home-message.html">Message</router-link>
</li>
</ul>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: "Home",
};
</script>
<style>
</style>
query参数
//字符串写法
<router-link :to="`/home/message/detail?id=${m.id}&title=${m.title}`">{{ m.title }}</router-link>
//对象写法
<router-link :to="{
path:'/home/message/detail',
query:{
id:m.id,
title:m.title
}
}">
{{ m.title }}
</router-link>
接受参数
<template>
<ul>
<li>消息编号{{$route.query.id}}</li>
消息详情{{ $route.query.title }}
</ul>
</template>
<script>
export default {
name:'Detail'
}
</script>
//D:\web\practice\route\src\pages\Message.vue
<template>
<div>
<ul>
<li v-for="m in messageList" :key="m.id">
<!-- <router-link :to="`/home/message/detail?id=${m.id}&title=${m.title}`">{{ m.title }}</router-link> -->
<router-link :to="{
// path:'/home/message/detail',
name:'xiangqing',
query:{
id:m.id,
title:m.title
}
}">
{{ m.title }}
</router-link>
</li>
</ul>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: "Message",
data() {
return {
messageList: [
{ id: 1, title: "消息001" },
{ id: 2, title: "消息002" },
{ id: 3, title: "消息003" },
],
};
},
};
</script>
//D:\web\practice\route\src\pages\Detail.vue
<template>
<ul>
<li>消息编号:{{id}}</li>
消息详情:{{ title }}
</ul>
</template>
<script>
export default {
name:'Detail',
props:['title','id'],
}
</script>
<style>
</style>
//D:\web\practice\route\src\router\index.js
//该文件专门用于创建整个应用的路由
import VueRouter from "vue-router";
import About from '../pages/About.vue'
import Home from '../pages/Home.vue'
import Message from '../pages/Message.vue'
import News from '../pages/News.vue'
import Detail from '../pages/Detail'
//创建一个路由
export default new VueRouter({
routes:[
{
name:'guanyu',
path:'/about',
component:About
},
{
path:'/home',
component:Home,
//二级路由
children:[
{
//不加 / 符号
path:'news',
component:News
},
{
path:'message',
component:Message,
children:[
{
name:'xiangqing',
path:'detail',
component:Detail,
// 回调函数,定义了不调用,却执行了
props($route){
return {
id:$route.query.id,
title:$route.query.title
}
}
}
]
},
]
}
]
})
更简便的写法——利用解构赋值
对历史记录的操作
//route\src\components\Banner.vue
<template>
<div class="col-xs-offset-2 col-xs-8">
<div class="page-header">
<h2>Vue Router Demo</h2>
<button @click="back">后退</button>
<button @click="forward">前进</button>
<button @click="go">跳转指定步数</button>
</div>
</div>
</template>
<script>
export default {
name: "Banner",
methods: {
back() {
this.$router.back({});
},
forward() {
this.$router.forward({});
},
go() {
this.$router.go(-2)
},
},
}
</script>
<style>
</style>
//route\src\pages\Message.vue
<template>
<div>
<ul>
<li v-for="m in messageList" :key="m.id">
<!-- <router-link :to="`/home/message/detail?id=${m.id}&title=${m.title}`">{{ m.title }}</router-link> -->
<router-link :to="{
// path:'/home/message/detail',
name:'xiangqing',
query:{
id:m.id,
title:m.title
}
}">
{{ m.title }}
</router-link>
<button @click="pushShow(m)">push</button>
<button @click="replaceShow(m)">replace</button>
</li>
</ul>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: "Message",
methods:{
pushShow(m){
this.$router.push({
name:'xiangqing',
query:{
id:m.id,
title:m.title
}
})
},
replaceShow(m){
this.$router.replace({
name:'xiangqing',
query:{
id:m.id,
title:m.title
}
})
}
},
data() {
return {
messageList: [
{ id: 1, title: "消息001" },
{ id: 2, title: "消息002" },
{ id: 3, title: "消息003" },
],
};
},
};
</script>
<style>
</style>
include里是组件名
//route\src\pages\Home.vue
<keep-alive include="News">
<router-view></router-view>
</keep-alive>
activated 激活
deactivated 失活
现存问题:希望跳转时后,缓存输入框信息,并且,可以停掉计时器
//route\src\pages\News.vue
<template>
<div>
<ul>
<h3 :style="{ opacity }">欢迎学习vue</h3>
<li>news001 <input type="text" /></li>
<li>news002 <input type="text" /></li>
<li>news003 <input type="text" /></li>
</ul>
</div>
</template>
<script>
export default {
name: "News",
data() {
return {
opacity: 1,
};
},
mounted() {
this.timer = setInterval(() => {
this.opacity -= 0.01;
if (this.opacity <= 0) this.opacity = 1;
}, 10);
},
beforeDestroy() {
clearInterval(this.timer);
},
};
</script>
activated() {
this.timer = setInterval(() => {
this.opacity -= 0.01;
console.log('A')
if (this.opacity <= 0) this.opacity = 1;
}, 10);
},
deactivated() {
clearInterval(this.timer);
},
权限问题
// route\src\router\index.js
//该文件专门用于创建整个应用的路由
import VueRouter from "vue-router";
import About from '../pages/About.vue'
import Home from '../pages/Home.vue'
import Message from '../pages/Message.vue'
import News from '../pages/News.vue'
import Detail from '../pages/Detail'
//创建一个路由
const router=new VueRouter({
routes:[
{
name:'guanyu',
path:'/about',
component:About
},
{
name:'zhuye',
path:'/home',
component:Home,
//二级路由
children:[
{
name:'xinwen',
//不加 / 符号
path:'news',
component:News
},
{
name:'xiaoxi',
path:'message',
component:Message,
children:[
{
name:'xiangqing',
path:'detail',
component:Detail,
//加强版,解构赋值
props({query:{id,title}}){
return {
id,title
}
}
}
]
},
]
}
]
})
//全局前置路由守卫
//在切换之前,调用下方函数
router.beforeEach((to,from,next)=>{
console.log(to,from)
next()
})
// 改变路由器暴露方式
export default router
设置权限
// route\src\router\index.js
router.beforeEach((to,from,next)=>{
if(localStorage.getItem('user')==='fang'){
next() //放权
}
})
给指定路径加权限
//该文件专门用于创建整个应用的路由
import VueRouter from "vue-router";
import About from '../pages/About.vue'
import Home from '../pages/Home.vue'
import Message from '../pages/Message.vue'
import News from '../pages/News.vue'
import Detail from '../pages/Detail'
//创建一个路由
const router=new VueRouter({
routes:[
{
name:'guanyu',
path:'/about',
component:About
},
{
name:'zhuye',
path:'/home',
component:Home,
//二级路由
children:[
{
name:'xinwen',
//不加 / 符号
path:'news',
component:News
},
{
name:'xiaoxi',
path:'message',
component:Message,
children:[
{
name:'xiangqing',
path:'detail',
component:Detail,
//加强版,解构赋值
props({query:{id,title}}){
return {
id,title
}
}
}
]
},
]
}
]
})
//全局前置路由守卫
//在切换之前,调用下方函数
router.beforeEach((to,from,next)=>{
if(to.path==='/home/news'||to.path==='/home/message'){
if(localStorage.getItem('user')==='fang'){
next() //放权
}else{
alert('您不是主人,没有权限进入/home/message及/home/news页面')
}
}else{
next()
}
})
export default router
简化写法
使用meta路由元信息
//该文件专门用于创建整个应用的路由
import VueRouter from "vue-router";
import About from '../pages/About.vue'
import Home from '../pages/Home.vue'
import Message from '../pages/Message.vue'
import News from '../pages/News.vue'
import Detail from '../pages/Detail'
//创建一个路由
const router=new VueRouter({
routes:[
{
name:'guanyu',
path:'/about',
component:About
},
{
name:'zhuye',
path:'/home',
component:Home,
//二级路由
children:[
{
name:'xinwen',
//不加 / 符号
path:'news',
component:News,
//不要权限即可进入
meta:{isAuth:false}
},
{
//不要权限即可进入
meta:{isAuth:false},
name:'xiaoxi',
path:'message',
component:Message,
children:[
{
//需要权限才可以看到
meta:{isAuth:true},
name:'xiangqing',
path:'detail',
component:Detail,
//加强版,解构赋值
props({query:{id,title}}){
return {
id,title
}
}
}
]
},
]
}
]
})
//全局前置路由守卫
//在切换之前,调用下方函数
router.beforeEach((to,from,next)=>{
if(to.meta.isAuth){
if(localStorage.getItem('user')==='fang'){
next() //放权
}else{
alert('您没有权限进入详情页')
}
}else{
next()
}
})
export default router
只有两个参数
给每个路由一个对应的title标题
//该文件专门用于创建整个应用的路由
import VueRouter from "vue-router";
import About from '../pages/About.vue'
import Home from '../pages/Home.vue'
import Message from '../pages/Message.vue'
import News from '../pages/News.vue'
import Detail from '../pages/Detail'
//创建一个路由
const router=new VueRouter({
routes:[
{
name:'guanyu',
path:'/about',
component:About,
meta:{title:'关于'}
},
{
meta:{title:'主页'},
name:'zhuye',
path:'/home',
component:Home,
//二级路由
children:[
{
meta:{title:'新闻'},
name:'xinwen',
//不加 / 符号
path:'news',
component:News,
},
{
//不要权限即可进入
meta:{
title:'消息',
isAuth:false
},
name:'xiaoxi',
path:'message',
component:Message,
children:[
{
//需要权限才可以看到
meta:{
isAuth:true,
title:'详情'
},
name:'xiangqing',
path:'detail',
component:Detail,
//加强版,解构赋值
props({query:{id,title}}){
return {
id,title
}
}
}
]
},
]
}
]
})
//全局前置路由守卫
//在切换之前,调用下方函数
router.beforeEach((to,from,next)=>{
document.title=to.meta.title
if(to.meta.isAuth){
if(localStorage.getItem('user')==='fang'){
next() //放权
}else{
alert('您没有权限进入详情页')
}
}else{
next()
}
})
export default router
优化后
//该文件专门用于创建整个应用的路由
import VueRouter from "vue-router";
import About from '../pages/About.vue'
import Home from '../pages/Home.vue'
import Message from '../pages/Message.vue'
import News from '../pages/News.vue'
import Detail from '../pages/Detail'
//创建一个路由
const router=new VueRouter({
routes:[
{
name:'guanyu',
path:'/about',
component:About,
meta:{title:'关于'}
},
{
meta:{title:'主页'},
name:'zhuye',
path:'/home',
component:Home,
//二级路由
children:[
{
meta:{title:'新闻'},
name:'xinwen',
//不加 / 符号
path:'news',
component:News,
},
{
//不要权限即可进入
meta:{
title:'消息',
isAuth:false
},
name:'xiaoxi',
path:'message',
component:Message,
children:[
{
//需要权限才可以看到
meta:{
isAuth:true,
title:'详情'
},
name:'xiangqing',
path:'detail',
component:Detail,
//加强版,解构赋值
props({query:{id,title}}){
return {
id,title
}
}
}
]
},
]
}
]
})
//全局前置路由守卫
//在切换之前,调用下方函数
router.beforeEach((to,from,next)=>{
if(to.meta.isAuth){
//判断是否需要鉴权
if(localStorage.getItem('user')==='fang'){
next() //放权
}else{
alert('您没有权限进入详情页')
}
}else{
next()
}
})
router.afterEach((to,from)=>{
document.title=to.meta.title||'route'
})
export default router
只对新闻做限制
//该文件专门用于创建整个应用的路由
import VueRouter from "vue-router";
import About from '../pages/About.vue'
import Home from '../pages/Home.vue'
import Message from '../pages/Message.vue'
import News from '../pages/News.vue'
import Detail from '../pages/Detail'
//创建一个路由
const router = new VueRouter({
routes: [
{
name: 'guanyu',
path: '/about',
component: About,
meta: { title: '关于' }
},
{
meta: { title: '主页' },
name: 'zhuye',
path: '/home',
component: Home,
//二级路由
children: [
{
//需要权限才可以看到
meta: {
isAuth: true,
title: '新闻',
},
name: 'xinwen',
path: 'news',
component: News,
beforeEnter: (to, from, next) => {
if (to.meta.isAuth) {
//判断是否需要鉴权
if (localStorage.getItem('user') === 'fang') {
next() //放权
} else {
alert('您没有权限进入详情页')
}
} else {
next()
}
}
},
{
//不要权限即可进入
meta: { title: '消息'},
name: 'xiaoxi',
path: 'message',
component: Message,
children: [
{
meta: {title: '详情'},
name: 'xiangqing',
path: 'detail',
component: Detail,
//加强版,解构赋值
props({ query: { id, title } }) {
return {
id, title
}
}
}
]
},
]
}
]
})
router.afterEach((to, from) => {
document.title=to.meta.title||'route'
})
export default router
没有前置后置,==只有 通过路由规则(也就是通过路由组件。而非一般组件)==进入、离开该组件
// route\src\pages\About.vue
<template>
<div>我是About的内容</div>
</template>
<script>
export default {
name: "About",
beforeRouteEnter(to, from, next) {
if (to.meta.isAuth) {
//判断是否需要鉴权
if (localStorage.getItem("user") === "fang") {
next(); //放权
} else {
alert("您没有权限进入about页");
}
} else {
next();
}
},
beforeRouteLeave(to, from, next) {
next();
},
};
</script>
<style>
</style>
// route\src\router\index.js
//该文件专门用于创建整个应用的路由
import VueRouter from "vue-router";
import About from '../pages/About.vue'
import Home from '../pages/Home.vue'
import Message from '../pages/Message.vue'
import News from '../pages/News.vue'
import Detail from '../pages/Detail'
//创建一个路由
const router = new VueRouter({
routes: [
{
name: 'guanyu',
path: '/about',
component: About,
meta:
{
title: '关于',
isAuth: true,
}
},
{
meta: { title: '主页' },
name: 'zhuye',
path: '/home',
component: Home,
//二级路由
children: [
{
meta: {title: '新闻',},
name: 'xinwen',
path: 'news',
component: News,
},
{
meta: { title: '消息'},
name: 'xiaoxi',
path: 'message',
component: Message,
children: [
{
meta: {title: '详情'},
name: 'xiangqing',
path: 'detail',
component: Detail,
//加强版,解构赋值
props({ query: { id, title } }) {
return {
id, title
}
}
}
]
},
]
}
]
})
router.afterEach((to, from) => {
document.title=to.meta.title||'route'
})
export default router
离开时
beforeRouteLeave(to, from, next) {
//不写以下代码则无法出去此页面
// next();
},
默认为hash
const router = new VueRouter({
mode:'hash',
- hash的兼容性好
- 上线问题
打包后的必须要放到服务器上部署
// route_node\server.js
//引入express
const express = require('express')
//创建app服务实例对象
const app = express()
//配置后端路由
app.get('/person', (request, response) => {
//给客户端返回消息
response.send({
name: 'fang',
age: 18
})
})
//端口监听
app.listen(5005, (err) => {
if (!err)
console.log('服务器启动了')
})
把刚刚
npm run build
的文件,打包放入route_node\static
在
route_node\static
加上下行代码
app.use(express.static(__dirname+'/static'))
因为是hash模式,所以后面的不会带给服务器,服务器指定的是/person路径
用history模式也可以,
在刷新完,出现404问题后
需要后端进行相关处理
// elementt\src\main.js
import Vue from 'vue'
//引入element-ui组件库
import ElementUI from 'element-ui';
//引入ElentUI全部样式
import 'element-ui/lib/theme-chalk/index.css';
import App from './App.vue'
//应用ElementUI,且是全局注册
Vue.use(ElementUI);
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
<template>
<div>
<button>原生的按钮</button>
<hr />
<h3>引入的按钮</h3>
<el-row>
<el-button plain>朴素按钮</el-button>
<el-button type="primary" plain>主要按钮</el-button>
<el-button type="success" plain>成功按钮</el-button>
<el-button type="info" plain>信息按钮</el-button>
<el-button type="warning" plain>警告按钮</el-button>
<el-button type="danger" plain>危险按钮</el-button>
</el-row>
</div>
</template>
<script>
export default {
name: "App",
};
</script>
// elementt\babel.config.js
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset',
//两种写法都可以
// ["es2015", { "modules": false }]
["@babel/preset-env", { "modules": false }]
],
"plugins": [
[
"component",
{
"libraryName": "element-ui",
"styleLibraryName": "theme-chalk"
}
]
]
}
报错
在elementt\src\App.vue
中加入import Vue from "vue";
// elementt\src\App.vue
<template>
<div>
<el-row>
<el-button icon="el-icon-search" circle></el-button>
<el-button type="primary" icon="el-icon-edit" circle></el-button>
<el-button type="success" icon="el-icon-check" circle></el-button>
<el-button type="info" icon="el-icon-message" circle></el-button>
<el-button type="warning" icon="el-icon-star-off" circle></el-button>
<el-button type="danger" icon="el-icon-delete" circle></el-button>
</el-row>
</div>
</template>
<script>
import Vue from "vue";
import { Button, Row } from "element-ui";
Vue.component("el-button", Button);
Vue.component("el-row", Row);
export default {
name: "App",
};
</script>
相比于脚手架,不需要new了
记得添加vue.config.js文件,并加上
lintOnSave:false
返回值是对象
// test\src\App.vue
<template>
<div>
<h2>一个人的信息</h2>
姓名:{{ name }}
<button @click="sayHello">说话</button>
</div>
</template>
<script>
export default {
name: "App",
setup() {
let name = "lucy";
function sayHello() {
alert(`你好,${name}`);
}
return {
name,
sayHello,
};
},
};
</script>
<template>
<div>
<h2>一个人的信息</h2>
姓名:{{ name }}
<button @click="sayHello">说话</button>
</div>
</template>
<script>
import { h } from 'vue';
export default {
name: "App",
setup() {
let name = "lucy";
function sayHello() {
alert(`你好,${name}`);
}
return ()=>{
//渲染函数有返回值
//返回h的调用结果
return h('h2',"学校")
}
},
};
</script>
简写
return ()=>h('h2',"学校")
向vue2兼容,但不推荐混用
如有重名,setup优先
setup收到的参数(props,context)
props
传了没接收会有警告(但是在vue2中不会有警告)
// test\src\App.vue
<template>
<Demo @fang="showInfo"></Demo>
</template>
<script>
import Demo from "./components/Demo.vue";
export default {
name: "App",
setup() {
function showInfo() {
alert("hello");
}
return {
showInfo,
};
},
components: { Demo },
};
</script>
// test\src\components\Demo.vue
<template>
<button @click="test">触发Demo组件上的fang事件</button>
</template>
<script>
export default {
name: "Demo",
emits:['fang'],
setup(a,context) {
function test() {
console.log('aaa')
context.emit('fang')
}
return {
test,
};
},
};
</script>
<template>
<div>
<button @click="test">触发Demo组件上的fang事件</button>
<br>
<slot name='hai'></slot>
</div>
</template>
<script>
export default {
name: "Demo",
emits:['fang'],
setup(a,context) {
function test() {
console.log(context.slots)
context.emit('fang')
}
return {
test,
};
},
};
</script>
<template>
<Demo @fang="showInfo">
<template v-slot:hai>
<span>haihaihai</span>
</template>
</Demo>
</template>
<script>
import Demo from "./components/Demo.vue";
export default {
name: "App",
setup() {
function showInfo() {
alert("hello");
}
return {
showInfo,
};
},
components: { Demo },
};
</script>
<template>
<div>
<h2>一个人的信息</h2>
姓名:{{ name }}
<button @click="changeInfo">改变信息</button>
</div>
</template>
<script>
import {ref} from 'vue'
export default {
name: "App",
setup() {
//普通变量
// let name = "lucy";
//响应式——通过ref
let name=ref('lucy')
function changeInfo(){
name.value='jack'
}
return {
name,
changeInfo
};
},
};
</script>
在模板中不需要
.value
,解析时,会自动添加
<template>
<div>
<h2>一个人的信息<button @click="changeInfo">改变信息</button></h2>
姓名:{{ name }}
<br>
工作职位:{{ job.type }}
<br>
工作薪水:{{ job.salary }}
</div>
</template>
<script>
import {ref} from 'vue'
export default {
name: "App",
setup() {
//普通变量
// let name = "lucy";
//响应式——通过ref
let name=ref('lucy')
let job=ref({
type:'前端',
salary:'10k'
})
function changeInfo(){
name.value='jack',
// job.type.value='后端'//错误写法
job.value.type='后端'
job.value.salary='11k'
}
return {
name,
job,
changeInfo
};
},
};
</script>
要先引入
<template>
<div>
<h2>一个人的信息<button @click="changeInfo">改变信息</button></h2>
姓名:{{ name }}
<br>
工作职位:{{ job.type }}
<br>
工作薪水:{{ job.salary }}
</div>
</template>
<script>
import {ref,reactive} from 'vue'
export default {
name: "App",
setup() {
let name=ref('lucy')
let job=reactive({
type:'前端',
salary:'10k'
})
function changeInfo(){
name.value='jack',
//使用reactive得到了简化
job.type='后端'
job.salary='11k'
}
return {
name,
job,
changeInfo
};
},
};
</script>
监测深层对象
<template>
<div>
<h2>c的值:{{ a.b.c }}</h2>
</div>
</template>
<script>
import {ref,reactive} from 'vue'
export default {
name: "App",
setup() {
let name=ref('lucy')
let a=reactive({
b:{
c:'找到了'
},
d:'1'
})
return {
name,
a,
};
},
};
</script>
<template>
<div>
<h2>{{ number }}</h2>
<button @click="change">更改数组</button>
</div>
</template>
<script>
import { ref, reactive } from "vue";
export default {
name: "App",
setup() {
let number = reactive([1, 2, 3]);
function change() {
number[0] = 5;
}
return {
number,
change,
};
},
};
</script>
测试新增与删除属性
<template>
<div>
<h2>姓名:{{person.name}}</h2>
<h2>年龄:{{person.age}}</h2>
<h2 v-show="person.sex">性别:{{person.sex}}</h2>
<button @click="add">新增信息</button>
<button @click="del">删除信息</button>
</div>
</template>
<script>
import { reactive } from "vue";
export default {
name: "App",
setup() {
let person=reactive({
name:'lucy',
age:18,
})
function add(){
person.sex='女'
}
function del(){
// person.sex=''
delete person.sex
}
return {
person,
add,
del
};
},
};
</script>
方法一(vue2)
<template>
<div>
<h2>个人信息</h2>
姓:<input type="text" v-model="person.surName" />
<br />
名:<input type="text" v-model="person.lastName" />
<br>
全名:{{ fullName }}
</div>
</template>
<script>
import { reactive } from "vue";
export default {
name: "Demo",
setup() {
let person = reactive({
surName: "张",
lastName: "三",
});
return {
person,
};
},
computed:{
fullName(){
return this.person.surName+'-'+this.person.lastName
}
}
};
</script>
vue3写法
<template>
<div>
<h2>个人信息</h2>
姓:<input type="text" v-model="person.surName" />
<br />
名:<input type="text" v-model="person.lastName" />
<br />
全名:{{ fullName }}
</div>
</template>
<script>
import { reactive, computed } from "vue";
export default {
name: "Demo",
setup() {
let person = reactive({
surName: "张",
lastName: "三",
});
let fullName = computed(() => {
return person.surName + "-" + person.lastName;
});
return {
person,
fullName,
};
},
};
</script>
简写
<template>
<div>
<h2>个人信息</h2>
姓:<input type="text" v-model="person.surName" />
<br />
名:<input type="text" v-model="person.lastName" />
<br />
全名:{{ person.fullName }}
</div>
</template>
<script>
import { reactive, computed } from "vue";
export default {
name: "Demo",
setup() {
let person = reactive({
surName: "张",
lastName: "三",
});
// let fullName = computed(() => {
// return person.surName + "-" + person.lastName;
// });
person.fullName=computed(() => {
return person.surName + "-" + person.lastName;
});
return {
person,
};
},
};
</script>
可修改的computed(完整写法)
<template>
<div>
<h2>个人信息</h2>
姓:<input type="text" v-model="person.surName" />
<br />
名:<input type="text" v-model="person.lastName" />
<br />
全名:<input type="text" v-model="person.fullName">
</div>
</template>
<script>
import { reactive, computed } from "vue";
export default {
name: "Demo",
setup() {
let person = reactive({
surName: "张",
lastName: "三",
});
person.fullName=computed({
get(){
return person.surName + "-" + person.lastName;
},
set(value){
const nameArr=value.split('-')
person.surName=nameArr[0]
person.lastName=nameArr[1]
}
});
return {
person,
};
},
};
</script>
监视一个
<template>
<div>
<h3>当前求和为:{{ sum }}</h3>
<button @click="sum++">点我+1</button>
</div>
</template>
<script>
import { reactive, watch,ref } from "vue";
export default {
name: "Demo",
setup() {
let sum=ref(0)
watch(sum,(newVal,oldVal)=>{
console.log('sum的值改变',newVal,oldVal)
})
return {
sum
};
},
};
</script>
监视多个
<template>
<div>
<h3>当前求和为:{{ sum }}</h3>
<button @click="sum++">点我+1</button>
<hr>
<h3>当前的信息为:{{ msg }}</h3>
<button @click="msg+='!'">修改信息</button>
</div>
</template>
<script>
import { reactive, watch,ref } from "vue";
export default {
name: "Demo",
setup() {
let sum=ref(0)
let msg=ref('你好')
watch([sum,msg],(newVal,oldVal)=>{
console.log('sum的值改变',newVal,oldVal)
},{immediate:true})
return {
sum,
msg
};
},
};
</script>
<template>
<div>
<h3>当前求和为:{{ sum }}</h3>
<button @click="sum++">点我+1</button>
<hr>
<h3>当前的信息为:{{ msg }}</h3>
<button @click="msg+='!'">修改信息</button>
<hr>
<h3>人员信息</h3>
<button @click="updateName">修改姓名</button>
<button @click="person.age++">增长年龄</button>
<h4>姓名:{{ person.name }}</h4>
<h4>年龄:{{ person.age }}</h4>
</div>
</template>
<script>
import { reactive, watch,ref } from "vue";
export default {
name: "Demo",
setup() {
let sum=ref(0)
let msg=ref('你好')
let person=reactive({
name:'lucy',
age:18
})
function updateName(){
person.name='jack'
}
watch(person,(newVal,oldVal)=>{
console.log('person的值改变',newVal,oldVal)
},{immediate:true})
return {
sum,
msg,
person,
updateName,
};
},
};
</script>
监测oldvalue有问题,都显示为newValue
多级嵌套的对象,不用加深度监测属性,也可以监测的到
可以加。value
<template>
<div>
<h3>当前求和为:{{ sum }}</h3>
<button @click="sum++">点我+1</button>
<hr>
<h3>当前的信息为:{{ msg }}</h3>
<button @click="msg+='!'">修改信息</button>
<hr>
<h3>人员信息</h3>
<button @click="updateName">修改姓名</button>
<button @click="person.job.salary++">涨薪</button>
<h4>姓名:{{ person.name }}</h4>
<h4>薪资:{{ person.job.salary }}</h4>
</div>
</template>
<script>
import { reactive, watch,ref ,watchEffect} from "vue";
export default {
name: "Demo",
setup() {
let sum=ref(0)
let msg=ref('你好')
let person=reactive({
name:'lucy',
job:{
salary:20
}
})
function updateName(){
person.name='jack'
}
watchEffect(()=>{
//用谁监测谁
const x1=sum.value
const x2=person.job.salary
console.log('a')
})
return {
sum,
msg,
person,
updateName,
};
},
};
</script>
正常写法
<template>
<h2>当前鼠标的坐标为:x:{{ point.x }},y:{{ point.y }}</h2>
</template>
<script>
import {reactive,onMounted} from "vue";
export default {
name: "Demo",
setup(){
let point=reactive({
x:0,
y:0
})
onMounted(()=>{
window.addEventListener('click',(e)=>{
point.x=e.pageX
point.y=e.pageY
})
})
return {
reactive,onMounted,point
}
}
};
</script>
可拆卸事件的版本
<template>
<h2>当前鼠标的坐标为:x:{{ point.x }},y:{{ point.y }}</h2>
</template>
<script>
import { reactive, onMounted, onBeforeUnmount } from "vue";
export default {
name: "Demo",
setup() {
let point = reactive({
x: 0,
y: 0,
});
function savePoint(e) {
point.x = e.pageX;
point.y = e.pageY;
}
onMounted(() => {
window.addEventListener("click", savePoint);
});
onBeforeUnmount(() => {
window.removeEventListener("click", savePoint);
});
return {
reactive,
onMounted,
point,
savePoint,
};
},
};
</script>
与别人共享这套方法
// test\src\hooks\Demo.vue
<template>
<h2>当前鼠标的坐标为:x:{{ point.x }},y:{{ point.y }}</h2>
</template>
<script>
import usePoint from "../hooks/usePoint";
export default {
name: "Demo",
setup() {
let point=usePoint();
return {
point,
};
},
};
</script>
// test\src\hooks\usePoint.js
import { reactive, onMounted, onBeforeUnmount } from "vue";
export default function () {
let point = reactive({
x: 0,
y: 0,
});
function savePoint(e) {
point.x = e.pageX;
point.y = e.pageY;
}
onMounted(() => {
window.addEventListener("click", savePoint);
});
onBeforeUnmount(() => {
window.removeEventListener("click", savePoint);
});
return point
}
<template>
<div>
{{ name }}
{{ age }}
{{ all }}
</div>
</template>
<script>
import { toRef,reactive } from 'vue'
export default {
name:'Demo',
setup(){
let person=reactive({
name:'lucy',
age:18,
job:{
salary:{
all:3
}
}
})
const name1=person.name
console.log(name1)
const name2=toRef(person.name)
console.log(name2)
return {
//告诉person,拿它的name
//以下同理
//好处,简化书写
name:toRef(person,'name'),
age:toRef(person,'age'),
all:toRef(person.job.salary,'all')
}
}
}
</script>
<template>
<div>
{{ name }}
{{ age }}
{{ job.salary.all }}
</div>
</template>
<script>
import { toRefs,reactive } from 'vue'
export default {
name:'Demo',
setup(){
let person=reactive({
name:'lucy',
age:18,
job:{
salary:{
all:3
}
}
})
return {
person,
...toRefs(person)
}
}
}
</script>
薪资+ 没有反应
<template>
<div>
姓名:{{ name }}
<br>
年龄:{{ age }}
<br>
薪资:
{{ job.salary.all }}
<br>
<button @click="name+='!'">改变名字</button>
<button @click="age++">年龄+</button>
<button @click="job.salary.all++">薪资+</button>
</div>
</template>
<script>
import { toRefs,shallowReactive } from 'vue'
export default {
name:'Demo',
setup(){
let person=shallowReactive({
name:'lucy',
age:18,
job:{
salary:{
all:3
}
}
})
return {
person,
...toRefs(person)
}
}
}
</script>
<template>
<div>
当前x.y的值是:{{ x.y }}
<br />
<button @click="x = { y: 888 }">点我替换x</button>
<button @click="x.y++">点我x.y++</button>
</div>
</template>
<script>
import { toRefs, shallowRef } from "vue";
export default {
name: "Demo",
setup() {
let x = shallowRef({
y: 0,
});
return {
x,
};
},
};
</script>
<template>
<div>
姓名:{{ name }}
<br>
年龄:{{ age }}
<br>
薪资:
{{ job.salary.all }}
<br>
<button @click="name+='!'">改变名字</button>
<button @click="age++">年龄+</button>
<button @click="job.salary.all++">薪资+</button>
</div>
</template>
<script>
import { readonly ,toRefs,reactive} from 'vue'
export default {
name:'Demo',
setup(){
let person=reactive({
name:'lucy',
age:18,
job:{
salary:{
all:3
}
}
})
person=readonly(person)
return {
person,
...toRefs(person),
}
}
}
</script>
<template>
<div>
姓名:{{ name }}
<br>
年龄:{{ age }}
<br>
薪资:
{{ job.salary.all }}
<br>
<button @click="name+='!'">改变名字</button>
<button @click="age++">年龄+</button>
<button @click="sal">薪资+</button>
</div>
</template>
<script>
import { shallowReadonly ,toRefs,reactive} from 'vue'
export default {
name:'Demo',
setup(){
let person=reactive({
name:'lucy',
age:18,
job:{
salary:{
all:3
}
}
})
function sal(){
person.job.salary.all++
console.log('更新后的salary值为:',person.job.salary.all)
}
person=shallowReadonly(person)
return {
person,
...toRefs(person),
sal
}
}
}
</script>
没有效果
<template>
<div>
姓名:{{ name }}
<br />
年龄:{{ age }}
<br />
薪资:
{{ job.salary.all }}
<br />
<button @click="name += '!'">改变名字</button>
<button @click="age++">年龄+</button>
<button @click="job.salary.all++">薪资+</button>
<br />
<button @click="rawShow">输出最原始的person</button>
</div>
</template>
<script>
import { toRefs, reactive, toRaw } from "vue";
export default {
name: "Demo",
setup() {
let person = reactive({
name: "lucy",
age: 18,
job: {
salary: {
all: 3,
},
},
});
function rawShow() {
let r = toRaw(person);
console.log(r);
}
return {
person,
...toRefs(person),
rawShow,
};
},
};
</script>
<template>
<div>
姓名:{{ name }}
<br />
年龄:{{ age }}
<br />
薪资:
{{ job.salary.all }}
<br />
<button @click="name += '!'">改变名字</button>
<button @click="age++">年龄+</button>
<button @click="job.salary.all++">薪资+</button>
</div>
</template>
<script>
import { toRefs, reactive, markRaw } from "vue";
export default {
name: "Demo",
setup() {
let person = reactive({
name: "lucy",
age: 18,
job: {
salary: {
all: 3,
},
},
});
person.age=markRaw(age)
return {
person,
...toRefs(person),
};
},
};
</script>
做延时显示效果
<template>
<div>
<input type="text" v-model="keyWord" />
<h2>{{ keyWord }}</h2>
</div>
</template>
<script>
import { customRef } from "vue";
export default {
name: "Demo",
setup() {
//初始化传入的值,是不变的
function myref(val) {
//自定义一个ref
// const x=customRef()
// return x
return customRef((track, trigger) => {
return {
get() {
track();
return val;
},
set(newVal) {
val = newVal;
setTimeout(() => {
trigger(); //通知Vue去重新解析模板
}, 1000);
},
};
});
}
// let keyWord=ref('hello'+123)//使用vue提供的ref(精装版)
//使用程序员自定义的ref
let keyWord = myref("hello");
return {
keyWord,
};
},
};
</script>
任何后代都可以用inject(注入)
// test\src\App.vue
<template >
<div class="app">
App
<br />
<h3>{{ name }}--{{ age }}
</h3>
<Child />
</div>
</template>
<script>
import { reactive, toRefs ,provide} from "vue";
import Child from "./components/Child.vue";
export default {
name: "App",
setup() {
let per = reactive({ name: "lucy", age: 18 });
provide("fang", per);
return { ...toRefs(per) };
},
components: {
Child,
},
};
</script>
<style>
.app {
background-color: rgb(246, 113, 171);
padding: 10px;
}
</style>
// test\src\components\Child.vue
<template>
<div class="child">
child
<GrandChild />
</div>
</template>
<script>
import GrandChild from "./GrandChild.vue";
export default {
name: "Child",
components: { GrandChild },
};
</script>
<style>
.child {
background-color: rgb(153, 153, 220);
padding: 10px;
}
</style>
// test\src\components\GrandChild.vue
<template>
<div class="gchild">GrandChild
<h3>{{ hai.name }}--{{ hai.age }}</h3>
</div>
</template>
<script>
import { inject } from "vue";
export default {
name: "GrandChild",
setup() {
let hai = inject("fang");
return { hai };
},
};
</script>
<style>
.gchild {
background-color: rgb(237, 192, 227);
padding: 10px;
}
</style>
<template></template>
<script>
import {
isProxy,
isReactive,
isReadonly,
isRef,
reactive,
readonly,
ref,
toRefs,
} from "vue";
export default {
name: "App",
setup() {
let per1 = reactive({ name: "lucy", age: 18 });
let per2 = readonly(per1);
let sum = ref(0);
console.log(isRef(sum));
console.log(isReactive(per2));
console.log(isReadonly(per2));
console.log(isReadonly(sum));
console.log(isProxy(per2));
console.log(isProxy(sum));
return { ...toRefs(per1) };
},
};
</script>
<style>
</style>
传送
// test\src\components\Dialog.vue
<template>
<div>
<button @click="show = true">点我弹窗</button>
<!-- 要传送的内容 -->
<!-- to到html结构里面 -->
<teleport to="body">
<!-- 遮罩层 -->
<div class="mask" v-if="show">
<div class="dia">
<h3>我是一个弹窗</h3>
@click="show=true"
<div>内容</div>
<div>内容</div>
<button @click="show = false">关闭弹窗</button>
</div>
</div>
</teleport>
</div>
</template>
<script>
import { ref } from "vue";
export default {
name: "Dialog",
setup() {
let show = ref(false);
return {
show,
};
},
};
</script>
<style>
.mask {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: rgba(0, 0, 0, 0.5);
}
.dia {
position: absolute;
/* 参考父元素的50% */
top: 50%;
left: 50%;
/* 参考自身的50% */
transform: translate(-50%, -50%);
border-radius: 10px;
widows: 200px;
padding: 10px;
height: 150px;
background-color: rgb(192, 111, 122);
}
</style>
<template>
<div class="app">APP
<Child/>
</div>
</template>
<script>
//静态引入
// import Child from './components/Child.vue'
//动态(异步)引入
import {defineAsyncComponent} from "vue";
//此处的import是个函数
const Child=defineAsyncComponent(()=>import('./components/Child.vue'))
export default {
name: "App",
components:{Child}
};
</script>
<style>
.app{
background-color: rgb(238, 144, 230);
padding: 10px;
}
</style>
<template>
<div class="app">
APP
<Suspense>
<!-- default放置应该展现的组件 -->
<template v-slot:default>
<Child />
</template>
<!-- 放置应急计划(退路) -->
<template v-slot:fallback>
<h3>加载中......</h3>
</template>
</Suspense>
</div>
</template>
<script>
import { defineAsyncComponent } from "vue";
//此处的import是个函数
const Child = defineAsyncComponent(() => import("./components/Child.vue"));
export default {
name: "App",
components: { Child },
};
</script>
<style>
.app {
background-color: rgb(238, 144, 230);
padding: 10px;
}
</style>
可以控制几秒到达
// test\src\components\Child.vue
<template>
<div class="child">
{{ sum }}
</div>
</template>
<script>
import { ref } from "vue";
export default {
name: "Child",
setup() {
let sum = ref(123);
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({ sum });
//随意设置等待几秒
}, 500);
});
},
};
</script>
<style>
.child {
background-color: rgb(153, 153, 220);
padding: 10px;
}
</style>
// app组件不变
<template>
<div class="app">
APP
<Suspense>
<!-- default放置应该展现的组件 -->
<template v-slot:default>
<Child />
</template>
<!-- 放置应急计划(退路) -->
<template v-slot:fallback>
<h3>加载中......</h3>
</template>
</Suspense>
</div>
</template>
<script>
import { defineAsyncComponent } from "vue";
//此处的import是个函数
const Child = defineAsyncComponent(() => import("./components/Child.vue"));
export default {
name: "App",
components: { Child },
};
</script>
<style>
.app {
background-color: rgb(238, 144, 230);
padding: 10px;
}
</style>
// test\src\components\Child.vue
<template>
<div class="child">
{{ sum }}
</div>
</template>
<script>
import { ref } from "vue";
export default {
name: "Child",
async setup() {
let sum = ref(123);
let p= new Promise((resolve, reject) => {
setTimeout(() => {
resolve({ sum });
}, 500);
});
return await p
},
};
</script>
<style>
.child {
background-color: rgb(153, 153, 220);
padding: 10px;
}
</style>