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,父传子

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

<template>
	<div id="father">
		<Son :message="d"></Son>
	</div>
</template>
<script>
  import Son from './son/Son';
  export default {
	data() {
		return {
			message: '信息'
		}
	},
	components: {
		Son
	}
}
</script>

在子组件中使用 props 接收

<template>
	<div id="son">
		子组件:{{message}}
	</div>
</template>
<script>
  export default {
  props: ["message"],
	data() {
		return {
			
		}
	}
}
</script>

*** props 两种写法

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

props: ["message"]

2,子传父

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

<template>
	<div id="son">
		<button @click="send">发送给父组件</button>
	</div>
</template>
<script>
  export default {
  props: ["message"],
	data() {
		return {
			message: '信息'
		}
	},
  methods: {
		send() {
			this.$emit('sendText', 'aaaaa')
		}
	},
}
</script>

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

<template>
	<div id="father">
		<Son v-on:sendText="getText"></Son>
	</div>
</template>
<script>
  import Son from './son/Son';
  export default {
	data() {
		return {
			message: '信息'
		}
	},
  methods: {
		getText(data) {
      // 接收的参数
			console.log(data)
		}
	},
	components: {
		Son
	}
}
</script>

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.创建局部指令

<template>
	<div id="demo">
		<div v-dir1></div>
	</div>
</template>

<script>
export default {
	data() {
		return {

		}
	},
  // 自定义局部指令
	directives:{
		dir1:{
			inserted(el){
				console.log(el)
				console.log(arguments)
				// 操作dom
				el.style.width = "200px"
				el.style.height = "200px"
				el.style.backgroundColor = "red"
			}
		}
	}
}
</script>

2.创建全局指令

在main.js中创建全局指令

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

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

1.创建局部指令

<template>
	<div id="demo">
		<h3>{{txt1|text_arr}}</h3>
	</div>
</template>

<script>
export default {
	data() {
		return {
			txt1:"123"
		}
	},
  // 自定义局部指令
	//  局部过滤器
	filters: {
		text_arr(data) {
			console.log(data)
			let str = '456'
			return str
		}
	},
}
</script>

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标签,分别根据什么条件显示什么功能),同时该文件导出的数据为一个对象。

<template>
    <div :class="type == 'Default'?'btn default':type == 'primary'?'btn primary':type == 'danger'?'btn danger':'btn default'">
        <slot></slot>
    </div>
</template>

<script>
export default {
    name:"alley-Button",
    props:{
        type:{
            type:String,
            default:"Default"
        }
    }
}
</script>


<style>
    .btn{
         width: 100px;
         height: 40px;
         color:#fff;
         text-align: center;
         line-height:40px;
    }
    .default{
       
        background: red;
       
    }

     .primary{
      
        background: yellow;
    }

     .danger{
     
        background: #ccc;
    }
</style>

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中可以进行使用了。

<template>
   <div id="app">
     <alley-Button>按钮</alley-Button>
     <alley-Button type="primary">按钮</alley-Button>
     <alley-Button>按钮</alley-Button>
     <alley-Button>按钮</alley-Button>
   </div>
 </template>
 
 <script>

 export default {
   name: 'app',
  
 }
 </script>
 
 <style>
 
 </style>

十三、vue插槽的使用

匿名插槽

子组件中写入slot插槽

<template>
<div id="son">
    今天天气怎么样
    <slot>
    </slot>
</div>
</template>

<script>
export { default } from './index.js'
</script>

<style lang="less" scoped>
@import url("./index.less");
</style>

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

<template>
	<div id="father">
		<div>我是父组件</div>
		<div style="margin-top: 30px">
			<child>
				<div>多云</div>
			</child>
		</div>
		<!-- <router-view></router-view> -->
	</div>
</template>
<script>
import child from './pages/index.vue'
export default {
	data(){
		return {

		}
	},
	create(){

	},
	components:{
		child
	}
}
</script>

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

匿名插槽解析

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

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

<template>
<div id="son">
    <slot name="header">
    </slot>
    <slot name="footer">
    </slot>
</div>
</template>

<script>
export { default } from './index.js'
</script>

