Vue基础

2018-12-11  本文已影响0人  爱笑的疯小妞

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

生命周期

image.png
解析:
执行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 模板中任何复杂逻辑,你都应当使用计算属性。

上一篇 下一篇

猜你喜欢

热点阅读