Vue基础
Vue.js
不支持IE8
及其以下版本,渐进式:易用、灵活、高效
实例化对象
new Vue({
el:"#vue-app",//el需要获取的元素,一定是html中的根容器关系
data:{//data用于数据的存储
fruits:['apple','banana','melon'],
users:[
{name:'li',age:10},
{name:'chen',age:11},
{name:'wang',age:12},
]
},
computed:{
},
methods:{//method用于存储各种方法
getName:function(){
return this.name;
}
}
})
//this.data.fruits wrong,this.fruits right
//this.methods.getName() wrong,this.getName() right
绑定属性和方法
v-bind:title="message" v-bind:id v-bind:disabled v-bind:href
:title="message" :id :disabled :href
v-model="message"
v-html="rawHtml"
v-on:click="reverseMessage" v-on:click="reverseMessage()"
@click.once="reverseMessage" @click="reverseMessage()"
v-on:dblclick
v-once
v-on:mousemove.stop .stop .once .prevent
v-on:keyup.enter
<div v-bind:class="{ active: isActive }"></div>
<div v-bind:class="classObject"></div>
<div v-bind:class="[activeClass, errorClass]"></div>
<div v-bind:style="{ fontSize: fontSize + 'px' }"></div>
<div v-bind:style="styleObject"></div>
<div v-bind:style="[baseStyles, overridingStyles]"></div>
v-if="seen" v-else-if v-else v-show
v-for="item in items"//数组
v-for="item of items"
v-for="(item, index) in items"
v-for="value in object"//对象
v-for="(value, key) in object"
v-for="(value, key, index) in object"
v-for="n in 10"
如何实现数据双向绑定?
方法一:v-model
方法二:this.$refs.name.value
<template name="Login">
<div>
<h1>Login</h1>
<form>
<label>用户名<input type="text" ref="name" v-on:keyup="getName">{{name}}</label><br/><br/>
<label>密码<input type="text" v-model="age">{{age}}</label>
</form>
</div>
</template>
<script>
export default {
name:"Login",
data(){
return{
name:"",
age:""
}
},
methods:{
getName:function(){
this.name=this.$refs.name.value;
}
}
}
</script>
如何区别methods和computed?
computed基于它的依赖缓存,只有在它的相关依赖发生改变时才会重新取值。
methods无论谁改变时都会重新取值。
换句话:methods里面的方法,若有一个被执行,其他也会被执行;computed不会。
computed 与methods
1、效果上两个都是一样
2、computed 是基于它的依赖缓存,只有相关依赖发生改变时才会重新取值。
而使用 methods ,在重新渲染的时候,函数总会重新调用执行。
可以说使用 computed 性能会更好,但是如果你不希望缓存,你可以使用 methods 属性。
3、computed 属性默认只有 getter ,不过在需要时你也可以提供一个 setter
computed: {
reversedMessage: function () {
return this.message.split('').reverse().join('')
}
}
<p>Computed reversed message: "{{ reversedMessage }}"</p>
methods: {
reverseMessage: function () {
return this.message.split('').reverse().join('')
}
}
<p>Reversed message: "{{ reverseMessage() }}"</p>
如何快速搭建大型单页应用(脚手架的使用)?
# 最新稳定版
$ npm install vue -g
# 全局安装 vue-cli
$ npm install vue-cli -g
# 创建一个基于 webpack 模板的新项目
$ vue init webpack my-project [-y]
或者 $ vue init webpack-simple my-project [-y]
# 安装依赖
$ cd my-project
$ npm install
$ npm run dev
/*index.html-->main.js-->App.vue
*App.vue
*1、模板<template>:html结构(有且只有一个根标签)
*2、行为<script>:处理逻辑
*3、样式<style scoped>:解决样式
*/
组件怎么使用?
全局组件/局部组件
//全局注册
//main.js
import Users from './components/Users'
Vue.component("users",Users);
//App.vue
<users></users>
//局部注册
//App.vue
import Users from './components/Users'
export default{
//components:{Users}
components:{
"users":Users
}
}
<users></users>
//User.vue
<template>
<div class="users">
<ul><li v-for="user in Users">{{user}}</li></ul>
</div>
</template>
<script>
export default {
name:"users",
data(){
return { Users:['Lily','Lucy','Rose']}
}
}
</script>
<style scoped></style>
CSS怎么使用?
//App.vue
<h1>App.vue</h1>
//User.vue
<h1>Users.vue</h1>
//方式一:结果全部颜色为color:purple
//App.vue
<style>h1{color:purple;}</style>
//方式二:结果全部颜色为color:salmon
//App.vue
<style>h1{color:purple;}</style>
//User.vue
<style>h1{color:salmon;}</style>
//方式三:结果分别为自己的颜色
//App.vue
<style>h1{color:purple;}</style>
//User.vue
<style scoped>h1{color:salmon;}</style>
Vue如何传值?
传值:string number boolean
传引用:object array
父组件向子组件传值如何实现(传值/传引用)?
父组件:<users v-bind:users="UsersInfo" v-bind:title="title"></users>
子组件:props: ['users','title']
子组件向父组件传值如何实现(值改变)?
子组件:
<h1 v-on:click="changeTitle">{{title}}</h1>
changeTitle:function(){this.$emit("titleChanged","子向父传值")}
父组件:
<users v-bind:users="UsersInfo" v-bind:title="title" v-on:titleChanged="updateTitle($event)"></users>
updateTitle(title){this.title=title;}
生命周期

