VUE 入门学习

一、对MVVM的理解?

MVVM:就是Model-View-ViewModel 的缩写

Model:表示数据模型,在model中定义数据修改和业务逻辑

View:表示视图层,负责将数据转化为UI展示出来

ViewModel:监听模型数据的改变和控制视图行为,以及用户交互,也就是同步model和view的对象,ViewModel通过双向数据绑定将view层和model层连接起来,而View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理。

二、Vue的生命周期

beforeCreate:(创建前),数据观测和初始化事件还未开始

created:(创建后),完成数据观测,属性和方法的运算,初始化事件,此时$el属性还未显示出来

beforeMount:(载入前),在 e l 被 新 创 建 的 v m . el被新创建的vm. elvm.el替换,并挂载到实例上去之后调用,实例以及完成以下配置:用上面编译好的html内容替换$el属性指向DOM对象,完成模型中的html渲染到html页面中,此过程进行ajax 交互。

beforeUpdate:(更新前),在数据更新之前调用,发生在DOM重新渲染和打补丁之前,可以在该钩子中进一步更新状态,不会触发附加的重新渲染过程。

updated(更新后) 在由于数据更改导致的虚拟DOM重新渲染和打补丁之后调用。调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作。然而在大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。该钩子在服务器端渲染期间不被调用。

beforeDestroy(销毁前) 在实例销毁之前调用。实例仍然完全可用。
destroyed(销毁后) 在实例销毁之后调用。调用后,所有的事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务器端渲染期间不被调用。

1.什么是vue生命周期?

答:vue从创建到销毁就是生命周期,从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、销毁等一系列过程,称之为 Vue 的生命周期。

2.vue生命周期的作用是什么?

答:它的生命周期中有多个事件钩子,让我们在控制整个Vue实例的过程时更容易形成好的逻辑。

3.vue生命周期总共有几个阶段?

答:它可以总共分为8个阶段:创建前/后, 载入前/后,更新前/后,销毁前/销毁后。

4.第一次页面加载会触发哪几个钩子?

答:会触发 下面这几个beforeCreate, created, beforeMount, mounted 。

5.DOM 渲染在 哪个周期中就已经完成?

答:DOM 渲染在 mounted 中就已经完成了。

三、 Vue实现数据双向绑定的原理:Object.defineProperty()

vue实现双向数据绑定主要采用数据劫持结合发布者-订阅者模式,通过Object.defineProperty()来劫持个个属性的setter,getter,在数据发生变化时通知订阅者,触发相应的回调函数,

简单的js实现双向绑定

<body>
    <div id="app">
    <input type="text" id="txt">
    <p id="show"></p>
</div>
</body>
<script type="text/javascript">
    var obj = {
     }
    Object.defineProperty(obj, 'txt', {
     
        get: function () {
     
            return obj
        },
        set: function (newValue) {
     
            document.getElementById('txt').value = newValue
            document.getElementById('show').innerHTML = newValue
        }
    })
    document.addEventListener('keyup', function (e) {
     
        obj.txt = e.target.value
    })
</script>

四、Vue组件间的参数传递

1,父传子

在父组件中引入子组件,在自定义属性名



在子组件中使用 props 接收



*** props 两种写法

props: {
 	name: {
  	type: String,
  	default:'Kobe Bryant'
 }
}

props: ["message"]

2,子传父

子组件通过点击事件触发,$emit方法传送参数



在父组件中用$on接收子组件传递过来的参数



3,非父子组件传值

使用eventBus.js文件,相当于一个中转站,用于接收和发送事件,项目小的时候可以使用

步骤如下:

创建Bus.js文件

import Vue from "vue";
export default new Vue();

第一个组件 first.vue

import Bus from '../bus.js';
export default {
  name: 'first',
  data () {
    return {
      value: '我来自first.vue组件!'
    }
  },
  methods:{
    add(){// 定义add方法,并将msg通过txt传给second组件
      Bus.$emit('txt',this.value);
    }
  }
}

