<span v-text="msg"></span>
<!-- 二者等价 -->
<span>{{msg}}</span>
复制代码
v-html:javascript
<div v-html="rawHtml"></div>
复制代码
<div id="app">
<input v-model="somebody">
<p>hello {{somebody}}</p>
</div>
<script> var app = new Vue({ el: '#app', data: { somebody:'小明' } }) </script>
复制代码
上面这个例子中直接在浏览器input中输入别的名字,下面的p的内容会直接跟着变。这就是双向数据绑定。css
v-model:仅仅是一个语法糖,至关于
:value
+@input
html![]()
input
事件:当输入框中的数据改变时发生
<a v-bind:href="hrefname">百度</a>
<a :href="hrefname">百度</a>
<script> var app = new Vue({ el:"#app", data: { hrefname:"http://www.baidu.com", } }) </script>
复制代码
<a v-if="ok">yes</a>
复制代码
若是属性值ok为true,则显示。不然,不会渲染这个元素。前端
<a v-if="ok">yes</a>
<a v-else>No</a 复制代码
<div v-if="type``='A'">
A
</div>
<div v-if="type``='B'">
B
</div>
<div v-if="type``='C'">
C
</div>
<div v-else>
Not A,B,C
</div>
复制代码
<h1 v-show="ok">hello world</h1>
复制代码
也是用于根据条件展现元素。和v-if不一样的是,若是v-if的值是false,则这个元素被销毁,不在dom中。可是v-show的元素会始终被渲染并保存在dom中,它只是简单的切换css的dispaly
属性。vue
注意:v-if有更高的
切换开销
v-show有更高的初始渲染开销。 所以,若是要很是频繁的切换,则使用v-show较好;若是在运行时条件不太可能改变,则v-if较好java
特别提醒
node
v-show
须要放到一个真实的dom上,不能放在template
上面webpack
v-for 遍历数组ios
<p v-for="(value,index) in links">{{value}}</p>
复制代码
注意:在使用v-for过程当中,要绑定惟一的key
,key尽可能不要绑定index,若是有id尽可能绑定id
git
<p v-for="(value,index) in links" :key="index">{{value}}</p>
特别提醒
建议不要在与
v-for
相同的元素上使用v-if
。由于v-for
指令的优先级高于v-if
当它们处于同一节点。v-for
的优先级比v-if
更高,这意味着v-if
将分别重复运行于每一个v-for
循环中。
<style>
.abc{color: red;}
.def{background-color: blue;}
.g-h{color: yellow;}
</style>
<div id="app">
<p class="abc">这是一个p标签</p>
<p :class="className">这是一个p标签</p>
<!-- ? : 三元运算符 -->
<p :class="isPass ? className : ''">这是一个p标签</p>
<p :class="{abc:true}">这是一个p标签</p>
<p :class="{abc:isPass}">这是一个p标签</p>
<p :class="{abc:isPass,def:true}">这是一个p标签</p>
<p :class="{'g-h':true}">这是一个p标签</p>
<p :class="['abc','def']">这是一个p标签</p>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
name:"wangcai",
className:"abc",
isPass:true,
}
})
</script>
复制代码
<div id="app">
<p :style="myStyle">这是一个p标签</p>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
myStyle:{color:'red',backgroundColor:'blue'}
}
})
</script>
复制代码
el指定app管理的边界
面试题
如何经过
$el
获取到更新后的dom元素? 答:在下一下事件环中获得更新后dom元素
数据模型
计算属性,依赖于data中的数据
计算属性和方法的区别:
过滤器
过滤器的简单使用:
![]()
组件:三部曲
- 定义组件
- 注册组件
- 使用组件
组件的简单使用:
![]()
生命周期方法
$watch
能够监控Data中的数据,经过$watch
获得值,确定是更新后的值 使用
vm.$watch( "name", function(newValue,oldValue){ } )
vue中的$nextTick主要涉及到vue中DOM的异步更新 nextTick
应用场景及缘由
created()
钩子函数进行的DOM操做必定要放在Vue.nextTick()
的回调函数中缘由:在
created()
钩子函数执行的时候DOM 其实并未进行任何渲染,而此时进行DOM操做无异于徒劳,因此此处必定要将DOM操做的js代码放进Vue.nextTick()
的回调函数中。与之对应的就是mounted()
钩子函数,由于该钩子函数执行时全部的DOM挂载和渲染都已完成,此时在该钩子函数中进行任何DOM操做都不会有问题 。
Vue.nextTick()
的回调函数中。Vue的官方文档中详细解释
Vue 异步执行 DOM 更新。只要观察到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的全部数据改变。若是同一个 watcher 被屡次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免没必要要的计算和 DOM 操做上很是重要。而后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工做。Vue 在内部尝试对异步队列使用原生的
Promise.then
和MessageChannel
,若是执行环境不支持,会采用setTimeout(fn, 0)
代替。
例如,当你设置
vm.someData = 'new value'
,该组件不会当即从新渲染。当刷新队列时,组件会在事件循环队列清空时的下一个“tick”更新。多数状况咱们不须要关心这个过程,可是若是你想在 DOM 状态更新后作点什么,这就可能会有些棘手。虽然 Vue.js 一般鼓励开发人员沿着“数据驱动”的方式思考,避免直接接触 DOM,可是有时咱们确实要这么作。为了在数据变化以后等待 Vue 完成更新 DOM ,能够在数据变化以后当即使用Vue.nextTick(callback)
。这样回调函数在 DOM 更新完成后就会调用。
$set
能够给data中动态地添加一个数据,前提
是只能给对象中添加数据
示例
事件三要素: 事件源,事件类型,监听器
语法
:v-on: 处理事件 或 @处理事件
注意:mouseover / mouseout 与 mouseenter / mouseleave的区别
- 当绑定事件的元素里面没有子元素的时候,两组触发效果是一致的。
- 当绑定事件的元素里面有子元素的时候,鼠标通过绑定mouseover的当前元素以及它里面的子元素的时候,都会触发, 而通过绑定mouseenter的元素时,只会在鼠标刚进入的时候触发,当进入其子元素的时候,是不会再触发的了。
总结
:
不论鼠标指针穿过被选元素或其子元素,都会触发 mouseover 事件。对应mouseout
只有在鼠标指针穿过被选元素时,才会触发 mouseenter 事件。对应mouseleave
当事件发生时,事件对象中保存了不少信息,如点击的坐标。 $event
固定的名字
示例:
![]()
示例:
![]()
示例:
![]()
// 自定义按键名称
Vue.config.keyCodes.ent = 13;
// 页面引用
<input type="text" @keyup.ent="enter_click"/>
复制代码
全局组件 : 定义全局组件,在每一个组件中均可以进行引用
语法:
Vue.component("组件名",{template:"组件内容"})
示例:
![]()
组件:三部曲
- 定义组件
- 注册组件
- 使用组件
示例:
![]()
父传子 : 父中有数据,传递给子,
步骤:
1,肯定父中有数据 2,在父组件的模板中经过属性绑定把数据绑到子组件上 3,在子组件中定义props属性,用来接收父传递过来的数据 4,在子组件的模板就可使用接收过来的数据了
示例:
![]()
属性校验:
总结:
父绑定数据 子接收数据
过程:
- 在父组件模板中,给子组件添加一个事件监听
- 在子组件中,某个时间经过
this.$emit
发出这个事件,发出事件的同时就能够携带数据- 当父中的方法触发,数据做用这个方法的第一个参数
示例:
![]()
npm i nrm -g
切换安装源
查看安装源
nrm ls
![]()
切换安装源 nrm use taobao
安装vue的脚手架
npm i -g @vue/cli
vue create myvue
cd myvue
npm run serve
html代码
<div id="app">
<h1>Hello App!</h1>
<p>
<!-- 使用 router-link 组件来导航. -->
<!-- 经过传入 `to` 属性指定连接. -->
<!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
<router-link to="/foo">Go to Foo</router-link>
<router-link to="/bar">Go to Bar</router-link>
</p>
<!-- 路由出口 -->
<!-- 路由匹配到的组件将渲染在这里 -->
<router-view></router-view>
</div>
复制代码
script代码
// 1. 定义 (路由) 组件。
// 能够从其余文件 import 进来
const Foo = { template: '<div>foo</div>' }
const Bar = { template: '<div>bar</div>' }
// 2. 定义路由
// 每一个路由应该映射一个组件。 其中"component" 能够是
// 经过 Vue.extend() 建立的组件构造器,
// 或者,只是一个组件配置对象。
const routes = [
{ path: '/foo', component: Foo },
{ path: '/bar', component: Bar }
]
// 3. 建立 router 实例,而后传 `routes` 配置
// 你还能够传别的配置参数, 不过先这么简单着吧。
const router = new VueRouter({
routes // (缩写) 至关于 routes: routes
})
// 4. 建立和挂载根实例。
// 记得要经过 router 配置参数注入路由,
// 从而让整个应用都有路由功能
const app = new Vue({
router
}).$mount('#app')
// 如今,应用已经启动了!
复制代码
经过路由
咱们能够在任何组件内经过
this.$router
访问路由器,也能够经过his.$route
访问当前路由:
格式
router.push(location, onComplete?, onAbort?)
注意:
在 Vue 实例内部,你能够经过
$router
访问路由实例。所以你能够调用this.$router.push
。
示例:
示例:
npm install axios
import axios from 'axios';
当vue的实例建立时,会伴随一系列的方法运行,称做生命周期函数
父组件向子组件传递数据是经过prop传递的,子组件传递数据给父组件是经过$emit触发事件来作到的。
props 与 $emit的简单使用
![]()
注意
: 使用$emit 触发父类绑定的方法时,触发的名称必须所有是小写,若父类绑定使用到小驼峰,则在触发时,所有变成小写,驼峰之间用-隔开
能够实现父组件与孙子组件之间的数据的传递 this.
attrs中
$attrs的简单使用
特别提醒
父组件中所绑定的传给父组件的属性,都存放在$attrs中,若在子组件中不接收,直接进行绑定,可使用:
v-bind="this.$attars"
$listenners的简单使用
触发父传递的click事件: @click="
listeners"
$parent 获取父组件的实例,能够以此来调用父组件中的方法。
this.$parent.cut();
$children 获取全部的儿子, 能够以此来获取子组件中的数据
this.$children[0].msg = "张三"
特别提醒
children:获取的是全部子组件的实例
ref 与refs是成对使用 ref 用于定义 $refs用户获取
$dispatch
是挂载到Vue实例
上的一个方法, 自动向上
父类中查找触发的方法,若是该方法存在就触发
示例
eventBus
原理
事件总线是,在vue的
原型
上,挂载一个$eventBus
事件(名字本身起),经过$on
进行绑定事件, 先在事件中心中注册一些事件 在须要的位置就能够经过$emit
去发布事件(触发事件)
示例
在数据进行传递的时候,数据的传递与触发的方法结合,能够有比较简便的语法糖
,更加方便程序的开发,可是与此同时也有必定的难度,不是很容易懂。下面就简单的介绍几种语法糖。
.sync
语法糖
.sync
是@update:data
的语法糖,data
是vue中data中的数据
在给子类传递数据的时候,经过.sync
对属性进行限定,在子类中能够直接触发update:数据名称
来修改父类中对应的数据,该方法能够省去父类中修改属性的方法。
没有使用.sync
以前
示例
使用.sync
以后
没有简化: 简化后:
示例
特别注意
update是规定的触发的方法,update冒号后面跟的必须是父类中要修改的数据的数据名
v-model
语法糖
v-model
是:value
和@input
的语法糖,绑定的属性必须是value
在给子类传递数据的时候,直接使用v-model
进行绑定,在子类中,能够触发input
事件,来达到修改数据的目的
示例
特别注意
v-model
至关于:value
+@input
至关于上述方法的简写
数据监控: : 监控数据的获取与改变,能够简称为数据劫持。
vue中data数据的监控原理:
代码以下:
// 数据的监控,监控数据的获取与改变
// vue中data数据的监控原理
obj = {
name: "wangcai",
age:18
};
function obServe(obj){
if(typeof obj ``= "object"){
for(key in obj){
defineReactive(obj,key,obj[key]);
}
}
}
function defineReactive(obj,key,value){
obServe(value);
Object.defineProperty(obj,key,{
get(){
console.log("get...");
return value;
},
set(val){
console.log('set... :');
obServe(val);
value = val;
}
})
}
// defineProperty是数组是无效的
//解决方式以下:
// vue中封装了数据的全部的方法,此处只作列举
let arr = ["push","slice","shift","unshift"]
arr.forEach(method=>{
let old = Array.prototype[method];
Array.prototype[method] = function(value){
console.log("set...")
old.call(this,value)
}
})
//-----------------------------------------------------------
// 测试数组
// observer(obj)
// obj.age = [1,2,3] // set..
// obj.age.push(4) // 设置值 defineProperty对数据是无效的
//-----------------------------------------------------------------
// 测试简单的对象
// obServe(obj)
// console.log(obj.name) //get...
// obj.name = "hello" // set...
// 测试嵌套的对象
// observer(obj)
// obj.name // get...
// obj.name = "hello" // set...
// obj.age = { k:"kkkk" } // set...
// obj.age.k = "mmmm" // set...
复制代码
在vue的路由跳转中有两种方式,分别是问号模式,和冒号模式,二者不能进行混合使用,
格式
传值
:<router-link to="/user/detail?id=1">用户1</router-link>
获取值
:{{this.$route.query.id}}
注意
:使用问号进行传值的时候不需在router中特别设置路由
格式
传值
:<router-link to="/user/detail/2">用户2</router-link>
配置router路由文件
path:"detail/:id",
获取值
:{{this.$route.params.id}}
在全局中有三个路由守卫,分别是beforeEach
,beforeResolve
,afterEach
beforeEach
router.beforeEach((to, from, next) => {}
beforeResolve
router.beforeResolve((to, from, next) => {}
afterEach
router.afterEach((to, from) => {}
格式:
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
复制代码
在组件的内部存在整合三个路由组件,分别是beforeRouteEnter
、beforeRouteUpdate
、beforeRouteLeave
beforeRouteEnter
不能
获取组件实例this
beforeRouteUpdate
this
beforeRouteUpdate ((to, from, next) => {}
beforeRouteLeave
this
beforeRouteLeave((to, from, next) => {}
beforeEach
beforeRouterLeave
。beforeEach
守卫。beforeRouteUpdate
守卫 (2.2+)。beforeEnter
。beforeRouteEnter
。beforeResolve
守卫 (2.5+)。afterEach
钩子。beforeRouteEnter
守卫中传给 next 的回调函数。源码
// 基于node的 node不支持import语法
// 默认环境变量 NODE_ENV 生产环境 production development
let path = require('path');
module.exports = {
// 配置开发环境(npm run serve)或生产环境(npm run build)url
publicPath:process.env.NODE_ENV ``= 'production'? 'http://www.abcd.cn':'/',
//打包后的资源放入的文件夹,默认未放入文件夹
assetsDir:'asserts',
//打包后生成的文件夹,默认是dist
outputDir:'./dist',
// 是否使用本身的内部模板 通常不使用
runtimeCompiler:false,
// 打包后删除生成的.map文件 再也不使用sourcemap
productionSourceMap:false,
chainWebpack:config=>{
// 能够获取到webpack的配置 在增长一些本身的逻辑
// 配置目录别名 别名叫+
config.resolve.alias.set('_c',path.resolve(__dirname,'src/components'));
config.resolve.alias.set('_v',path.resolve(__dirname,'src/views'));
},
//webpack配置,到时候会合并到默认的webpack中。
configureWebpack:{ // webpack-merge
plugins:[],
module:{}
},
// 开发 服务时使用 上线时不须要 解决跨域的问题
devServer:{
proxy:{
'/api/getUser':{
target:'http://localhost:3000',
pathRewrite:{
'/api':''
}
}
}
},
//第三方插件的配置
pluginOptions: {
'style-resources-loader': {
preProcessor: 'less',
patterns: [
path.resolve(__dirname,'src/assets/common.less')
]
}
}
}
复制代码
源码
let express = require('express');
let app = express();
// 在后端配置,让全部的人均可以访问个人api接口
app.use('*', function (req, res, next) {
// 容许哪些客户端来访问我
res.setHeader("Access-Control-Allow-Origin","*");
// 容许能够添加哪些头,而后来访问我
res.setHeader("Access-Control-Allow-Headers","*");
// res.header('Access-Control-Allow-Headers', 'Content-Type,Authorization');
// 容许哪些方法来访问我
res.setHeader("Access-Control-Allow-Methods","OPTIONS,PUT,DELETE");
// res.header('Access-Control-Allow-Methods', '*');
// 能够每隔半小时,来发送一个options请求--试探请求
res.setHeader("Access-Control-Max-Age","1800");
// 请求的类型编码
res.header('Content-Type', 'application/json;charset=utf-8');
// 容许客户端携带凭证,处理cookie信息,若是有,而且不对每次请求都新开一个session
res.setHeader("Access-Control-Allow-Credentials",true);
next();
});
复制代码
路由的元信息通常可用于权限的校验
定义路由的时候能够配置 meta
字段
配置meta字段,该字段配置为对象信息
一个路由匹配到的全部路由记录会暴露为 $route
对象 (还有在导航守卫中的路由对象) 的 $route.matched
数组。所以,咱们须要遍历 $route.matched
来检查路由记录中的 meta
字段。
示例: