Vue 基础知识

文章目录

  • Vue.js
    • 1. 单向绑定
    • 2. 列表渲染
    • 3. 条件渲染
    • 4. 显示隐藏
    • 5. 事件处理
    • 6. 插入HTML内容
    • 7. 双向绑定
    • 8. 过滤器
    • 9. 计算属性
    • 10. 组件传值
      • 10.1. 父组件传值给子组件
      • 10.2. 子组件传值给父组件
      • 10.3. 兄弟组件之间传值
    • 11. 插槽
    • 12. 插件
      • 12.1. Router
        • 12.1.1. 导航守卫(地址拦截)
      • 12.2. Vuex
    • 13. 状态监听
    • 14. 生命周期
    • 15. 全局API
    • 16. 过渡动画
    • 17. 项目目录
    • 18. 安装辅助工具

Vue.js

Web前端流行框架之一 ,使用DOM模板,采用MVVM(Model-View-ViewModel)设计模式,中心思想是一切都是组件,数据驱动

JQuery属于DOM驱动
Vue 基础知识_第1张图片

脚手架的概念:原本我们需要自己去搭建一个框架结构,例如

├─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>

1. 单向绑定

只用于单向输入输出,不会视图驱动操作数据

指令 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]"

2. 列表渲染

v-for="(item,index) in arrs :key=(index)"

3. 条件渲染

原理是将节点创建与删除,性能较低
v-if="value"

4. 显示隐藏

原理是显示与隐藏节点 style="display:none"; style="display:block";之间切换,value数据为布尔值
当用户频繁切换时使用,避免耗费性能,因为是操作css
v-show="value"

5. 事件处理

v-on:click="function"
监听事件常用简写 @click="function"

6. 插入HTML内容

例如富文本编辑器内容
v-html

7. 双向绑定

会通过操作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进行改变,否则数据变动但是视图不变

8. 过滤器

将数据进行拦截后格式化处理

<div>{{value|function}}div>

<script>
filters:{
    function(value){
        console.log(value)
    }
}
script>    

9. 计算属性

{{str + “123”}} ===> str123

computed 根据响应式进行缓存数据,也就是说如果data中相应的值没变不会去重新计算,无论在当前页面调用几次,只要数据没变化,第一次计算后数据就缓存了,不会再重新去计算
围绕data属性变换,复杂逻辑时计算模板表达式会很乱
虽然是函数计算,但是调用时还是以表达式写{{function}},不要出现{{function()}}

methods 没有缓存,不管data中的值有没有变化,只要模板中调用时都会去重新计算,也就是说模板渲染就会去执行,耗费性能
但是如果是调用methods里面的函数时需要{{function()}}

10. 组件传值

10.1. 父组件传值给子组件

<Child :value = "value" :prop = "prop">Child>

<template>
    <div>
    {{value}}
    div>
template>


<script>
    export default{
        props:['value','prop'],
        data(){
            return{
                
            }
        }
    }
script>

10.2. 子组件传值给父组件

通过自定义事件

<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>

10.3. 兄弟组件之间传值

通过一个中间通道 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>

11. 插槽

slot

在组件中默认可活动的部分

<slot>
<div>我可以在其它调用此组件的地方更换div>
slot>
<Component>
<div>我将原插槽位置替换掉div>
Component>

12. 插件

12.1. Router

SPA,单页面应用,前端路由不刷新页面,操作盒子,保证只有一个url

  1. 切换页面组件
  2. 路径传值
  3. 拦截

展示的部分是

<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 地址栏没有#

12.1.1. 导航守卫(地址拦截)
  • 全局守卫
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()
})

12.2. Vuex

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);
              });

13. 状态监听

因为事件是需要用户进行触发的,例如点击事件、键盘事件等,前提是必须拥有触发条件

watch能自动的监听当前Vue对象的数据变化来调用事件处理

  1. 监听路由的变化
watch:{
    $route(to,from){
        console.log(to.path,from.path)
    }
}
  1. 监听数据变化
data(){
   return{
       value:"", 
       arr:[
       	a:""
       ],
        }
   },
        
watch:{
	value(newVal,oldVal){
	    console.log("显示新值",newVal,"---->","显示旧值",oldVal)
	}
	//深度监听
	arr:{
		handler(newVal,oldVal){
			console("监听arr里面a的值变化",newVal.a)
		},
		deep:true
	}
	
}

14. 生命周期

vue中每个组件都是独立的,都有自己的生命周期(钩子函数),实例初始化—>创建—>数据初始化—>挂载—>更新—>销毁

共有四对八个,都是函数

# 未挂载数据及页面对象
beforeCreate
# 数据已绑定,未挂载页面对象
created

# 数据未关联到$el
beforeMount
# 数据挂载$el完毕,并通过插值表达式展示到页面相应位置
mounted

beforeUpdate
updated

beforeDestory
destoryed

15. 全局API

  • 注册自定义组件
Vue.component()
  • 在Vue中安装插件
Vue.use()
  • 在Vue中的每个组件注入自定义行为
Vue.mixin()

16. 过渡动画

<transition>

transition>

17. 项目目录

node_modules 项目依赖包安装目录

public 放置静态文件目录

src

|—assets 放置静态文件

|—components 放置公共组件,方便后期在页面中引用

|—router 路由,地址映射控制器

|—store 状态管理器,方便数据的共享,全局状态的统一管理

|—views 存放页面

App.vue 入口页面,在main.js里被调用

main.js 整个项目的启动入口,需在此进行全局引入配置

18. 安装辅助工具

  • 使用Element UI、axios
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')
  • axios: 类ajax的http库
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)
})

你可能感兴趣的:(#,Vue,vue.js,前端框架)