Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动
Vue中文文档,具体学习还是官方好:https://cn.vuejs.org/
文件 => 首选项 => 用户代码片段 => 新建全局代码片段/或文件夹代码片段:自定义文件名
{
"vue htm": {
//作用范围,删除即全局
"scope": "html",
//prefix固定的-自定义快捷键
"prefix": "vuehtml",
"body": [
"",
"",
"",
"",
" ",
" ",
" ",
" Document ",
"",
"",
"",
" ",
"",
" ",
" ",
" ",
"",
"",
"",
],
"description": "my vue template in html"
}
}
保存好,新建一个html文件输入之前定义的快捷键vuehtml然后tab即可以快速生成代码片段
被称为指令。指令带有前缀 v- 。
除了使用插值表达式{{}}
进行数据渲染,也可以使用 v-bind
指令,它的简写的形式就是一个冒号(:)
data: {
message: '页面加载于 ' + new Date().toLocaleString()
}
<!-- 如果要将模型数据绑定在html属性中,则使用 v-bind 指令,此时title中显示的是模型数据-->
<h1 v-bind:title="message">我是标题</h1>
<!-- v-bind 指令的简写形式: 冒号(:) -->
<h1 :title="message">我是标题</h1>
双向数据绑定,会根据控件类型自动选取正确的方法来更新元素
<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>
输入:DAIHAO
Message is: DAIHAO
还可以绑定很多
v-model 在内部为不同的输入元素使用不同的属性并抛出不同的事件:
text
和 textarea
元素使用 value
属性和 input
事件;
checkbox
和 radio
使用 checked
属性和 change
事件;
select
字段将 value
作为 prop
并将 change
作为事件
监听 DOM 事件,并在触发时运行一些 JavaScript 代码
<!-- v-on 指令绑定事件,click指定绑定的事件类型,事件发生时调用vue中methods节点中定义的方法 -->
<button v-on:click="search()">查询</button>
<!-- v-on 指令的简写形式 @ -->
<button @click="search()">查询</button>
用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 truthy 值的时候被渲染。
<h1 v-if="awesome">Vue is awesome!</h1>
也可以用 v-else 添加一个“else 块”:
<h1 v-if="awesome">Vue is awesome!</h1>
<h1 v-else>Oh no </h1>
另一个用于根据条件展示元素的选项是 v-show 指令。用法大致一样:
<h1 v-show="ok">Hello!</h1>
不同的是带有 v-show 的元素始终会被渲染并保留在 DOM 中。v-show 只是简单地切换元素的 CSS 属性 display。
注意,v-show 不支持 元素,也不支持 v-else。
v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。
v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
相比之下,v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。
一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。
可以绑定数组的数据来渲染一个项目列表
<div id="app-4">
<ol>
<li v-for="todo in todos">
{{ todo.text }}
</li>
</ol>
</div>
var app4 = new Vue({
el: '#app-4',
data: {
todos: [
{ text: '学习 JavaScript' },
{ text: '学习 Vue' },
{ text: '整个牛项目' }
]
}
})
在控制台里,输入 app4.todos.push({ text: ‘新项目’ }),你会发现列表最后添加了一个新项目。
data: {
numbers: [1, 2, 3, 4, 5]
}
<!-- 2、遍历数组,使用计算属性 -->
<ul>
<li v-for="n in numbers">{{ n }}</li>
</ul>
<ul>
<li v-for="n in evenNumbers">{{ n }}</li>
</ul>
computed:计算属性,和data定义在同一级别
// 计算属性:这里的数据是通过某种方式计算出来的
computed: {
evenNumbers() {
console.log('计算属性 evenNumbers')
// filter:遍历numbers,并返回满足条件的值,放在一个数组中
return this.numbers.filter(function (number) {
return number % 2 === 0
})
}
}
data: {
userList: [
{ id: 1, username: 'helen', age: 18 },
{ id: 2, username: 'peter', age: 28 },
{ id: 3, username: 'andy', age: 38 }
]
}
<!-- 3、遍历数据列表 -->
<table border="1">
<!-- <tr v-for="item in userList"></tr> -->
<tr v-for="(item, index) in userList">
<td>{{index}}</td>
<td>{{item.id}}</td>
<td>{{item.username}}</td>
<td>{{item.age}}</td>
</tr>
</table>
data: {
user:{
id: 1,
username: 'helen',
age: 18
}
}
<!-- 4、遍历对象 -->
<!-- 直接访问 -->
<form action="">
<p><label>id:<input type="text" v-model="user.id"></label></p>
<p><label>用户名:<input type="text" v-model="user.username"></label></p>
<p><label>年龄:<input type="text" v-model="user.age"></label></p>
</form>
<!-- 遍历 -->
<form action="">
<!-- <p v-for="value in user"> -->
<p v-for="(value, key, index) in user">
<label>{{index}}-{{key}}:<input type="text" v-model="value"></label>
</p>
</form>
data: {
message: '上海自来水来自海上 haha'
}
模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。
<p>原始值: "{{ message }}"</p>
<!-- 1、插值数据绑定中使用表达式 -->
<p>反转消息: {{ message.split('').reverse().join('') }}</p>
所以,对于任何复杂逻辑,你都应当使用计算属性
例2:使用计算属性
computed: {
reversedMessage () {
return this.message.split('').reverse().join('')
}
}
<!-- 2、使用计算属性 -->
<p>反转消息: "{{ reversedMessage }}"</p>
例3:使用方法
methods:{
reversed () {
return this.message.split('').reverse().join('')
}
}
<!-- 3、使用方法 -->
<p>反转消息: "{{ reversed() }}"</p>
看起来计算属性和方法能完成相同的功能,那么他们有什么区别呢?
计算属性基于缓存:在相关依赖发生改变时它们才会重新求值。
方法将总会再次执行
我们为什么需要缓存?假设我们有一个性能开销比较大的计算属性 A,它需要遍历一个巨大的数组并做大量的计算。然后我们可能有其他的计算属性依赖于 A 。如果没有缓存,我们将不可避免的多次执行 A 的 计算!如果你不希望有缓存,请用方法来替代。
<!-- 2、使用计算属性 -->
<p>反转消息: "{{ reversedMessage }}"</p>
<!-- 调用两次只执行一次属性的计算 -->
<p>反转消息: "{{ reversedMessage }}"</p>
<!-- 3、使用方法 -->
<p>反转消息: "{{ reversed() }}"</p>
<!-- 调用两次执行了两次属性的计算 -->
<p>反转消息: "{{ reversed() }}"</p>
当你有一些数据需要随着其它数据变动而变动时,可以使用侦听属性
data: {
firstName: '道格拉斯',
lastName: '狗剩'
fullName: '道格拉斯 狗剩'
},
watch: {
firstName(val){
console.log('firstName changed...')
this.fullName = val + ' ' + this.lastName
},
lastName(val){
console.log('lastName changed...')
this.fullName = this.firstName + ' ' + val
}
}
<label>名:<input type="text" v-model="firstName"></label>
<label>姓:<input type="text" v-model="lastName"></label>
{{fullName}}
实际上,上一个例子是对 watch 的滥用。我们完全可以用计算属性更高效的完成同样的操作
data: {
firstName: '道格拉斯',
lastName: '狗剩'
// fullName: 'Foo Bar' //既然fullName需要被计算,那么将此属性放在计算属性中
},
computed: {
fullName () {
return this.firstName + ' ' + this.lastName
}
}
例3:
<p>
Ask a yes/no question:
<input v-model="question">
<button @click="getAnswer()">提问</button>
</p>
<p>{{ answer }}</p>
var app = new Vue({
el: '#app',
data: {
question: '',
answer: '请提问!'
},
methods: {
getAnswer: function () {
this.answer = '我想想...'
var vm = this
$.ajax({
url: 'https://yesno.wtf/api',
type: 'get',
success(data) {
// console.log(this);
vm.answer = data.answer
},
error (error) {
vm.answer = '网找不到API接口. ' + error
}
})
}
}
})
使用watch:当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。
watch: {
// 如果 `question` 发生改变,这个函数就会运行
question: function (newQuestion, oldQuestion) {
this.answer = '等待您停止输入...'
this.getAnswer()
}
}
例1:局部过滤器
data: {
userList: [
{id: 1, name: 'peter', gender: 1},
{id: 2, name: 'helen', gender: 0}
]
}
使用if指令判断
<table border="1">
<tr v-for="item in userList">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<!-- <td>{{item.gender}}</td> -->
<td>
<span v-if="item.gender === 1">男</span>
<span v-else>女</span>
</td>
</tr>
</table>
使用过滤器
// filters 定义局部过滤器,只可以在当前vue实例中使用
filters: {
genderFilter(gender) {
return gender === 1 ? '男' : '女'
}
}
<td>
<!-- | 管道符号:表示使用后面的过滤器处理前面的数据 -->
{{item.gender | genderFilter}}
</td>
例2:全局过滤器
// 在创建 Vue 实例之前全局定义过滤器:
Vue.filter('capitalize', function (value) {
return value.charAt(0).toUpperCase() + value.slice(1)
})
应用全局过滤器
<td>{{item.name | capitalize}}</td>
定义另一个vue实例
var app2 = new Vue({
el: '#app2',
data: {
user: { id: 3, name: 'annie', gender: 0 }
}
})
<div id="app2">
<!-- 全局过滤器可以应用在不同的vue实例的渲染范围中 -->
{{user.name | capitalize}}
<!-- 局部过滤器则不可以,只能应用在定义的vue实例中 -->
{{user.gender | genderFilter}}
</div>
过滤器常用来处理文本格式化的操作。过滤器可以用在两个地方:双花括号插值和 v-bind 表达式
过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符号指示
通常一个应用会以一棵嵌套的组件树的形式来组织
例如,你可能会有页头、侧边栏、内容区等组件,每个组件又包含了其它的像导航链接、博文之类的组件。
为了能在模板中使用,这些组件必须先注册以便 Vue 能够识别。这里有两种组件的注册类型:全局注册和局部注册。至此,我们的组件都只是通过 Vue.component 全局注册的:
Vue.component('my-component-name', {
// ... options ...
})
全局注册的组件可以用在其被注册之后的任何 (通过 new Vue) 新创建的 Vue 根实例,也包括其组件树中的所有子组件的模板中
Vue 组件的示例:
// 定义一个名为 button-counter 的新组件
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: ''
})
组件是可复用的 Vue 实例,且带有一个名字:在这个例子中是 。我们可以在一个通过 new Vue 创建的 Vue 根实例中,把这个组件作为自定义元素来使用:
<div id="components-demo">
<button-counter></button-counter>
</div>
new Vue({ el: '#components-demo' })
你可以将组件进行任意次数的复用:
<div id="components-demo">
<button-counter></button-counter>
<button-counter></button-counter>
<button-counter></button-counter>
</div>
data 必须是一个函数
当我们定义这个 组件时,你可能会发现它的 data 并不是像这样直接提供一个对象:
data: {
count: 0
}
取而代之的是,一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝:
data: function () {
return {
count: 0
}
}
在注册一个组件的时候,我们始终需要给它一个名字。比如在全局注册的时候我们已经看到了:
Vue.component('my-component-name', { /* ... */ })
该组件名就是 Vue.component 的第一个参数。
你给予组件的名字可能依赖于你打算拿它来做什么。当直接在 DOM 中使用一个组件 (而不是在字符串模板或单文件组件) 的时候,我们强烈推荐遵循 W3C 规范中的自定义组件名 (字母全小写且必须包含一个连字符)。这会帮助你避免和当前以及未来的 HTML 元素相冲突。
定义组件名的方式有两种:
使用 kebab-case
Vue.component('my-component-name', { /* ... */ })
当使用 kebab-case (短横线分隔命名) 定义一个组件时,你也必须在引用这个自定义元素时使用 kebab-case,例如
使用 PascalCase
Vue.component('MyComponentName', { /* ... */ })
当使用 PascalCase (首字母大写命名) 定义一个组件时,你在引用这个自定义元素时两种命名法都可以使用。也就是说
和
都是可接受的。注意,尽管如此,直接在 DOM (即非字符串的模板) 中使用时只有 kebab-case 是有效的。
到目前为止,我们只用过 Vue.component
来创建组件:
Vue.component('my-component-name', {
// ... 选项 ...
})
这些组件是全局注册的。也就是说它们在注册之后可以用在任何新创建的 Vue 根实例 (new Vue) 的模板中。比如:
Vue.component('component-a', { /* ... */ })
Vue.component('component-b', { /* ... */ })
Vue.component('component-c', { /* ... */ })
new Vue({ el: '#app' })
<div id="app">
<component-a></component-a>
<component-b></component-b>
<component-c></component-c>
</div>
在所有子组件中也是如此,也就是说这三个组件在各自内部也都可以相互使用。
全局注册往往是不够理想的。比如,如果你使用一个像 webpack 这样的构建系统,全局注册所有的组件意味着即便你已经不再使用一个组件了,它仍然会被包含在你最终的构建结果中。这造成了用户下载的 JavaScript 的无谓的增加。
在这些情况下,你可以通过一个普通的 JavaScript 对象来定义组件:
var ComponentA = { /* ... */ }
var ComponentB = { /* ... */ }
var ComponentC = { /* ... */ }
然后在 components
选项中定义你想要使用的组件:
new Vue({
el: '#app',
components: {
'component-a': ComponentA,
'component-b': ComponentB
}
})
对于 components 对象中的每个属性来说,其属性名就是自定义元素的名字,其属性值就是这个组件的选项对象。
注意局部注册的组件在其子组件中不可用。例如,如果你希望 ComponentA 在 ComponentB 中可用,则你需要这样写:
var ComponentA = { /* ... */ }
var ComponentB = {
components: {
'component-a': ComponentA
},
// ...
}
或者如果你通过 Babel 和 webpack 使用 ES2015 模块,那么代码看起来更像:
import ComponentA from './ComponentA.vue'
export default {
components: {
ComponentA
},
// ...
}
注意在 ES2015+ 中,在对象中放一个类似 ComponentA
的变量名其实是 ComponentA: ComponentA
的缩写,即这个变量名同时是:
用在模板中的自定义元素的名称
包含了这个组件选项的变量名
每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。
比如 created 钩子可以用来在一个实例被创建之后执行代码:
new Vue({
data: {
a: 1
},
created: function () {
// `this` 指向 vm 实例
console.log('a is: ' + this.a)
}
})
// => "a is: 1"
也有一些其它的钩子,在实例生命周期的不同阶段被调用,如 mounted、updated 和 destroyed。生命周期钩子的 this 上下文指向调用它的 Vue 实例。
> 不要在选项属性或回调上使用箭头函数,比如 created: () => console.log(this.a) 或
> vm.$watch('a', newValue => this.myMethod())。因为箭头函数并没有 this,this
> 会作为变量一直向上级词法作用域查找,直至找到为止,经常导致 Uncaught TypeError: Cannot read property
> of undefined 或 Uncaught TypeError: this.myMethod is not a function
> 之类的错误。
Vue.js 路由允许我们通过不同的 URL 访问不同的内容。
1、创建vue文件夹
2、复制js资源
vue.min.js
vue-router.min.js
3、创建 路由.html
4、引入js
<script src="vue.min.js"></script>
<script src="vue-router.min.js"></script>
5、编写html
<div id="app">
<h1>Hello App!</h1>
<p>
<!-- <router-link> 默认会被渲染成一个 `` 标签 -->
<!-- 通过传入 `to` 属性指定链接. -->
<router-link to="/">首页</router-link>
<router-link to="/login">登录</router-link>
<router-link to="/logout">注销</router-link>
</p>
<!-- 路由出口 -->
<!-- 路由匹配到的组件将渲染在这里 -->
<router-view></router-view>
</div>
6、编写js
<script>
// 1. 定义(路由)组件。
// 复杂的组件也可以从独立的vue文件中引入
const Welcome = { template: '欢迎' }
const Student = { template: 'login list' }
const Teacher = { template: 'logout list' }
// 2. 定义路由
// 每个路由应该映射一个组件。
const routes = [
{ path: '/', redirect: '/welcome' }, //设置默认指向的路径
{ path: '/welcome', component: Welcome },
{ path: '/login', component: Login },
{ path: '/logout', component: Logout }
]
// 3. 创建 router 实例,然后传 `routes` 配置
const router = new VueRouter({
routes // (缩写)相当于 routes: routes
})
// 4. 创建和挂载根实例。
// 从而让整个应用都有路由功能
new Vue({
el: '#app',
router
})
// 现在,应用已经启动了!
</script>
使用vue-cli快速创建一个基于webpack模板的项目
Webpack 是一个前端资源加载/打包工具。它将根据模块的依赖关系进行静态分析,然后将这些模块按照指定的规则生成对应的静态资源。
Webpack 可以将多种静态资源 js、css、less 转换成一个静态文件,减少了页面的请求。
详细安装使用参考[https://www.cnblogs.com/mapengfei247/p/11074429.html]
饿了么前端出品的基于 Vue.js的 后台组件库,方便程序员进行页面快速布局和构建
安装element-ui
npm install element-ui -S
S代表save 安装到本地开发者环境中
检查一下package.json看看是否安装成功,如果有element-ui 表示安装成功
import Element from 'element-ui'
import './styles.scss'
Vue.use(Element)//全局使用ElementUI
一般流程-cv大法:
找想要的样式组件
复制代码到对应的.vue文件
修改对应的数据
Element中文文档