JS表达式

  • 函数(方法)调用表达式
test() //函数调用表达式
  • 属性调用表达式
var obj = {name:'wt'};
var arr = [123,'bai'];
obj.name   //属性调用表达式
arr[0]     //属性调用表达式
  • 变量(常量)调用表达式
let name = 'wutao';
name  //变量调用表达式
  • 字面量表达式
123         //数值字面量表达式
'wtao'      //字符串字面量表达式
true        //布尔字面量表达式
null        //空表达式
undefined   //未定义表达式
{name:'wt'} //对象字面量表达式
[123,true]  //数组字面量表达式
  • 算术表达式
a + 1       //算术表达式
b * 1       //算术表达式
  • 三目表达式
conidion ? name : title

模板语法

  • 插值
// 语法:     双大括号{{}}
// 使用场景: 标签内容处使用
// 单向数据绑定
// 支持JS表达式

<div id="app">
    {{msg}}
    <div>{{getContent()}}</div>
</div>

<script>
    const vue = new Vue({
        el: '#app',
        data: {
            msg: 'who is this'
        },
        methods: {
            getContent: function(){
                return 'wtao';
            }
        }
    });
</script>
插值v-text 区别
两者都是在标签内容处插入内容,但v-text是全量插入,而插值更灵活,除了全量插入,还可以使用部分插入
推荐只要使用插值就可以了
  • 指令
是模板语法重中之重,常用如下
v-text     //使用插值替代
v-html     
v-show
v-if       //条件判断
v-else
v-else-if
v-for      //循环
v-on       //绑定事件
v-bind     //绑定属性
v-model    //双向数据绑定
v-pre
v-cloak
v-once

指令

  • 属性绑定
// 单向数据绑定
// 支持JS表达式
// 使用指令v-bind,需传入标签属性作为参数,例如:v-bind:title=""

<div id="app">
    <div title="你好" :title="go">xxx</div>
    <p :title="test()"></p>
</div>
<script>
    const vue = new Vue({
        el: '#app',
        data: {
            go: '振东',
            test: function(){
                return 'xxx';
            }
        }
    });
</script>

出现上面的情况,属性谁后谁显示,原理是后面替代前面如果title在:title后面,那单向数据绑定失效
如果是使用函数,必须后面加括号调用()
1、数值型   :title="123"             等同于  title="123"
2、布尔型   :title="true"            等同于  title="true"   //false时,属性消失
3、字符串   :title="'go'"            等同于  title="go"
4、对象     :title="{name:'wt'}"     等同于  title="[Object object]" 
5、数组     :title="[123,true,'bb']" 等同于  title="true,ok,123"
  • 事件绑定
<div id="app">
    <div v-html="title" @click="fngo"></div>

    <div v-html="title" @click="getUser"></div>
</div>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            name:'wt',
            title: '<h1>试试</h1>',
            fngo: function(){
                console.log(this);   // this代表window
            }
        },
        methods: {
            getUser: function(){
                console.log(this);   // this代表Vue实例
            }
        }
    });
</script>
注意如果改为如下代码,this将发生变化
<div id="app">
    <div v-html="title" @click="fngo()"></div>

    <div v-html="title" @click="getUser"></div>
</div>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            name:'wt',
            title: '<h1>试试</h1>',
            fngo: function(){
                console.log(this);   // this代表Vue实例
            }
        },
        methods: {
            getUser: function(){
                console.log(this);   // this代表Vue实例
            }
        }
    });
</script>
所有函数(方法)的定义,强烈推荐放在methods里,不要定义到data里面
  • 条件判断渲染
// 单向数据绑定
// 支持JS表达式

<div v-if="0"></div>    //数字0 --> false
<div v-else-if="'0'"></div>    //字符串0 ---> true
<div v-else></div>
注意点:
1、对象和数组转boolean都是true
2、空字符串转boolean是false
3、null、underfined、NaN转boolean是false
4、数值0是false
let arr = []
if(arr){
    console.log('true');
}

if(arr == fasle){
    console.log('true');  // ==两边转数值
}
  • 循环渲染
// 单向数据绑定
// 支持JS表达式
// items可以是数字、字符串、数组、对象

<ul id="example-1">
  <li v-for="item in 15">
    {{ item.message }}
  </li>
</ul>

<ul id="example-1">
  <li v-for="(item,key) in 'abcd'">
    {{ item }} : {{ key }}
  </li>
</ul>

<ul id="example-1">
  <li v-for="(item,key) in {name:'taobi',age:18}">
    {{ item }} : {{key}}
  </li>
</ul>

双向/单向数据动态绑定__原理

  • 单向
var obj = {};
var initValue = 'hello';
Object.defineProperty(obj,"newKey",{
    get:function (){
        //当获取值的时候触发的函数
        return initValue;
    },
    set:function (value){
        //当设置值的时候触发的函数,设置的新值通过参数value拿到
        initValue = value;
    }
});
//获取值
console.log( obj.newKey );  //hello   输出

//设置值
obj.newKey = 'change value';

console.log( obj.newKey ); //change value
console.log( initValue );  //change value
  • 双向
var obj = {};
var initValue = 'hello';
Object.defineProperty(obj,"newKey",{
    get:function (){
        //当获取值的时候触发的函数
        return initValue;
    },
    set:function (value){
        //当设置值的时候触发的函数,设置的新值通过参数value拿到
        initValue = value;
    }
});
document.getElementById('txt').oninput = function(e){
    obj.newKey = e.target.value;
}

单页应用 vs 多页应用

  • 多页应用
页面跳转 ---> 返回html

优点:
首屏速度快,SEO效果好

缺点:
页面切换慢
  • 单页应用
页面跳转 ---> JS动态渲染

优点:
页面切换快

缺点:
首屏速度慢,SEO差

Vue 实例

  • 分类

图片描述

  • 根实例组件实例区别
1、是否有挂载
    有---根实例
    没---组件实例
    
2、文件后缀
    .js---根实例
    .vue--组件实例
    
3、写法
    手动new Vue()---根实例
    导出export default {}---组件实例

组件

  • 组件是什么?与模块有什么不同?
使用Vue构建单页应用,单页应用由Vue单文件组件组成,所谓组件指的就是Vue单文件组件(包含模板、样式、交互)
模块指的就是JS模块(单纯包含JS代码)
使用ES6模块化导入

1、路径问题

nodejs内置模块与npm安装的第三方模块,直接引用
import Vue from 'vue';
import http from 'http';

自定义模块或自定义组件,要带路径引用
./ 代表 当前文件所在路径
../代表 当前文件父级所在路径
import App from './App.vue';
import App from '../App.vue';

2、后缀问题(无后缀,先判断是否是文件,找不到再判断是否是目录)

当省略后缀,只会匹配js/json/node后缀文件
所以当你要导入css、vue单文件组件时,就必须加上后缀
如果导入的是文件夹(包),将按如下顺序查找:
<1>查找 package.json 下是否定义了 main 字段,是则读取 main 字段下定义的入口。
<2>如果没有 package.json 文件,则读取文件夹下的 index.js 或者 index.node。
<3>如果都 package.json、index.js、index.node 都找不到,抛出错误 Error: Cannot find module 'some-library'。

链接描述

组件与模块最大区别是:是否要注册
使用流程

组件(.vue): 导入——>注册——>使用
模块(.js):   导入——>使用
  • 组件之间关系
1、嵌套关系(父子、爷孙)
2、非嵌套关系(兄弟、表叔与我)
  • 组件定义的三大区域
1、模板 <template> 0~1个
2、脚本 <script>   0~1个
3、样式 <style>    0~n个

组件间通信

  • 通信方式
1、父子组件间通信

   1>通过props  父向子传递数据,单向,响应
   2>通过引用   $root/$refs/$parent/$children  
   3>通过自定义事件   $on/$emit/$once/$off
   4>通过vuex   (推荐)

2、兄弟组件间通信

   1>通过事件   $on/$emit/$once/$off
   2>通过vuex   (推荐)
  • 自定义事件通信
原则:谁发起自定义事件,谁就注册处理自定义事件函数
// 父级
this.$refs.customComp.$on('custom-event',function(){});

// 子级
this.$emit('custom-event');
还有另外一种写法

Vuex 集中式状态管理

  • 安装与使用
1、安装
npm i vuex -S

2、导入
import Vue from 'vue';
import Vuex from 'vuex';

3、安装插件
Vue.use(Vuex);

4、定义一个仓库并导出
export default new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  }
});

5、在vue根实例中注入store
import store from './store'

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')
初始化Vue根实例时,自动注入两个插件,分别是$router与$store,以后直接this.$store使用
  • 状态是什么?有哪些分类?
状态就是数据

状态的分类:
1、组件级别 --- 组件内部的数据,只允许内部操作
2、应用级别 --- 多组件共享的数据,整个应用都可以操作,而且是响应式的,适用于层级很深的
Vuex 就是集中存储 应用级别状态
  • 获取状态
在Vuex的store中如此定义
export default new Vuex.Store({
  state: {
    count: 0
  }
});

在模板中
<p>{{$store.state.count}}</p>

在脚本中
this.$store.state.count
  • 修改状态
必须使用mutation来对Vuex存储的状态进行修改,修改方式类似处理事件
export default new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {     // state参数自动注入
      state.count++
    }
  }
});

在模板中
<button @click="$store.commit('increment')">改变</button>

在脚本中
this.$store.commit('increment')
修改要传值时,该如何写?
1、只能传一个参数,建议传一个对象,代码如下:

export default new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state,payload) {     // state参数自动注入
      state.count += payload.num;
    }
  }
});

在模板中
<button @click="$store.commit('increment',{num:12})">改变</button>

在脚本中
this.$store.commit('increment',{num:12});
  • 使用注意
1、不要在组件中直接在data选项中绑定状态,如下

export default {
    name: 'about',
    data() {
        return {
            title: this.$store.state.num
        }
    }
}

如果修改状态后,data中数据不会发生响应,因此推荐使用计算属性,代码修改如下

export default {
    name: 'about',
    data() {
        return {
            
        }
    },
    computed: {
        title(){
            return this.$store.state.num;
        }
    }
}

Vue Router 路由器

单页应用,遇到第一个<router-view>标签开始适配/根路由
如果<router-view>中有<router-view>,那必须要配有嵌套路由,否则里面的<router-view>没有内容

Vue内置组件 <keep-alive>

  • 作用
在路由切换时,组件继续缓存在内存里,无需销毁,性能高,用户体验更好

PS: 原本路由切换时,组件是销毁的
  • 适用场景
1、缓存的组件必须是对实时性没有要求
2、缓存的组件必须是一级路由的组件,对二级、三级路由组件无效

例如:一级路由的组件不需要缓存的,但二级路由的组件需要缓存,那么会导致一级路由组件也会缓存下来,所以不符合使用需求

104828720
1.4k 声望222 粉丝

编程其实很枯燥,所以一定要有追求。


« 上一篇
前端基础_ES6
下一篇 »
前端基础_CSS