解析:
执行beforeCreate函数 data上还是undefined
执行created函数 数据已经和data属性进行绑定
created钩子函数和beforeMount间的生命周期
1、判断对象是否有el选项
如果没有el选项,则停止编译,也就意味着停止了生命周期,直到在该vue实例上调用vm.$mount(el)
当Vue实例没有el属性时,则该实例尚没有挂载到某个dom中;
假如需要延迟挂载,可以在之后手动调用vm.$mount()方法来挂载。
const app = new Vue({
router
}).$mount('#app')
const app = new Vue({
router,
el:"#app"
})
如果有el选项,转步骤2
2、判断对象有没有render函数
如果有render函数,执行render函数的内容
如果没有render函数,转步骤3
3、判断对象是否有template选项
如果没有template选项,则将外部HTML作为模板编译
如果有template选项,则将其作为模板编译成render函数
结论:render函数选项 > template选项 > outer HTML
执行beforeMount函数 el上还是undefined
执行mounted函数 el存在值
beforeCreate
-组件实例化之前执行的函数
created
-组件实例化完毕,但页面还未显示
beforeMount
-组件挂载前,页面还未显示,但虚拟Dom已经配置
mounted
-组件挂载后,此方法执行后,页面显示
beforeUpdate
-组件更新前,页面仍未更新,但虚拟Dom已经配置
updated
-组件更新,此方法执行后,页面显示
beforeDestroy
-组件销毁前
destroyed
-组件销毁
路由的使用?
npm i vue-router -D
//router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import Users from '../components/Users'
Vue.use(Router)
export default new Router({
routes: [
{path:"/users",component:Users}
],
mode:'history'
})
//main.js
import router from './router'
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
//App.vue
<router-view></router-view>
<router-link to='/users'>go to users</router-link>
如何自定义指令和过滤器?
<template>
<div id="show-blog" v-theme:column="'narrow'">
<h1>博客总览</h1>
<input type="text" v-model="search" placeholder="搜索">
<div v-for="blog in filteredBlogs" class="single-blog">
<h2 v-rainbow>{{blog.title | to-uppercase}}</h2>
<article>{{blog.body | snippet }}</article>
</div>
</div>
</template>
全局定义
//全局指令
Vue.directive('rainbow',{
bind(el,binding,vnode){
el.style.color="#"+Math.random().toString(16).slice(2,8);
}
})
Vue.directive('theme',{
bind(el,binding,vnode){
if(binding.value=="wide"){
el.style.maxWidth="1260px";
}else if(binding.value='narrow'){
el.style.maxWidth="500px";
}
if(binding.arg=='column'){
el.style.background="#6677cc";
el.style.padding="20px";
}
}
})
//全局过滤器
Vue.filter("to-uppercase",function(value){
return value.toUpperCase();
})
Vue.filter("snippet",function(value){
return value.slice(0,100)+"...";
})
局部定义
computed:{
filteredBlogs:function(){
return this.blogs.filter((blog)=>{
return blog.title.match(this.search);
})
}
},
filters:{
"to-uppercase":function(value){
return value.toUpperCase();
},
"snippet":function(value){
return value.slice(0,100)+"...";
}
},
directives:{
'rainbow':{
bind(el,binding,vnode){
el.style.color="#"+Math.random().toString(16).slice(2,8);
}
},
'theme':{
bind(el,binding,vnode){
if(binding.value=="wide"){
el.style.maxWidth="1260px";
}else if(binding.value='narrow'){
el.style.maxWidth="500px";
}
if(binding.arg=='column'){
el.style.background="#6677cc";
el.style.padding="20px";
}
}
}
}
vue项目main.js文件下import router from './router'默认导入router文件夹下index.js的原因?
a.把router当作文件,从指定路径开始,依次查找router、router.js、router.json、router.node不存在
b.把router当作目录,从指定路径开始,依次查找router/package.json(main)、router/index.js、router/index.json、router/index.node,找到router/index.js,返回该文件
关于import About from '@/components/About'中@是什么?
webpack.base.conf.js文件中的resolve里面的alias
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src')
}
}
qs
qs是一个npm仓库所管理的包,可通过npm install qs
qs.parse()将URL解析成对象的形式
qs.stringify()将对象 序列化成URL的形式,以&进行拼接
lodash
_.debounce
是一个通过 lodash
限制操作频率的函数
参考: https://lodash.com/docs#debounce
请问最终 span-a 和 span-b 中分别展示什么字符串?
只有当实例被创建时 data 中存在的属性才是响应式的。当这些数据改变时,视图会进行重渲染。
案例一:
<div id="app">
<span class=span-a>
{{obj.a}}
</span>
<span class=span-b>
{{obj.b}}
</span>
</div>
var app = new Vue({
el: '#app',
data: {
obj: {
a: 'a',
}
},
})
app.obj.b = 'b'
span-a 中显示a,span-b 中不显示
案例二:
<div id="app">
<span class=span-a>
{{obj.a}}
</span>
<span class=span-b>
{{obj.b}}
</span>
</div>
var app = new Vue({
el: '#app',
data: {
obj: {
a: 'a',
}
},
})
app.obj.a = 'a2'
app.obj.b = 'b'
span-a 中显示a2,span-b 中显示b
解析:
要理解为什么 span-b 会更新,要点是理解视图更新其实是异步的。
a、当我们让 a 从 'a1' 变成 'a2' 时,Vue 会监听到这个变化,但是 Vue 并不能马上更新视图,因为 Vue 是使用 Object.defineProperty 这样的方式来监听变化的,监听到变化后会创建一个视图更新任务到任务队列里。(文档有写)
b、所以在视图更新之前,要先把余下的代码运行完才行,也就是会运行 b = 'b'。
c、等到视图更新的时候,由于 Vue 会去做 diff(文档有写),于是 Vue 就会发现 a 和 b 都变了,自然会去更新 span-a 和 span-b。
5、模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。所以,对于 Vue 模板中任何复杂逻辑,你都应当使用计算属性。