<style lang="less" scoped>
@import url("./index.less");
</style>

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

<template>
	<div id="father">
		<div>我是父组件</div>
		<div style="margin-top: 30px">
			<child>
				<template v-slot:header>
					<h1>头部</h1>
				</template>
				<template v-slot:footer>
					<h1>尾部</h1>
				</template>
			</child>
		</div>
		<!-- <router-view></router-view> -->
	</div>
</template>
<script>
import child from './pages/index.vue'
export default {
	data(){
		return {

		}
	},
	create(){

	},
	components:{
		child
	}
}
</script>

十四、vue this.$nexTick使用

this.$nexTick()解析

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

<template>
	<div id="parent">
		<div ref="messageDiv">{{ message }}</div>
		<br />
		<br />
		<br />
		<div>这个是没用的nextTick获得的消息:{{ messageOne }}</div>
		<br />
		<br />
		<br />
		<div>这个是我用的nextTick后获得的消息:{{ messageTwo }}</div>
		<br />
		<br />
		<br />
		<button @click="changeMsg">改变数据</button>
	</div>
</template>
<script>
import child from './pages/index.vue'
export default {
	data() {
		return {
			message: '这是我的测试消息',
			messageOne: '',
			messageTwo: ''
		}
	},
	create() {

	},
	methods: {
		changeMsg() {
			this.message = "我改变了测试消息"
			this.messageOne = this.$refs.messageDiv.innerHTML;
			this.$nextTick(() => {
				this.messageTwo = this.$refs.messageDiv.innerHTML;
			})
		}
	},
	components: {
		child
	}
}
</script>

十五、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. 不带参数
 
<router-link :to="{name:'home'}"> 
<router-link :to="{path:'/home'}"> //name,path都行, 建议用name  
// 注意:router-link中链接如果是'/'开始就是从根路由开始,如果开始不带'/',则从当前路由开始。
 
 
 
2.带参数
 
<router-link :to="{name:'home', params: {id:1}}">  
 
// params传参数 (类似post)
// 路由配置 path: "/home/:id" 或者 path: "/home:id" 
// 不配置path ,第一次可请求,刷新页面id会消失
// 配置path,刷新页面id会保留
 
// html 取参  $route.params.id
// script 取参  this.$route.params.id
 
 
<router-link :to="{name:'home', query: {id:1}}"> 
 
// 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/01@3x.png"),
					texts:"书籍容量"
				}
			]

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue.js是一种流行的JavaScript框架,用于构建用户界面。如果你想学习Vue.js,以下是一些值得推荐的入门学习资料PDF。 1. Vue.js官方文档:Vue.js官方文档是学习Vue.js最重要的资料之一。它提供了详细的教程和示例,涵盖了Vue.js的所有重要概念和功能。官方文档以清晰简洁的方式解释了Vue.js的工作原理,对于初学者来说非常友好。 2. Vue.js权威指南:Vue.js权威指南是一本由Vue.js核心团队编写的书籍。它深入探讨了Vue.js的各个方面,从基础知识到高级主题都有涉及。该书提供了丰富的示例和练习,能够帮助你更好地理解和应用Vue.js。 3. Vue.js实战:这是一本实用指南,重点介绍如何在实际项目中使用Vue.js。该书提供了一系列实际案例,涵盖了Vue.js的常见应用场景和最佳实践。通过学习这些案例,你可以加深对Vue.js的理解,并学习如何将其应用到自己的项目中。 4. Vue.js视频教程:如果你更喜欢通过视频学习,有很多免费的Vue.js视频教程可供选择。这些视频教程通常由经验丰富的开发者或教育机构制作,讲解了Vue.js的基础知识和实战技巧。通过跟随这些视频教程,你可以从头开始学习Vue.js,并且能够实时观看代码示例和演示。 总的来说,学习Vue.js需要一些基础的JavaScript和HTML/CSS知识,但这些资料将帮助你快速入门并掌握Vue.js的核心概念和技巧。无论你选择哪种学习方法,重要的是要坚持练习和实践,这样你才能真正掌握Vue.js并将其应用到实际项目中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值