赞
踩
自己使用 Css 也能实现
<!-- 使用标签transition包裹 --> // apper属性可以让动画加载时出现 简写 apper 属性直接添加 <transition name="hello" :apper="true" apper> <div> <button @click="isShow = !isShow"> 显示/隐藏 </button> <h1 v-show="isShow"> 我是动画元素 </h1> </div> </transition> <!-- 必须使用 vue 规定的名称识别 --> <style> /* .之后的名称与name一致 不加name默认为v */ .hello-enter-active { animation: 动画名 持续时间; } .hello-leave-active { animation: 动画名 持续时间 everse; } .v-enter-active { animation: 动画名 持续时间; } .v-leave-active { animation: 动画名 持续时间 everse; } @keyfarm 动画名{ ... } </style>
<!-- 使用标签transition包裹 --> // apper属性可以让动画加载时出现 简写 apper 属性直接添加 <transition name="hello" :apper="true" apper> <div> <button @click="isShow = !isShow"> 显示/隐藏 </button> <h1 v-show="isShow"> 我是动画元素 </h1> </div> </transition> <!-- 必须使用 vue 规定的名称识别 --> <style> /* .之后的名称与name一致 不加name默认为v */ /* 给所需动画添加过度属性 */ h1 { transition: all 0.5s linear; } /* 初始效果 离开的终点 */ .v-enter,.v-leave-to { animation: 动画名 持续时间; } /* 过渡效果中 */ .v-enter-active,.v-leave-active { transition: all 0.5s linear; } /* 结束效果 结束的起点 */ .v-leave-enter-to,.v-leave { animation: 动画名 持续时间 everse; } @keyfarm 动画名{ ... } </style>
<!-- 使用标签transition包裹 --> // apper属性可以让动画加载时出现 简写 apper 属性直接添加 <button @click="isShow = !isShow"> 显示/隐藏 </button> <!-- 多个动画添加需要使用transition-group --> <transition-group group name="hello" apper> <div> <h1 v-show="isShow"> 我是动画元素 </h1> <h1 v-show="isShow"> 我是动画元素 </h1> </div> </transition-group> <!-- 必须使用 vue 规定的名称识别 --> <style> /* .之后的名称与name一致 不加name默认为v */ /* 给所需动画添加过度属性 */ h1 { transition: all 0.5s linear; } /* 初始效果 离开的终点 */ .v-enter,.v-leave-to { animation: 动画名 持续时间; } /* 过渡效果中 */ .v-enter-active,.v-leave-active { transition: all 0.5s linear; } /* 结束效果 结束的起点 */ .v-leave-enter-to,.v-leave { animation: 动画名 持续时间 everse; } @keyfarm 动画名{ ... } </style>
animate.css
// 使用方法
// name="animate__animated animate__bounce" 在 transition中添加该属性
// 在官网找到喜欢的属性配置 复制添加到
// enter-active-class="" leave-active-class=""
官网:Animate.css | A cross-browser library of CSS animations.
// 对 xhr 进行封装
// xhr new XMLHttpRequest() xhr.open() xhr.send()
// jQuery $.get $.post
// axios
// 与 xhr平级
// fetch
Vue 项目中 推荐使用 axios
解决跨域问题
1.CORS
2.Jsonp script src 只能使用 get
3.代理服务器 代理服务器默认端口号 8080
1.-- nginx
2.-- vue-cli
const { defineConfig } = require('@vue/cli-service') module.exports = defineConfig({ transpileDependencies: true, // 在配置文件中添加以下配置 开启代理服务器 代理服务器开启在 8080 devServer: { // 需要转发给谁 proxy:'http://后端服务器地址', } }) /* 注意 8080端口服务器 的根目录为 public 其中有的东西直接回返回 不会转发请求 */ // 在axios中请求 axios.get('http://localhost:8080/后端路由地址').then( response =>{ }, errror =>{ }, )
const { defineConfig } = require('@vue/cli-service') module.exports = defineConfig({ transpileDependencies: true, // 在配置文件中添加以下配置 开启代理服务器 代理服务器开启在 8080 devServer: { proxy:{ // 配置 转发服务器的前缀 '/api':{ // 转发地址 target:'http://后端服务器地址', //加入此配置项 转发地址为 /api/student 替换为 /student 不然会请求原路径 pathRewrite:{ '^/api':'' }, ws:true, // 用于支持 websocket changeOrigin:true, // 说谎(伪装请求地址) 默认为 true }, // 可配置多个 '/cas':{ target:'http://后端服务器地址', pathRewrite:{ '^/cas':'' }, ws:true, changeOrigin:true, } } } }) axios.get('http://localhost:8080/配置的前缀/后端路由地址')
import '....' // vue 会进行严格的语法检查 放在assat进行引入
// 推荐放入 public 文件夹 在 index.html 中使用 link 引入 bootstrap.. 等
ES6 合并对象语法 Obj = {…对象1名称,…对象2名称}
对 xhr 进行封装
Vue.use(vueResource) 在main.js中进行全局配置
在 vm 中会出现 $http
使用 this.$http 代替 axios api完全一致 vue1.0广泛使用
<!-- 正常自闭和组件 / 正常组件 --> <Student/> <Student></Student> <!-- 相同组件需要展示不同的元素时使用 --> <!-- 默认插槽写法 --> <!-- 父组件 --> <Student> <!-- 需要插入的内容 --> <img src=""> </Student> <!-- 子组件 --> <div> <!-- 父组件传入插槽的内容 --> <slot>使用者没有传入插槽 会将我展示</slot> </div> <!-- style 可以在 父/子 组件书写 -->
<!-- 多个插槽写法 --> <!-- 父组件 --> <Student> <!-- 需要插入的内容 --> <img src="" slot="slot名称1"> <vido src="" slot="slot名称2"> <!-- template写法 template标签 不影响结构--> <!-- slot:slot名称1 为 vue2.7 更新的写法 只能在 template标签中使用 --> <template slot="slot名称1" slot:slot名称1> <h1>我是h1</h1> <div>我是div</viv> </template> </Student> <!-- 子组件 --> <div> <!-- 父组件传入插槽的内容 --> <slot name="slot名称1">使用者没有传入插槽 会将我展示</slot> <slot name="slot名称2">使用者没有传入插槽 会将我展示</slot> </div> <!-- style 可以在 父/子 组件书写 -->
<!-- 作用域插槽写法 --> <!-- 父组件 --> <Student> <!-- 作用域必须使用 template 标签 传参 作用域 --> <template scop="Obj"> <!-- games msg 在Obj中 --> <h1>{{Obj.games}}</h1> <h1>{{Obj.msg}}</h1> </template> </Student> <!-- 子组件 --> <div> <!-- 子组件插槽中给父组件传参 --> <slot :games="games" msg="这里是msg信息">使用者没有传入插槽 会将我展示</slot> </div> <!-- style 可以在 父/子 组件书写 -->
多组件共享数据 状态 = 数据
1.npm i vuex
2.import Vuex from 'vuex' // 在 index.js 中 引入
// vue2 -> vuex3
// vue3 -> vuex4
3.Vue.use(Vuex)
Vue({
store:"hello",
})
// 在 vm 中 出现 $store 保存传入的数据
在components同级文件夹下添加 store 文件夹
添加 index.js
// 该文件用于创建 Vuex 中最为核心的store // 引入 import Vue from 'vue' import Vuex from 'vuex' // 应用Vuex插件 Vue.use(Vuex) // 准备 actions const actions = { // 需要dispatch的函数 "函数名"(context,value){ console.log('actions 中的函数被调用了',context,value); // 分配给 其他 dispatch 分段处理 便于维护代码 context.dispatch("函数2",value); context.commit("函数名(使用大写与actions进行区分)",value); } } // 准备 mutations 操作 data // 开发者工具 检测 mutations const mutations = { "大写函数名"(state,value){ state.value += value; } } // 准备 state 用于存储数据 全局 data const state = {e // 准备数据 value:0, // 改变后会替代 vc 里的 data } // 实现全局的 计算属性 computed const getters = { // 对 state 进行加工 bigSum(state){ return state.sum*10; } } // 创建并暴露 store export default new Vuex.Store({ actions, mutations, state, })
main.js
import store from './store/index.js'
// 配置项中添加store
new Vue({
store
})
js 执行 import 全部 import 会被提升到最高层
vue 规定必须 先 ues(vuex) 再 创建 store 实例
使用2.import Vuex from ‘vuex’
// vue2 -> vuex3
// vue3 -> vuex4
3.Vue.use(Vuex)
methds:{
this.$store.dispatch("事件名",传入的数据);
// 直接跨过action
this.$store.commit("事件名",传入的数据);
// 获得计算属性
this.$store.getters.bigSum;
}
可直接夸过 Actions 进行 Commit 调用 mutation 的函数
vuex 开发者工具 历史记录符号
回到该次数据 历史记录符号
可以删除历史记录 禁用符号
合并记录 下载符号
底部分 可以 导入导出 / 粘贴复制
ES6 语法
let Obj1 = {x:1,y:2}
let Obj2 ={
z:3,
...Obj1, // 直接将Obj1的键值对插入
m:7,
}
import {mapState} from 'vue'
// 映射 State 中的数据
computed:{
// 借助mapState生成计算属性 从state中读取数据
...mapState({sum:'sum',adress:'adress'}) // 可直接在计算属性中添加
// 不可简写 对象简写方式为 {sum:sum} === {sum} !== {sum:"sum"}
// Vue 可识别 简写方法 与上述方法用途一致
...mapState(['sum','subject'])
// 全局计算属性获取
...mapGeters(['bigSum'])
}
import {mapState} from 'vue'
// 映射 State 中的数据
methods:{
// 数组 / 对象 形式默认生成方法 需要在调用时传参
/*add(value){
this.$store.commit('add',value)
}*/
...mapActions(['add']),
...mapMutations(['add'])
}
index.js
import Vuex from 'vuex' // 计数相关属性 const countOptions = { // 配置该项可在 组件 中使用更简洁的写法 namespaced:true, // 与正常 vuex 配置完全一致 action:{}, mutation:{}, state:{}, getter:{}, } // 人员相关属性 const personOptions = { action:{}, mutation:{}, state:{}, getter:{}, } export default new Vuex.Store({ modules:{ countAbout:countOptions, personAbout:personOptions } })
// 组件中简写使用
computed:{
// 普通简写
// 调用 state时 需要使用 countAbout.data
...mapState(['countAbout','personAbout']),
// 需要在 vuex 中 开启 namespaced
// 调用时 直接使用 data 就可以
...mapState('countAbout',['data']),
...mapState('personAbout',['data']),
// 其他 map 同理使用
// getter 模块化之后 值为 countAbout/bigSum countAbout不再为对象
}
单页面应用 路由改变 页面局部刷新 (没有全部刷新)
使用 vue 的插件库 vue-router
npm install -g vue-router
/*
vue-router 3 版本对应 vue 2
vue-router 4 版本对应 vue 3
*/
// npm install vue-router@3
在 components 同级文件夹下创建 router 文件夹
index.js
// 引入 vue-router import Vuerouter from 'vue-router' // 引入组件 import TheList from '../components/TheList.vue'; import AboutSnowman from '../components/AboutSnowman.vue'; // 创建 并 暴露 一个路由器 export default new VueRouter({ routes: [ { path:"/TodoList", component:TheList, }, { path:"/about", component:AboutSnowman, }, // path 为 * 表示匹配全部 可以匹配全部路径 路径匹配为从上至下 { path:"*", component:AboutSnowman, }, ] })
main.js
// 引入 路由器
import router from './router'
new Vue({
render: h => h(App),
// 设置 router
router:router,
}).$mount('#app')
<!-- 最终 在 html 页面中转化为 a 标签 -->
<!-- to 为跳转到的路由 -->
<!-- active-class 为在该路由时应用的 样式 -->
<router-link to="/TodoList" active-class="active">每日清单</router-link>
<router-link to="/about" active-class="active">关于我的主页</router-link>
<!-- 视图展示 对应路由的位置 -->
<router-view></router-view>
在 components 同级文件夹下创建 pages 文件夹
便于分类 pages存放 路由组件 components文件夹存放 一般组件
原理 : {不断销毁与挂在组件}
index.js
// 引入 vue-router import VueRouter from 'vue-router' // 引入组件 import TheList from '../components/TheList.vue'; import AboutSnowman from '../components/AboutSnowman.vue'; // 创建 并 暴露 一个路由器 export default new VueRouter({ routes: [ // 一级路由 { path:"/TodoList", component:TheList, // 路由嵌套从这里开始 // 二级路由 children:[{ // 第二级不需要加 / 会出问题 path:"new", component:TheList, }] }, // 一级路由 { path:"/about", component:AboutSnowman, }, ] })
<!-- 最终 在 html 页面中转化为 a 标签 -->
<!-- to 为跳转到的路由 -->
<!-- active-class 为在该路由时应用的 样式 -->
<!-- 二级路由必须携带父亲级路由的路径 -->
<router-link to="/TodoList/new" active-class="active">每日清单</router-link>
<router-link to="/about/new" active-class="active">关于我的主页</router-link>
<!-- 视图展示 对应路由的位置 -->
<router-view></router-view>
query参数 get传参
<router-link to="/TodoList/new?name=雪人&age=18" active-class="active">每日清单</router-link> <!-- 加 v-bind + ES6 `` 动态传参 --> <router-link :to="`/TodoList/new?name=${name}&age=${age}`" active-class="active">每日清单</router-link> <!-- 对象式 传参 --> <router-link :to="`{ path="/TodoList/new", query:{ name:name, age:age, } } `" active-class="active">每日清单</router-link> <router-link to="/about/new" active-class="active">关于我的主页</router-link>
// 组件中获取
this.$route.query.name
this.$route.query.age
export default new VueRouter({ routes: [ { // 配置姓名 简化传参 name:'ListName', path:"/TodoList", component:TheList, children:[{ // 配置姓名 简化传参 name:'new', path:"new", component:TheList, }] }, ] })
<!-- 对象式 传参 -->
<!-- 使用 name 必须使用对象式 -->
<router-link :to="`{
// 此处直接传入 路由器 定义的名字
name:"ListName",
query:{
name:name,
age:age,
}
}
`" active-class="active">每日清单</router-link>
<!-- params参数 传参 需要配置占位符 -->
<router-link :to="`/TodoList/new/11/王二`" active-class="active">每日清单</router-link>
<!-- params参数 对象式 -->
<router-link :to="`{
// params 只能使用name path会报错!!!
name:"ListName",
params:{
id:11,
name:"王二",
}
}
`" active-class="active">每日清单</router-link>
export default new VueRouter({ routes: [ { // 添加占位符设置参数 name:'ListName', path:"/TodoList/:id/:name", component:TheList, children:[{ // 添加占位符设置参数 name:'new/:id/:name', path:"new", component:TheList, }] }, ] })
// 组件中获取
this.$route.params.name
this.$route.params.age
export default new VueRouter({ routes: [ { name:'ListName', path:"/TodoList/:id/:name", component:TheList, children:[{ name:'new/:id/:name', path:"new", component:TheList, // props 写法一 // 该对象中的所有 key-value 都会以props的形式传给 组件 TheList中 props:{id:1,name:'hello'}, // props 写法二 // props值为布尔值,若布尔值为真,就会把该参数的 params值当做 props 值传递给组件 props:true, // props 写法三 // 值为函数 返回值 以props 传递给组件 // $route 被回调传入 真好 props($route){ return {id:$route.query.id,name:'hello'} } // 结构赋值写法 props({query}){ return {id:query.id,name:query.name} } }] }, ] })
默认为push记录 栈的不断添加
replace 替换当前记录 不能返回
<!-- 开启replace :replace="true" -->
<router-link to="/TodoList/new" active-class="active" :replace="true">每日清单</router-link>
<!-- 开启replace 简写方式 -->
<router-link to="/about/new" active-class="active" replace>关于我的主页</router-link>
在 $router 中 直接操作 不借助 router-link
<template> <button @click="showPush"> push查看 </button> <button @click="showReplace"> replace查看 </button> <button @click="back"> 后退 </button> <button @click="forward"> 前进 </button> <button @click="go"> 前进 </button> </template> <script> export default { name:'Message', methods:{ showPush(){ // 调用 $router 上的API this.$router.push({ name:"xiangqing", query:{ id:'11', name:'王二', } }) }, showReplace(){ // 调用 $router 上的API this.$router.replace({ name:"xiangqing", query:{ id:'11', name:'王二', } }) }, back(){ this.$router.back }, forward(){ this.$router.forward }, go(){ // 正数 前进 n 次 // 复数 后退 n 次 this.$router.go(n) }, } } </script>
组件切走时会被销毁 内容消失 如何保存?
需要保存数据的去缓存
<!-- inlude="" 配置需要缓存的组件 否则缓存全部组件 -->
<!-- 防止组件被销毁 数据丢失 -->
<keep-alive inlude="组件名">
<router-view></router-view>
</keep-alive>
<!-- 缓存多个组件 -->
<keep-alive :inlude="['组件名1','组件名2','组件名3']">
<router-view></router-view>
</keep-alive>
用于路由组件的 开启定时器 比 mounted更高效
methods:{
activated(){
// 开启定时器
},
deactivated(){
// 定时器自动关闭
}
}
保护路由的安全 验证数据库再展示
全局前置路由守卫
export default new VueRouter({ routes: [ { path:"/TodoList", component:TheList, // 用于存放用户需要的特殊数据 // 可以在判断中进行索引 不指定默认为 undefined 为 false meta:{isAuth:true,title:"每日清单"}, } ] }) // 全局前置路由守卫 // to 路由去向 路由对象 // from 路由由来 路由对象 // next 回调函数 使用 next()才能切换路由 router.beforeEach((to,from,next)=>{ if(to.path === '/home'){ // 利用meta判断 if(from.meta.isAuth){ next() } next() } next() }) export default router
// 全局后置路由守卫
// 无 next 路由跳转已经完成后触发
router.afterEach((to,from)=>{
// 可在跳转完成后更改路由
doucment.title = to.meta.title || '网页标题' // 短路判断
})
export default new VueRouter({ routes: [ { path:"/TodoList", component:TheList, // 用于存放用户需要的特殊数据 // 可以在判断中进行索引 不指定默认为 undefined 为 false meta:{isAuth:true,title:"每日清单"}, // 独享路由守卫 仅有前置 无后置 beforeEnter:(to,from,next)=>{ if(...){ next() } } } ] })
<script>
mounted(){
// 通过路由器规则 进该组件时被调用
// 在beforeEnter 之前
// to 一定是该组件路由
beforeRouteEnter(to,from,next){
},
// 通过路由器规则 离开该组件时被调用
// from 一定是该组件路由
beforeRouteLeave(to,from,next){
}
}
</script>
main.js
// hash 带 # 兼容性好 不美观
// history 不带 # 兼容性差(相对) 美观 会寻找服务器路径资源 容易出错(后端解决)
new VueRouter({
// 设置模式
mode:history,
})
>>> npm run build
// 生成 dist 文件夹
// 为打包后的 css js html 文件
// 直接点击 index.html 无法运行必须在服务器部署
如何部署服务器
node.js express 框架
->npm init
->text_serve 包名
->npm i express
中间件解决 history 模式 404问题
->npm i connect-history-api-fallback
// 在 server.js 同级目录下 新建 js
const express = require('express') const history = require('connect-history-api-fallback') const app = express() // 解决history 404 问题 app.use(history) // 默认选择 index.html app.use(express.static(__dirname+"./static")) app.get('/person',(req,res)=>{ res.send({ name:'tom', age:18 }) }) app.listen(5005,(err)=>{ if(!err) console.log('服务器启动成功了!') })
7.1 移动端常用组件库
7.2PC端常用UI组件库
直接用就行
此处介绍Element UI
->npm i element-ui
import Vue from 'vue';
import ElementUI from 'element-ui';
// 引入全部样式
import 'element-ui/lib/theme-chalk/index.css';
import App from './App.vue';
// 此处use 后 会注册全部组件为全局组件
// 引入的 js 非常大 7.2M(别用)
Vue.use(ElementUI);
new Vue({
el: '#app',
render: h => h(App)
});
按需引入
-> npm install babel-plugin-component -D 按需引入的库 -D为开发依赖(开发环境)
需要修改 babel.config.js 配置
module.exports = { presets: [ // vue 相关js '@vue/cli-plugin-babel/preset', // element ui 预设 // ["es2015", { "modules": false }] 官网没更新 旧版脚手架的 ["@babel/preset-env", { "modules": false }], // 两个都试一下 版本问题 ["@babel/env", { "modules": false }] ], // element ui 插件 "plugins": [ [ "component", { "libraryName": "element-ui", "styleLibraryName": "theme-chalk" } ] ] }
main.js
// 按需引入
import {Button,Row,...} from 'element-ui'
// 配置之后会引入需要的 css 而不是全部css
import 'element-ui/lib/theme-chalk/index.css';
// Button 的组件名 可以自定义
// 注册全局组件
VUe.component(Button.name,Button)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。