1,Vue的环境创建
1,安装Vue.js
cnpm install -g @vue/cli
2,创建项目
vue create vue-demo
学习状态不要选Listen选项
3,启动项目
cd vue-demo
npm run serve
4,高亮插件
VSCode安装vetur或者volar
2,Vue模板语法
1,文本
<template>
<span>Message: {{ msg }}</span>
</template>
<script>
export default {
name: 'HelloWorld',
data(){
return{
msg:"消息提示"
}
}
}
</script>
2,原始HTML
<span vhtml="rawHtml"></span>
3,JavaScript 表达式
{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
4,条件渲染
<p v-if="flag">我是孙猴子</p>
<p v-else>你是傻猴子</p>
data() {
return {
flag: true
}
}
和v-show的区别是,v-if是false则不会渲染,v-show一直会渲染,基于css来切换来显示
切换比较频繁用v-show
5,列表渲染
<div v-for="(item,index) in items":key="item.id|index">{{}item.vau}</div>
有id用id,没id用index代替
6,事件处理方法
<button @click="greet">Greet</button>
methods: {
greet(event) {
// `event` 是原生 DOM event
if (event) {
alert(event.target.tagName)
}
}
}
7,内联处理器中的方法
<button @click="say('hi')">Say hi</button>
<button @click="say('what')">Saywhat</button>
methods: {
say(message) {
alert(message)
}
}
8、表单输入绑定
<input v-model="message" placeholder="edit me" />
<p>Message is: {{ message }}</p>
data() {
return {
message:""
}
}
placeholder表示灰色提示语
默认实时同步,
v-model.lazy修饰符.lazy表示懒加载,只有改变事件之后才会同步
v-model.trim可以过滤用户输入得空白字符
3,组件基础
1,单文件组件
<template>
<h3>单文件组件</h3>
</template>
<script>
export default {
name:"MyComponent"
}
</script>
<style scoped>
h3{
color: red;
}
</style>
scoped表示只在本文件内生效
加载组件:
- 引入组件:import MyComponentVue from './components/MyComponent.vue'
挂载组件 components: { MyComponentVue } 显示组件 <my - componentVue />
2, 父组件传递子组件消息
父组件
<template>
<img alt="Vue logo" src="./assets/logo.png">
<HelloWorld :msg2="msg1" :names1="names"/>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
components: {
HelloWorld
},
data(){
return{
msg1:"我是父组件信息",
names:["张三","李四","王五"]
}
}
}
</script>
子组件
<template>
<div class="hello">
{{ msg2 }}
<ul>
<li v-for="(item,index) in names1" :key="index">{{ item }}</li>
</ul>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data(){
return{
}
},
props:{
msg2:{
type:String,
default:""
},
names1:{
type:Array,
default:function(){
return[]
}
}
}
}
</script>
3,自定义事件实现子组件给父组件传递消息
子组件
<template>
<button @click="sendHandle">发送数据</button>
</template>
<script>
export default {
name: "MyComponent",
methods:{
sendHandle(){
this.$emit("onCustom","数据")
}
}
}
</script>
父组件
<template>
<my-componentVue @onCustom="getData" />
</template>
<script>
import MyComponentVue from
'./components/MyComponent.vue'
export default {
name: 'App',
components: {
MyComponentVue
},
methods: {
getData(data) {
console.log(data);
}
}
}
</script>
4,组件生命周期
创建时: beforeCreate 、 created渲染时: beforeMount 、 mounted更新时: beforeUpdate 、 updated卸载时: beforeUnmount 、 unmounted
4,swiper插件的使用
1,安装插件
cnpm instal -- save swiper@8.1.6
2, 基础实现
<template>
<div class="hello">
<swiper class="mySwiper">
<swiper-slide>Slide 1</swiper-slide>
<swiper-slide>Slide 2</swiper-slide>
<swiper-slide>Slide 3</swiper-slide>
</swiper>
</div>
</template>
<script>
import { Swiper, SwiperSlide } from'swiper/vue';
import 'swiper/css';
export default {
name: 'HelloWorld',
components: {
Swiper,
SwiperSlide,
}
}
</script>
3,添加指示器
<template>
<div class="hello">
<swiper class="mySwiper" :modules="modules" :pagination="{ clickable: true }">
<swiper-slide><img src="../assets/logo.png"alt=""></swiper-slide>
<swiper-slide><img src="../assets/logo.png"alt=""></swiper-slide>
<swiper-slide><img src="../assets/logo.png"alt=""></swiper-slide>
</swiper>
</div>
</template>
<script>
import { Pagination } from 'swiper/modules';
import { Swiper, SwiperSlide } from'swiper/vue';
import 'swiper/css';
import 'swiper/css/pagination';
export default {
name: 'HelloWorld',
data(){
return{
modules: [ Pagination ]
}
},
components: {
Swiper,
SwiperSlide,
}
}
</script>
5,Axios插件使用
1,安装插件
cnpm install -- save axios
2,插件引入
1,组件局部引用
import axios from "axios"
2,全局引用
import axios from "axios"
const app = createApp(App);
app.config.globalProperties.$axios = axios
app.mount('#app')
// 在组件中调用
this.$axios
3,请求方式
1,get请求方式
axios.get("http://iwenwiki.com/api/blueberrypai/getChengpinDetails.php")
.then(res =>{
console.log(res.data);
})
2,post请求方式
安装依赖
cnpm install -- save querystring
axios.post("http://iwenwiki.com/api/blueberrypai/login.php", qs.stringify({
user_id: "iwen@qq.com",
password: "iwen123",
verification_code: "crfvw"
}))
.then(res => {
console.log(res.data);
})
4,Axios网络请求封装
1,请求工具包
import axios from "axios"
2 import qs from "querystring"
3
4
5 const errorHandle = (status,info) => {
6 switch(status){
7 case 400:
8 console.log("语义有误");
9 break;
10 case 401:
11 console.log("服务器认证失败");
12 break;
13 case 403:
14 console.log("服务器拒绝访问");
15 break;
16 case 404:
17 console.log("地址错误");
18 break;
19 case 500:
20 console.log("服务器遇到意外");
21 break;
22 case 502:
23 console.log("服务器无响应");
24 break;
25 default:
26 console.log(info);
27 break;
28 }
33
29 }
30
31
32 const instance = axios.create({
33 timeout:5000
34 })
35
36 instance.interceptors.request.use(
37 config =>{
38 if(config.method === "post"){
39 config.data =
qs.stringify(config.data)
40 }
41 return config;
42 },
43 error => Promise.reject(error)
44 )
45
46 instance.interceptors.response.use(
47 response => response.status === 200 ?
Promise.resolve(response) :
Promise.reject(response),
48 error =>{
49 const { response } = error;
50
errorHandle(response.status,response.info)
51 }
52 )
53
54 export default instance;
2,请求API包
// path.js
2 const base = {
3 baseUrl:"http://iwenwiki.com",
4
chengpin:"/api/blueberrypai/getChengpinDetai
ls.php"
5 }
6
7 export default base
// index.js
2 import path from "./path"
3 import axios from "../utils/request"
4
5 export default {
6 getChengpin(){
7 return axios.get(path.baseUrl +
path.chengpin)
8 }
9 }
组件中直接调用网络请求
import api from "../api/index"
2
3 api.getChengpin().then(res =>{
4 console.log(res.data);
5 })
5,跨域问题
vue.config.js中增加一下内容
devServer: {
proxy: {
'/api': {
target: '<url>',
changeOrigin: true
}
}
}
6,Vue路由
1,Vue引入路由配置
1,安装路由
cnpm install -- save vue - router
2,配置路由文件index.js
import {createRouter,createWebHashHistory} from "vue-router"
import HomeView from '../views/HomeView.vue'
const routes = [
{
path:'/',
name:'home',
component: HomeView
},
{
path:'/about',
name:'about',
component:() => import('../views/AboutView.vue')
}
]
const router = createRouter({
//history:createWebHistory,没有#号,要后台重定向
history:createWebHashHistory(),
routes
})
export default router
3,配置main.js
import router from "./router"
createApp(App).use(router).mount('#app')
4,编写App.vue
<router-link to="/">首页</router-link> |
<router-link to="/about">关于页面</router-link>
<!--路由显示入口-->
<router-view/>
2,路由传递参数
1,在路由配置中指定参数key
{
path:"/list/:name",
name:"list",
component:() =>
import("../views/ListView.vue")
}
2,在跳转过程携带参数
<li><router-link to="/list/内蒙">内蒙旅游十大景区</router-link></li>
<li><router-link to="/list/北京">北京旅游十大景区</router-link></li>
<li><router-link to="/list/四川">四川旅游十大景区</router-link></li>
3,详情页读取路由携带参数
<p>{{ $route.params.name }}城市旅游景区详情</p>
3,嵌套路由配置
1,在路由配置中index.js
import { createRouter, createWebHashHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
const routes = [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/about',
name: 'about',
//重定向默认页面
redirect:"/about/us",
component: () => import( '../views/AboutView.vue'),
children:[
{
//二级导航不加斜杠
path:"us",
component:() => import('../views/AboutSub/AboutUS.vue')
},
{
path:"info",
component:() => import('../views/AboutSub/Aboutinfo.vue')
}
]
}
]
const router = createRouter({
history: createWebHashHistory(),
routes
})
export default router
2,修改主页面App.vue
<nav>
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</nav>
<router-view/>
3,AboutView.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>
4,创建子页面AboutUS.vue和Aboutinfo.vue
7,Vuex
1,引入Vuex
1,安装Vuex
cnpm install -- save vuex
2,配置Vuex文件src/store/index.js
所有的状态都放在state中,
import { createStore } from 'vuex'
export default createStore({
state: {
counter:0
}
})
3,在main.js中引入Vuex
import store from './store'
app.use(store)
4,在组件中读取组件状态
<p>counter:{{ $store.state.counter }}</p>
// 或者
<p>{{counter}}</p>
import { mapState } from 'vuex';
computed:{
...mapState(["counter"])
}
2,Vue状态管理核心(Vuex)
1,Gerrer
对Vuex中state的状态进行过滤
import { createStore } from 'vuex'
export default createStore({
state: {
counter: 0
},
getters: {
getCount(state){
return state.counter > 0 ?
state.counter : "counter小于0,不符合要求"
}
}
})
读取状态
<p> count={{ $store.getters.getCounter }}</p>
//或者
import { mapState,mapGetters } from 'vuex';
computed:{
...mapGetters(["getCount"])
}
2,Mutation
更改Vuex中store的状态
import { createStore } from 'vuex'
export default createStore({
state: {
counter: 0
},
mutations: {
setCounter(state, num) {
state.counter += num
}
}
})
读取状态写法1
<button @click="clickHandle">增加</button>
import { mapState } from
'vuex';
methods:{
clickHandler(){
this.$store.commit("setCounter",20)
}
}
读取状态写法2
<button @click="clickHandle">增加</button>
import { mapState,mapMutations } from
'vuex';
methods:{
...mapMutations(["setCounter"]),
clickHandler(){
this.setCounter(10)
}
}
3,Action
Action 提交的是 mutation ,而不是直接变更状态Action 可以包含任意 异步 操作
更改Vuex中store的状态
import { createStore } from 'vuex'
import axios from "axios"
export default createStore({
state: {
counter: 0
},
mutations: {
setCounter(state, num) {
state.counter += num
}
},
actions: {
asyncSetCount({ commit }){
axios.get("http://iwenwiki.com/api/generator/list.php").then(res =>{
commit("setCounter",res.data[0])
})
}
}
})
读取状态写法1
<button @click="addAsynClickHandle">异步增加</button>
import {mapState,mapMutations,mapGetters,mapActions} from 'vuex';
methods:{
clickAsyncHandler(){
this.$store.dispatch("asyncSetCount")
}
}
读取状态写法2
<button @click="addAsynClickHandle">异步增加</button>
import {mapState,mapMutations,mapGetters,mapActions} from 'vuex';
methods:{
...mapActions(["asyncSetCount"]),
clickAsyncHandler(){
this.asyncSetCount()
}
}
8,Vue3新特性
Performance :性能更比 Vue 2.0 强。Tree shaking support :可以将无用模块 “ 剪辑 ” ,仅打包需要的。Composition API :组合 APIFragment, Teleport, Suspense : “ 碎片 ” , Teleport 即 Protal 传送门, “ 悬念 ”Better TypeScript support :更优秀的 Ts 支持Custom Renderer API :暴露了自定义渲染 API
1,ref或者reactive
1,vue2.x中
data() {
return {
name: 'iwen',
list: [],
}
}
2,vue3.x中
import { ref,reactive } from "vue"
export default {
name: 'HelloWorld',
setup(){
const name = ref("iwen")
const state = reactive({
list:[]
})
return{
name,
state
}
}
}
2,methods中定义的方法
1,vue2.x中
methods:{
http(){}
}
2,vue3.x中
setup() {
const http = ()=>{
// do something
}
return {
http
};
}
3,setup()中使用props和context
export default {
props: {
name: String,
},
setup(props,ctx) {
console.log(props.name)
ctx.emit('event')
},
}
4,在setup中使生命周期函
export default {
setup() {
// mounted
onMounted(() => {
console.log('Component is mounted!')
})
}
}
5,Provide / Inject
provide() 和 inject() 可以实现嵌套组件之间的数据传递。这两个函数只能在 setup() 函数中使用。父级组件中使用 provide() 函数向下传递数据。子级组件中使用 inject() 获取上层传递过来的数据。不限层级
// 父组件
import { provide } from "vue"
setup() {
provide("customVal", "我是父组件向子组件传递的值");
}
// 子组件
import { inject } from "vue"
setup() {
const customVal = inject("customVal");
return {
customVal
}
}
9,引入element-plus
1,安装element-pius
cnpm install element - plus -- save
2,完整引用
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
app.use(ElementPlus)
3,按需导入
cnpm install - D unplugin - vue - componentscnpm install unplugin - auto - import
修改vue.config.js文件
configureWebpack: {
plugins: [
AutoImport({
resolvers: [ElementPlusResolver()]
}),
Components({
resolvers: [ElementPlusResolver()]
})
]
}
4,安装icons字体图标
1,安装
cnpm install @ element - plus / icons - vue
2,全局注册
创建piugins文件,在此下创建icons.js文件
import * as components from "@elementplus/icons-vue";
export default {
install: (app) => {
for (const key in components) {
const componentConfig =
components[key];
app.component(componentConfig.name,
componentConfig);
}
},
};
3,在main.js中引入icons.js文件
import elementIcon from "./plugins/icons";
app.use(elementIcon)