第二个组件second.vue

import Bus from '../bus.js';
export default {
  name: 'second',
  data () {
    return {
    }
  },
  mounted:function(){
    Bus.$on('txt',function(val){//监听first组件的txt事件
      console.log(val);
    });
  }
}

五、Vue的路由实现:hash模式 和 history模式

**hash模式:**在浏览器中符号“#”,#以及#后面的字符称之为hash,用window.location.hash读取;
特点:hash虽然在URL中,但不被包括在HTTP请求中;用来指导浏览器动作,对服务端安全无用,hash不会重加载页面。
hash 模式下,仅 hash 符号之前的内容会被包含在请求中,如 http://www.xxx.com,因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回 404 错误。

**history模式:**history采用HTML5的新特性;且提供了两个新方法:pushState(),replaceState()可以对浏览器历史记录栈进行修改,以及popState事件的监听到状态变更。
history 模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致,如 http://www.xxx.com/items/id。后端如果缺少对 /items/id 的路由处理,将返回 404 错误。Vue-Router 官网里如此描述:“不过这种模式要玩好,还需要后台配置支持……所以呢,你要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。”

六、vue路由的钩子函数

首页可以控制导航跳转,beforeEach,afterEach等,一般用于页面title的修改。一些需要登录才能调整页面的重定向功能。

beforeEach主要有3个参数to,from,next:

to:route即将进入的目标路由对象,

from:route当前导航正要离开的路由

next:function一定要调用该方法resolve这个钩子。执行效果依赖next方法的调用参数。可以控制网页的跳转。

七、vuex是什么?怎么使用?哪种功能场景使用它?

只用来读取的状态集中放在store中; 改变状态的方式是提交mutations,这是个同步的事物; 异步逻辑应该封装在action中。
在main.js引入store,注入。新建了一个目录store,…… export 。
场景有:单页应用中,组件之间的状态、音乐播放、登录状态、加入购物车

state
Vuex 使用单一状态树,即每个应用将仅仅包含一个store 实例,但单一状态树和模块化并不冲突。存放的数据状态,不可以直接修改里面的数据。
mutations
mutations定义的方法动态修改Vuex 的 store 中的状态或数据。
getters
类似vue的计算属性,主要用来过滤一些数据。
action
actions可以理解为通过将mutations里面处里数据的方法变成可异步的处理数据的方法,简单的说就是异步操作数据。view 层通过 store.dispath 来分发 action。

const store = new Vuex.Store({ //store实例
      state: {
         count: 0
             },
      mutations: {                
         increment (state) {
          state.count++
         }
          },
      actions: { 
         increment (context) {
          context.commit('increment')
   }
 }
})

modules
项目特别复杂的时候,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。

const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
 }
const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
 }

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
})

八、vue-cli如何新增自定义指令?

1.创建局部指令




2.创建全局指令

在main.js中创建全局指令

// 自定义全局指令
Vue.directive("dir1", {
     
  inserted(el) {
     
    el.style.width = '200px';
    el.style.height = '200px';
    el.style.background = 'red';
  }
})

九、vue如何自定义一个过滤器?

1.创建局部指令




2.创建全部指令

在main.js中注册全局过滤器

// 全局过滤器
Vue.filter('str_change', (data) => {
     
    console.log(data)
})

十、$refs的基本用法

1、$refs的三种用法

  • ref 加在普通的元素上,用this.$refs.(ref值) 获取到的是dom元素
  • ref 加在子组件上,用this. r e f s . ( r e f 值 ) 获 取 到 的 是 ∗ ∗ 组 件 实 例 , 可 以 使 用 组 件 的 所 有 方 法 ∗ ∗ 。 在 使 用 方 法 的 时 候 直 接 t h i s . refs.(ref值) 获取到的是**组件实例,可以使用组件的所有方法**。在使用方法的时候直接this. refs.ref使使this.refs.(ref值).方法() 就可以使用了。
  • 如何利用 v-for 和 ref 获取一组数组或者dom 节点

