建立vue项目
npm init vue@latest
Need to install the following packages:
create-vue@3.10.3 Ok to proceed? (y) y
Vue.js - The Progressive JavaScript Framework
√ 请输入项目名称: ... vue-base
√ 是否使用 TypeScript 语法? ... 否 / 是
√ 是否启用 JSX 支持? ... 否 / 是
√ 是否引入 Vue Router 进行单页面应用开发? ... 否 / 是
√ 是否引入 Pinia 用于状态管理? ... 否 / 是
√ 是否引入 Vitest 用于单元测试? ... 否 / 是
√ 是否要引入一款端到端(End to End)测试工具?
√ 是否引入 ESLint 用于代码质量检测? ... 否 / 是
√ 是否引入 Vue DevTools 7 扩展用于调试? (试验阶段) ... 否 / 是
正在初始化项目 D:\biancheng\vue_vscode\vue-base...
项目初始化完成,可执行以下命令:
cd vue-base
npm install
npm run dev
npm notice
npm notice New major version of npm available! 9.5.1 -> 10.5.2
npm notice Changelog:github.com/npm/cli/rel…
npm notice Run npm install -g npm@10.5.2 to update!
npm notice
安装路由
npm install vue-router@4
- 导入路由
目录介绍
| 目录/文件 | 说明 |
|---|---|
| build | 项目构建(webpack)相关代码 |
| config | 配置目录,包括端口号等。我们初学可以使用默认的。 |
| node_modules | npm 加载的项目依赖模块 |
| src | 这里是我们要开发的目录,基本上要做的事情都在这个目录里。里面包含了几个目录及文件: assets: 放置一些图片,如logo等。 components: 目录里面放了一个组件文件,可以不用。 App.vue: 项目入口文件,我们也可以直接将组件写这里,而不使用 components 目录。main.js: 项目的核心文件。 index.css: 样式文件。 |
| static | 静态资源目录,如图片、字体等。 |
| public | 公共资源目录。 |
| test | 初始测试目录,可删除 |
| .xxxx文件 | 这些是一些配置文件,包括语法配置,git配置等。 |
| index.html | 首页入口文件,你可以添加一些 meta 信息或统计代码啥的。 |
| package.json | 项目配置文件。 |
| README.md | 项目的说明文档,markdown 格式 |
| dist | 使用 npm run build 命令打包后会生成该目录。 |
模版语法
浏览器跨域问题
场景代码:
CorsDemo.vue
<template>
<h1>CorsDemo</h1>
<div>
<button @click="getInfo">获取信息</button>
</div>
<div>
info====>>>{{ res }}
</div>
</template>
<script setup>
import axios from 'axios';
import { ref } from 'vue';
const res = ref();
const getInfo = () => {
axios.get('http://localhost:2048/api/info').then(
success => {
res.value = success.data;
},
error => {
res.value = error.data;
}
);
}
</script>
CorsController.java
package wnan.controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController("corsController")
public class CorsController {
@GetMapping("/info")
public Map<Integer, String> getInfo(){
Map<Integer, String> map = new HashMap<>();
map.put(1,"one");
map.put(2,"two");
map.put(3,"three");
return map;
}
}
运行error:
解决方法
cors: 这种方式是我工作中处理跨域用到最多也是最简单的一种方式,直接通过注解解决跨域问题,cors解决跨域,一般不用于前端做任何事,而是后端或者服务器去操作,其实就是在服务器里面返回相应的时候加几个响应头,某种程度上来说,cors解决跨域才是真正意义上的解决跨域,但是在开发中,这个响应头不是随便配置的,如果随意配置,就会造成一个问题就算任何人都能找服务器要数据,存在一些安全风险
- 后端添加注解【后端】
org.springframework.web.bind.annotation.CrossOrigin;用于单独的控制器@CrossOrigin注解是Spring框架中用于处理跨域请求的一个注解。它的主要功能是允许前端应用在发起跨域请求时,后端服务器能够响应并允许这些请求。这样做的目的是为了克服浏览器的同源策略限制,使得跨域请求能够成功进行。
@RestController("corsController")
@CrossOrigin
public class CorsController {}
- 全局配置跨域【后端】 单独写一个配置类 CrosConfig.java
package wnan.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
String[] methods = {"GET", "POST", "DELETE", "PUT", "OPTIONS"};
//addMapping 添加可跨域的请求地址
// 配置CORS(跨域资源共享)策略,以允许特定的跨域请求
// 对所有路径进行映射,应用以下CORS规则
registry.addMapping("/**")
// 允许所有来源的请求,* 表示任意域名,域名权限 规定由某一个指定的域名+端口能访问跨域项目
.allowedOrigins("*")
// 不允许发送凭证(如Cookies),因为这在当前上下文中不是必需的,是否开启cookie跨域
.allowCredentials(false)
// 允许指定的HTTP方法通过,methods变量应包含需要允许的方法列表
.allowedMethods(methods)
// 指定预检请求(preflight request)的结果可以缓存的最大时间,单位为秒
.maxAge(3600);
}
}
- 代理【前端】 vit.config.js
export default defineConfig({
// 定义服务器配置
server: {
// 服务器端口
port: 6930,
// 代理配置
proxy: {
// 定义以'/api'开头的请求代理
'/api': {
// 代理目标服务器地址
target: 'http://localhost:2048',
// 启用WebSocket代理
ws: true,
// 更改代理请求的主机头为目标URL
changeOrigin: true,
// 重写代理路径
pathWrite: {
// 将请求路径中的'^/api'保留为'/api'
'^/api': '/api',
}
},
}
}
})
axios的请求里不要有代理目标服务器地址,比如:http://localhost:2048。 例如:
const getInfo2 = () => {
axios.get('/api/info').then(
success => {
res2.value = success.data;
},
error => {
res2.value = error.data;
}
);
}
如果成功:
如果有
http://localhost:2048,则是如下情况,代理失败
组件间的数据传递
父组件-->子组件
- 在父组件中,把变量名写在子组件的标签上
- 子组件中使用
defineProps()方法里,采用对象的格式,{变量名:变量类型}props.xxxx的格式调用
- 父组件
<template>
<p>这是父组件</p>
<PropsChild greetingMessage="hello" />
</template>
<script setup>
import PropsChild from "@/deep-components/PropsChild.vue";
</script>
- 子组件
<template>
<p>这是子组件</p>
<span>{{ props.greetingMessage }}</span>
</template>
<script setup>
import { defineExpose } from 'vue';
const props = defineProps({
greetingMessage: String,
})
</script>
<template>
<PropsChild :greetingMessage="data" />
</template>
<script setup>
import { ref } from 'vue'
const data = ref("1");
</script>
子组件里的props.greetingMessage不具有响应式
子组件-->父组件
- 子组件里使用
defineEmits(),传入数组,数组格式['子组件事件名称1',.....]- 使用
emit('子组件事件名称1',变量值)发送数据到父组件- 父组件里在子组件标签上使用
@子组件事件名称1='父组件事件1'父组件事件1=(变量值)=>{ //进行数据传递的操作 }- 2和4的变量值是同一个
- 父组件
<template>
<p>这是父组件</p>
<!-- clickChild是子组件绑定的事件,click是父组件接受方式 -->
<PropsChild @clickChild="clickEven"></PropsChild>
<span>父组件里显示===>>>{{ child_data }}</span>
</template>
<script setup>
import PropsChild from "@/deep-components/PropsChild.vue";
import { ref } from 'vue'
const child_data = ref('2')
const clickEven = (val) => {
console.log(val);
child_data.value = val;
}
</script>
- 子组件
<template>
<p>这是子组件</p>
<button @click="clickChild">点击子组件</button>
</template>
<script setup>
import { defineEmits, ref, defineExpose, reactive } from 'vue';
const emit = defineEmits(['clickChild'])
const clickChild = () => {
let content = '子主件的数据';
console.log('子组件点击了')
//传递给父组件
emit('clickChild', content)
}
</script>
例二
- 父组件
<template>
<p>这是父组件</p>
<span>父组件里显示===>>>{{ child_data }}</span>
<PropsChild @child_data_input="getval"></PropsChild>
</template>
<script setup>
import PropsChild from "@/deep-components/PropsChild.vue";
import { ref } from 'vue'
const child_data = ref();
const getval=(val)=>{
child_data.value=val;
}
</script>
```
2. 子组件
```vue
<template>
<p>这是子组件</p>
<input v-model="child_data" type="text">
</template>
<script setup>
import { defineEmits, ref, defineExpose, reactive,watch } from 'vue';
const child_data = ref("")
const emit = defineEmits(['child_data_input'])
watch(child_data,(child_data)=>{
console.log(child_data)
emit('child_data_input',child_data)
})
</script>
父组件获得子组件的数据ref方法
- 需要将组建的属性及方法通过
[defineExpose]导出,defineExpose()参数是对象{}- 父组件里在子组件标签里使用
ref="自定义变量"- 子定义变量是
defineExpose里传递的对象
- 父组件
<template>
<p>这是父组件</p>
<span>父组件里显示===>>>{{ child_data_ref }}</span>
<PropsChild ref="child_data_ref"></PropsChild>
<button @click="dodo">child_data_ref</button>
</template>
<script setup>
import PropsChild from "@/deep-components/PropsChild.vue";
import { ref } from 'vue'
const child_data_ref = ref({});
console.log(child_data_ref.value.info)
console.log(child_data_ref.value.sex)
function dodo (){
console.log(child_data_ref.value.info)
console.log(child_data_ref.value.sex)
}
</script>
- 子组件
<template>
<p>这是子组件</p>
</template>
<script setup>
import { defineEmits, ref, defineExpose, reactive,watch } from 'vue';
const info = reactive({
name: 'huahua',
age: 18
})
const sex = ref('男')
defineExpose({ info, sex })
</script>
路由useRouter和useRout的区别
在Vue 3中,useRouter() 和 useRoute() 是Vue Router提供的两个不同的组合式API函数,它们分别用于不同的目的:
- useRouter()
useRouter()函数返回一个路由实例,该实例提供了许多方法,可以让你在组件内进行编程式导航。例如,你可以使用router.push()来导航到不同的URL,或者使用router.replace()来替换当前的历史记录。 以下是一些useRouter()可以使用的路由实例方法:router.push(location, onComplete?, onAbort?): 添加一个新的路由到历史记录栈中。router.replace(location, onComplete?, onAbort?): 在历史记录中替换当前路由。router.go(n): 在历史记录中前进或后退n步。router.back(): 等同于router.go(-1),后退一步。router.forward(): 等同于router.go(1),前进一步。 示例:
import { useRouter } from 'vue-router'
export default {
setup() {
const router = useRouter()
function goToBookDetail(bookId) {
router.push(`/book/${bookId}`)
}
return {
goToBookDetail
}
}
}
- useRoute()
useRoute()函数返回当前路由对象,该对象包含了当前激活路由的详细信息,如params、query、hash等。它是一个只读对象,因此你无法通过它来改变当前路由。 以下是一些可以从useRoute()获取的信息:route.params: 路由参数。route.query: 路由查询参数。route.hash: 当前路由的hash值。route.fullPath: 完整的URL路径。route.matched: 匹配到的路由记录数组。
示例:
import { useRoute } from 'vue-router'
export default {
setup() {
const route = useRoute()
// 获取当前路由的参数
const bookId = route.params.id
return {
bookId
}
}
}
总结:
useRouter()用于导航到不同的URL。useRoute()用于获取当前激活路由的详细信息。
关于依赖安装
scss
npm install -D sass-embedded