Web前端流行框架之一 ,使用DOM模板,采用MVVM(Model-View-ViewModel)设计模式,中心思想是一切都是组件,数据驱动
脚手架的概念:原本我们需要自己去搭建一个框架结构,例如
├─index.html
│
├─css
│ style.css
│
├─img
└─js
theme.js
现在通过脚手架工具直接搭建好,默认一个项目结构,方便阅读以及统一标准
最终访问是public里面的index.html,是由入口mian.js 将 App.vue 挂载到 index.html 中的 id=“app”
因为.vue文件浏览器不认识,所以必须要有loader支撑,vue2.x采用webpack
# 安装文本webpack前端资源打包工具
npm instal webpack -g
npm instal webpack-cli -g
# 安装vue2.x脚手架
npm instal vue-cli -g
# 指定webpack为项目模板
vue init webpack vueproject
#### vue -V 或 vue --version 查看版本,当使用Vue Cli 3.x 时需先卸载 2.x ####
npm uninstall vue-cli -g
# 安装3.x
npm install @vue/cli -g
# 创建项目
vue create vueproject
# Web版vue项目创建管理可视化工具
vue ui
# VS Code中打开vueproject项目运行
npm run dev
创建Vue3的项目时,建议使用Vite
Vite 与 Vue CLI 类似,Vite 也是一个提供基本项目脚手架和开发服务器的构建工具。然而,Vite 并不是基于 Webpack 的,它有自己的开发服务器,利用浏览器中的原生 ES 模块。这种架构使得 Vite 比 Webpack 的开发服务器快了好几个数量级。Vite 采用 Rollup 进行构建,速度也更快。
<div id="app">
{{value}}
div>
<script>
var vm = new Vue({
el: '#app',
data:{
value: 'Vue实例绑定成功'
}
})
script>
只用于单向输入输出,不会视图驱动操作数据
指令 v-bind
例如<img v-bind:src="value" />
常用简写 :value(class src id title)
<img :src="value" />
# 对象写法
:class="{className:true,className:true}"
# 常用三元运算符判断
:class='currentIndex==index ? "className" : "" '
# 数组写法
:class="[className,className]"
v-for="(item,index) in arrs :key=(index)"
原理是将节点创建与删除,性能较低
v-if="value"
原理是显示与隐藏节点 style="display:none"; style="display:block";之间切换,value数据为布尔值
当用户频繁切换时使用,避免耗费性能,因为是操作css
v-show="value"
v-on:click="function"
监听事件常用简写 @click="function"
例如富文本编辑器内容
v-html
会通过操作DOM由视图驱动数据变化
v-model="value"
获取原生DOM里面的根id,一般为#app
this.$el = document.querySelector(options.el)
this.$data = options.data;
获取节点,根据节点的类型进行判断,针对 {{value}} 进行正则取值后赋值进行编译解析,获取事件@click也大体相同
/\{\{(.*?)\}\}/g
劫持data属性,保证页面的value与$data中定义的值保持一致,再采用观察者watch,劫持数据变化后操作DOM更新保证数据改变后视图层DOM进行改变,否则数据变动但是视图不变
将数据进行拦截后格式化处理
<div>{{value|function}}div>
<script>
filters:{
function(value){
console.log(value)
}
}
script>
{{str + “123”}} ===> str123
computed 根据响应式进行缓存数据,也就是说如果data中相应的值没变不会去重新计算,无论在当前页面调用几次,只要数据没变化,第一次计算后数据就缓存了,不会再重新去计算
围绕data属性变换,复杂逻辑时计算模板表达式会很乱
虽然是函数计算,但是调用时还是以表达式写{{function}},不要出现{{function()}}
methods 没有缓存,不管data中的值有没有变化,只要模板中调用时都会去重新计算,也就是说模板渲染就会去执行,耗费性能
但是如果是调用methods里面的函数时需要{{function()}}
<Child :value = "value" :prop = "prop">Child>
<template>
<div>
{{value}}
div>
template>
<script>
export default{
props:['value','prop'],
data(){
return{
}
}
}
script>
通过自定义事件
<template>
<div>
{{value}}
<button @click = "btn">传值按钮button>
div>
template>
<script>
export default{
data(){
return{
value:"我是子组件的数据",
}
},
methods:{
btn(){
this.$emit('childEvent',this.value)
}
}
}
script>
<Child @childEvent = "function">Child>
<script>
import Child from './components/Child'
export default{
components:{
Child
},
data(){
return{
parentValue:"",
}
},
methods:{
//val表示子组件传过来的值
function(val){
this.parentValue = val;
}
}
}
script>
通过一个中间通道 bus.js
import Vue from 'vue'
export default new Vue;
<template>
<div>
{{avalue}}
<button @click = "btn">传值按钮button>
div>
template>
<script>
import bus from './bus'
export default{
data(){
return{
avalue:"我是A组件的数据",
}
},
methods:{
btn(){
bus.$emit('aEvent',this.avalue)
}
}
}
script>
<template>
<div>
我是B组件,接收兄弟A组件的值
{{value}}
div>
template>
<script>
import bus from './bus'
export default{
data(){
return{
value:"",
}
},
computed:{
bShow(){
//这里的res就是avalue
bus.$on('aEvent',(res)=>{
this.value = res;
})
}
}
}
script>
slot
在组件中默认可活动的部分
<slot>
<div>我可以在其它调用此组件的地方更换div>
slot>
<Component>
<div>我将原插槽位置替换掉div>
Component>
SPA,单页面应用,前端路由不刷新页面,操作盒子,保证只有一个url
展示的部分是
<router-view />
标签跳转形式
<router-link :to="{name: 'UserCenter'}">个人中心router-link>
<router-link :to="{path: '/userCenter'}">个人中心router-link>
<router-link to='/userCenter'><i class="el-icon-user-solid">i>个人中心router-link>
tag属性,默认为a标签,可进行更改
<router-link :to="{name: 'UserCenter'}" tag="span">个人中心router-link>
<router-link :to="{name: 'UserCenter'}" tag="div">个人中心router-link>
路径传值
<router-link :to="{name: 'UserCenter',query:{value:value}}" tag="span">个人中心router-link>
js跳转方式
this.$router.push('/url') #打开新页面,可以返回上一页
this.$router.replace('/url') #打开新页面,不能返回上一页
this.$router.go() #打开新页面,跳转几层
this.$router.back() #返回上一页
传值方式
this.$router.push({
path:'/url',
query:{
value:value
}
});
接收值方式
this.$route.query.value
路由模式
hash
会在地址栏加#,更近似于锚点
history
地址栏没有#
router.beforeEach
router.afterEach
router.beforeRouteEnter
router.beforeRouteUpdate
router.beforeRouteLeave
router.beforeEnter
// to: 即将要进入的目标
// from: 当前导航正要离开的路由
// next: 可以接收参数的方法,例如地址,next是必须要有的,没有无法跳转,也就是说它是最后一道守卫,必须跟它打招呼
// next(),跳到to指的方向; next(false) 中断跳转; next('/') 直接指定某个路径
router.beforeEach((to, from, next) => {
if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
// 如果不加else用户未能验证身份,则 `next` 会被调用两次
else next()
})
store 商店的概念,数据在多个地方使用,谁要用某个数据直接来拿,避免每次请求后台来送数据,状态管理模式,采用集中式存储数据,管理所有组件的状态
import Vue from 'vue'
import Vuex from 'vuex'
import menus from "./modules/menus";
Vue.use(Vuex)
export default new Vuex.Store({
// 放数据的地方,类似于data,但是在外部组件引用中不能修改数据,只能在这里的mutations中修改
state: {
// 设定全局token
token: '',
value:"",
list:[{
good_id:1,
good_name:"衣服",
good_num:3,
good_price:55,
},
{
good_id:2,
good_name:"鞋子",
good_num:5,
good_price:88,
}],
networkData:[],
},
// 计算属性,类似于computed
getters: {
total(state){
let obj = {
count:0,
num:0
}
state.list.forEach(g=>{
//总价
obj.count += g.good_num * g.good_price;
//总数量
obj.num += g.good_num;
})
return obj;
}
},
// 存放方法,类似于methods,是同步的
mutations: {
SET_TOKEN: (state, token) => {
state.token = token
localStorage.setItem("token", token)
},
changeValue(state):{
state.value = "abc";
},
//进行组件请求后传过来的data存储到state中,方便其它组件直接调用
initData(state,data){
state.networkData = data;
}
},
// 类似于mutations,可以提交mutations,而不是直接变更状态,可以包含异步操作
actions: {},
// 防止单个store臃肿,划分为多个store,加入m
modules: {
menus
}
})
# state取数据方式
{{this.$store.state.value}}
# state computed取数据方式
{{value}}
{{token}}
import {mapState} from 'vuex'
computed:{
...mapState(['value','token'])
}
# getters取数据方式
{{total.num}}
{{total.price}}
import {mapGetters} from 'vuex'
computed:{
...mapGetters(['total'])
}
# mutations外部组件调用
{{value}}
{{token}}
<button @click="changeValue"></button>
import {mapState,mapMutations} from 'vuex'
computed:{
...mapState(['value','token'])
},
methods:{
...mapMutations(['changeValue','initData'])
}
this.$axios.get("/url")
.then((res) => {
this.initData(res.data);
}).catch((res) => {
console.log(res.message);
});
因为事件是需要用户进行触发的,例如点击事件、键盘事件等,前提是必须拥有触发条件
watch能自动的监听当前Vue对象的数据变化来调用事件处理
watch:{
$route(to,from){
console.log(to.path,from.path)
}
}
data(){
return{
value:"",
arr:[
a:""
],
}
},
watch:{
value(newVal,oldVal){
console.log("显示新值",newVal,"---->","显示旧值",oldVal)
}
//深度监听
arr:{
handler(newVal,oldVal){
console("监听arr里面a的值变化",newVal.a)
},
deep:true
}
}
vue中每个组件都是独立的,都有自己的生命周期(钩子函数),实例初始化—>创建—>数据初始化—>挂载—>更新—>销毁
共有四对八个,都是函数
# 未挂载数据及页面对象
beforeCreate
# 数据已绑定,未挂载页面对象
created
# 数据未关联到$el
beforeMount
# 数据挂载$el完毕,并通过插值表达式展示到页面相应位置
mounted
beforeUpdate
updated
beforeDestory
destoryed
Vue.component()
Vue.use()
Vue.mixin()
<transition>
transition>
node_modules 项目依赖包安装目录
public 放置静态文件目录
src
|—assets 放置静态文件
|—components 放置公共组件,方便后期在页面中引用
|—router 路由,地址映射控制器
|—store 状态管理器,方便数据的共享,全局状态的统一管理
|—views 存放页面
App.vue 入口页面,在main.js里被调用
main.js 整个项目的启动入口,需在此进行全局引入配置
import Element from "element-plus"
import "element-plus/theme-chalk/index.css"
import axios from 'axios'
Vue.prototype.$axios = axios //定义全局引用变量
Vue.config.productionTip = false
createApp(App).use(Element).use(store).use(router).mount('#app')
npm install axios --save
GET写法
this.$axios({
url:"xxx",
params:{}
}).then(res=>{
console.log(res)
})
POST写法
this.$axios({
url:"xxx",
data:{}
}).then(res=>{
console.log(res)
})