2、应注意的坑:

1、如果通过v-for 遍历想加不同的ref时记得加 :号,即 :ref =某变量 ;
这点和其他属性一样,如果是固定值就不需要加 :号,如果是变量记得加 :号。(加冒号的,说明后面的是一个变量或者表达式;没加冒号的后面就是对应的字符串常量(String))

2、通过 :ref =某变量 添加ref(即加了:号) ,如果想获取该ref时需要加 [0],如this.$refs[refsArrayItem] [0];如果不是:ref =某变量的方式而是 ref =某字符串时则不需要加,如this.$refs[refsArrayItem]。

1、ref 需要在dom渲染完成后才会有,在使用的时候确保dom已经渲染完成。比如在生命周期 mounted(){} 钩子中调用,或者在 this.$nextTick(()=>{}) 中调用

2、如果ref 是循环出来的,有多个重名,那么ref的值会是一个数组 ,此时要拿到单个的ref 只需要循环就可以了。

十一、vue触发input的点击事件

html
<Button @click="choiceImg" icon="ios-cloud-upload-outline" type="primary">点击上传</Button>
<input ref="filElem" type="file" >

script
choiceImg(){
     
    this.$refs.filElem.dispatchEvent(new MouseEvent('click')) 
},

十二、Vue封装组件(以button 为例子)

1,在components文件内创建一个button文件,文件内创建一个index.vue文件,在index.vue文件内写的是原型(包含组件的名字,应用的最底层的HTML标签,分别根据什么条件显示什么功能),同时该文件导出的数据为一个对象。







2.在button文件下建立一个index.js文件,文件内对新构建组件的名字进行注册。

import Button from "./index.vue";

 Button.install = (Vue)=>{
     
    Vue.component(Button.name,Button)
}

export default Button;

3.与button文件同级建立一个index.js文件,对组件进行注册,同时也注册进install中,在导出时,不仅要引出全局的,而且单个的也要引出,便于局部或全局引用。

import Button from "./button"

 const components = [
     Button
 ]
 
 //vue。use使用时,必须要有install方法。参数就是vue。
 const install  = (Vue)=>{
     
     for(var key in components){
     
         Vue.component(components[key].name,components[key])
     }
 }
 
 export default {
     
     install,
     Button
 }

4.在main.js中进行引用

import Vue from 'vue'
 import App from './App.vue'
 import AlleyUI from "./components"
 Vue.config.productionTip = false
 Vue.use(AlleyUI);
 
 new Vue({
     
   render: h => h(App),
 }).$mount('#app')

5.到这里,组件便是封装完成了,在App.vue中可以进行使用了。


 
 
 
 

十三、vue插槽的使用

匿名插槽

子组件中写入slot插槽






父组件中往注册的子组件中填充内容



总结:父组件填充内容到子组件标签中,子组件写上slot插槽,则会显示填充的内容

匿名插槽解析

具名插槽其实就是给插槽娶个名字。一个子组件可以放多个插槽,而且可以放在不同的地方,而父组件填充内容时,可以根据这个名字把内容填充到对应插槽中

子组件中写入多个具名插槽






父组件中使用“v-slot:插槽名称”



十四、vue this.$nexTick使用

this.$nexTick()解析

将回调函数延迟到下次 DOM 更新循环之后执行,修改数据之后立即使用它



十五、vue修饰符号.sycn

一个组件只能定义一个v-model双向数据绑定,如果其他的也要用到双向数据绑定,则使用.sycn修饰符

场景:父组件传值 子组件弹出窗

父组件中使用自组件

<Alerts :alerts.sync="alert_type" v-on:update:alerts="alert_type=$event"></Alerts>

子组件中接受参数

props: {
     
		alerts: {
     
			type: Boolean,
			default: ''
		},
	},

子组件关闭窗口

_this.$emit('update:alerts', false)
// 父组件中
v-on:update:alerts="alert_type=$event"

其他按钮触发弹窗

修改点击按钮的绑定值

@click="alerts_=true"
// 利用计算属性传值
 computed:{
        alerts_:{
            get(){
                return this.alerts
            },
            set(val){
                this.$emit('update:alerts',val)
            }
        }
    }

十六、vue路由跳转的4种方法(带参数)

1. router-link

1. 不带参数
 
 
 //name,path都行, 建议用name  
// 注意:router-link中链接如果是'/'开始就是从根路由开始,如果开始不带'/',则从当前路由开始。
 
 
 
2.带参数
 
  
 
// params传参数 (类似post)
// 路由配置 path: "/home/:id" 或者 path: "/home:id" 
// 不配置path ,第一次可请求,刷新页面id会消失
// 配置path,刷新页面id会保留
 
// html 取参  $route.params.id
// script 取参  this.$route.params.id
 
 
 
 
// query传参数 (类似get,url后面会显示参数)
// 路由可不配置
 
// html 取参  $route.query.id
// script 取参  this.$route.query.id


2. this.$router.push() (函数里面调用)

1.  不带参数
 
this.$router.push('/home')
this.$router.push({
     name:'home'})
this.$router.push({
     path:'/home'})
 
 
 
2. query传参 
 
this.$router.push({
     name:'home',query: {
     id:'1'}})
this.$router.push({
     path:'/home',query: {
     id:'1'}})
 
// html 取参  $route.query.id
// script 取参  this.$route.query.id
 
 
 
3. params传参
 
this.$router.push({
     name:'home',params: {
     id:'1'}})  // 只能用 name
 
// 路由配置 path: "/home/:id" 或者 path: "/home:id" ,
// 不配置path ,第一次可请求,刷新页面id会消失
// 配置path,刷新页面id会保留
 
// html 取参  $route.params.id
// script 取参  this.$route.params.id
 
 
 
4. query和params区别
query类似 get, 跳转之后页面 url后面会拼接参数,类似?id=1, 非重要性的可以这样传, 密码之类还是用params刷新页面id还在
 
params类似 post, 跳转之后页面 url后面不会拼接参数 , 但是刷新页面id 会消失


注意*** 由于动态路由也是传递params的,所以在this.$router.push() 的方法中, path不能和params一起使用,否则params将无效。需要用name来指定页面。

及通过路由配置的name属性访问

3. this.$router.replace() (用法同上,push)

区别在于,这个方法不会向history里面添加新的记录,点击返回,会返回到上上个记录,上一个记录是不存在的。

4. this.$router.go(n)

相对于当前页面向前或向后跳转多少个页面,类似 window.history.go(n)。n可为正数可为负数。正数返回上一个页面

this.$router.go(n)
向前或者向后跳转n个页面,n可为正整数或负整数

ps : 区别

this. r o u t e r . p u s h 跳 转 到 指 定 u r l 路 径 , 并 想 h i s t o r y 栈 中 添 加 一 个 记 录 , 点 击 后 退 会 返 回 到 上 一 个 页 面 t h i s . router.push 跳转到指定url路径,并想history栈中添加一个记录,点击后退会返回到上一个页面 this. router.pushurlhistory退this.router.replace
跳转到指定url路径,但是history栈中不会有记录,点击返回会跳转到上上个页面 (就是直接替换了当前页面)

this.$router.go(n)
向前或者向后跳转n个页面,n可为正整数或负整数

十七、vue中js给html赋值图片路径

直接给路径不会生效,需要require引入,图片才会在页面中生效

// js中
progoImgs: [
				{
     
					img: require("@/pages/user/images/[email protected]"),
					texts:"书籍容量"
				}
			]

本文属于个人积累,如果不对,还请指出!

你可能感兴趣的:(vue)