安装:
node -V_10.16 -v_8.9
npm(管理依赖) -V_6.0 -v_5.5.1
安装node ->自带npm无需安装
node -v ->安装成功后会显示版本
npm install nrm -g ->切换全局镜像(下载依赖快些)
nrm ls ->带*的是当前选中的镜像
nrm use ???? ->指定要使用的镜像源 例:nrm use taobao
nrm test npm ->测试速度 例:测试淘宝:nrm test taobao
// 安装完成请一定要重启下电脑!!! (切换镜像无效重启)
// 或者直接配置仓库: npm config set registry http://registry.npm.taobao.org/
创建:
npm init -y ->对项目初始化
npm install vue --save ->安装Vue,输入命令 --save (只在当前项目,非全局)
npm install -g vue-cli ->全局环境安装命令
操作命令:
1. 重新安装项目依赖: npm install
2. 安装最新版的 vue-cli: npm install -g @vue/cli
3. 安装 node-sass npm install node-sass --save-dev
4. 运行 vue ui助手: vue ui
快速搭建webpack的项目: vue init webpack
启动项目: npm run dev
vue:
使用它能快速的构建一个web工程模板。
Git官网:https://github.com/vuejs/vue-cli
官网:https://cli.vuejs.org/zh/
使用:
App.vue 单文件组件中包含三部分内容:
// 每个组件都有自己独立的html、JS、CSS,互不干扰,真正做到可独立复用。
- template:模板,支持html语法高亮和提示
- script:js脚本,
- 这里编写的就是vue的组件对象,看到上面的data(){}
- export:导出,这个是ES6中的模块化语法,导出后,其它组件才能import导入使用。类似java中的导包
- style:样式,支持CSS语法高亮和提示
package.json 文件:{
- 可以看到这引入了非常多的依赖
- dependencies:这里是运行期依赖,会随代码一起打包的
- devDependencies:开发期依赖,开发时用的一些插件,生成运行时用不到,因此不会被打包。
- scripts:代表运行脚本,运行这里的脚步,使用:npm run '脚本名'执行,例如npm run dev会执行dev脚本
- dev脚本:使用了webpack-dev-server命令,会启动一个热加载服务器,动态对资源进行加载,修改页面无需重启。
- start脚本:使用了npm run dev命令,与上面的dev效果完全一样
- build脚本:使用了webpack的打包功能,会把所有代码打包,存储到项目dist目录下。
}
页面模板:
{
<v-card> // - v-card:卡片;是vuetify中提供的组件,提供一个悬浮效果的面板,用来展示一组数据
<v-flex xs12 sm10> // 布局容器,用来控制响应式布局; sm10:在小屏幕显示宽度为10格;xs12:在大屏幕显示宽度为12格
<v-tree // v-tree:树组件; Vuetify并没有提供树组件,这个是我们自己编写的自定义组件:
url="/item/category/list" // 用来加载数据的地址,即延迟加载 类型:String
:isEdit="isEdit" // 是否开启树的编辑功能 类型:boolean 默认值: false
:treeData="" // 整颗树数据,这样就不用远程加载了 类型:Array 不推荐使用上
treeData // 整颗树数据,这样就不用远程加载了 类型:Array
@handleAdd="handleAdd" // 新增节点时触发,isEdit为true时有效;新增节点node对象,包含属性:name、parentId和sort
@handleEdit="handleEdit" // 当某个节点被编辑后触发,isEdit为true时有效; 被编辑节点的id和name
@handleDelete="handleDelete"// 当删除节点时触发,isEdit为true时有效; 被删除节点的id
@handleClick="handleClick" // 点击某节点时触发; 被点击节点的node对象,包含全部信息
/>
</v-flex>
</v-card>
这里推荐使用url进行延迟加载,每当点击父节点时,就会发起请求,根据父节点id查询子节点信息。
当有treeData属性时,就不会触发url加载;远程请求返回的结果格式:
[
{
"id": 74, // 节点id
"name": "手机", // "手机", // 节点名称
"parentId": 0, // 父节点id
"isParent": true, // 是否是父节点
"sort": 2 // 顺序
"path": ["手机", "手机通讯", "手机"] // 所有父节点的名称数组
},
{
"id": 75,
"name": "家用电器",
"parentId": 0,
"isParent": true,
"sort": 3
}
]
}
v-data-table中有以下核心属性:{
- dark:是否使用黑暗色彩主题,默认是false
- expand:表格的行是否可以展开,默认是false
- headers:定义表头的数组,数组的每个元素就是一个表头信息对象,结构:
{
text: string, // 表头的显示文本
value: string, // 表头对应的每行数据的key
align: 'left' | 'center' | 'right', // 位置
sortable: boolean, // 是否可排序
class: string[] | string,// 样式
width: string,// 宽度
}
- items:表格的数据的数组,数组的每个元素是一行数据的对象,对象的key要与表头的value一致
- search:搜索过滤字段,用不到,直接删除
- loading:是否显示加载数据的进度条,boolean类型; 默认是false
- no-data-text:当没有查询到数据时显示的提示信息,string类型,无默认值
- pagination.sync:包含分页和排序信息的对象,将其与vue实例中的属性关联,表格的分页或排序按钮被触发时,会自动将最新的分页和排序信息更新。对象结构:
{
page: 1, // 当前页
rowsPerPage: 5, // 每页大小
sortBy: '', // 排序字段
descending:false, // 是否降序
}
- total-items:总条数; 分页的总条数信息,number类型,无默认值
- select-all :是否显示每一行的复选框,Boolean类型,无默认值
- value:当表格可选的时候,返回选中的行
}
组件功能:
案例:{
<div id="app">
<input type="text" v-model="num"> // 在input元素,通过v-model与num进行绑定。input与num绑定,input的value值变化,影响到了data中的num值
<button v-on:click="num++">+</button> // 绑定点击事件,直接操作num 简写方法: @click="num++"
<button v-on:click="add">按钮</button> // 绑定方法;可以简化:@click="方法"
<h2>
{{name}} 非常帅,
有{{num}}位女神为他着迷。
</h2>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript">
// 生成一个Vue实例
var app = new Vue({
el:"#app", // el,即element。通过id选中要渲染的页面元素,本例中是一个 id="app" 的div
data:{ // 数据是一个对象,里面有很多属性,都可以渲染到视图中
name:"虎哥", // 通过{{name}}来渲染定义的name属性
num:1, // 通过{{num}}来渲染定义的num属性
methods:{
add:function () {
console.log("弹弹弹!")
}
}
}
})
</script>
说明:
对象:
- el: 即element。通过id选中要渲染的页面元素;本例中是一个 id="app" 的div,div范围以外的部分是无法使用vue特性的
- data: 数据是一个对象,里面有很多属性,都可以渲染到视图中;属性具有 "双向绑定"
- name: 指定了一个name属性,通过{{name}}来渲染定义的name属性
- num: 指定了一个num属性,通过{{num}}来渲染定义的num属性
// 在input元素,通过v-model与num进行绑定。input与num绑定,input的value值变化,影响到了data中的num值
- methods:定义方法,并且在Vue的作用范围内使用
标签:
v-on:click :绑定点击事件,直接操作属性 简写方法: @click="num++"
}
钩子函数:
created (可用于初始化){
var vm = new Vue({
el:"#app",
data:{
hello: '' // hello初始化为空
},
created(){
this.hello = "hello, world! 我出生了!";
}
})
总结:this就是当前的Vue实例,在Vue对象内部,必须使用this才能访问到Vue中定义的data内属性、方法等。
}
插值: v-text="name" (当网速慢时不会想 {{name}} 一样显示 再刷新)
插值: v-html="name" ( <a>{{name}}<a> 和v-text不同的是 可以解析 html标签)
双向绑定:
{
v-model="名字"
- input
- input 和textarea 默认对应的model是字符串
- textarea
- input 和textarea 默认对应的model是字符串
- select
- select单选对应字符串,多选对应也是数组
- checkbox
- 多个CheckBox对应一个model时,model的类型是一个数组,单个checkbox值是boolean类型
- radio
- radio 对应的值是input的value值
- components(Vue中的自定义组件)
// 基本上除了最后一项,其它都是表单的输入项。
}
v-on:
语法:v-on:事件名="js片段或函数名"
简写语法:@事件名="js片段或函数名"
例如: v-on:click="num++"可以简写为 @click="num++"
事件修饰符: // Vue.js 为 v-on 提供了事件修饰符。
- .stop :阻止事件冒泡
- .prevent:阻止默认事件发生
- .capture:使用事件捕获模式
- .self:只有元素自身触发事件才执行。(冒泡或捕获的都不执行)
- .once:只执行一次
v-for:{
遍历数据渲染页面是非常常用的需求,Vue中通过v-for指令来实现。
遍历数组
语法:v-for="item in items"
示例:
<div id="app">
<ul>
<li v-for="user in users">
{{user.name}} : {{user.gender}} : {{user.age}}
</li>
</ul>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el:"#app",
data:{
users:[
{name:'柳岩', gender:'女', age: 21},
{name:'虎哥', gender:'男', age: 30},
{name:'范冰冰', gender:'女', age: 24},
{name:'刘亦菲', gender:'女', age: 18},
{name:'古力娜扎', gender:'女', age: 25}
]
}
})
</script>
}
数组角标:
{
在遍历的过程中,如果我们需要知道数组角标,可以指定第二个参数:
语法:v-for="(item,index) in items" (index:迭代到的当前元素索引,从0开始。)
示例:
<div id="app">
<ul>
<li v-for="(user,index) in users">
{{index}} - {{user.name}} : {{user.gender}} : {{user.age}}
</li>
</ul>
</div>
}
遍历对象:
{
v-for除了可以迭代数组,也可以迭代对象。语法基本类似
语法:
v-for="value in object"
- 1个参数时,得到的是对象的值
v-for="(value,key) in object"
- 2个参数时,第一个是值,第二个是键
v-for="(value,key,index) in object"
- 3个参数时,第三个是索引,从0开始
示例:
<div id="app">
<ul>
<li v-for="(value,key,index) in user">
{{index}} - {{key}} : {{value}}
</li>
</ul>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el:"#app",
data:{
user:{name:'柳岩', gender:'女', age: 21}
}
})
</script>
}
key:{
示例:
<ul>
<li v-for="(item,index) in items" :key="index"></li>
</ul>
特殊语法::key="" 我们后面会讲到,它可以让你读取vue中的属性,并赋值给key属性
}
v-if:
语法:v-if="布尔表达式"
v-if与v-for结合:{ // v-for优先级更高。也就是说,会先遍历,再判断条件
示例:
<div id="app">
<ul>
<li v-for="(user,index) in users" v-if="user.gender === '女'">
{{index}} - {{user.name}} : {{user.gender}} : {{user.age}}
</li>
</ul>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el:"#app",
data:{
users:[
{name:'柳岩', gender:'女', age: 21},
{name:'虎哥', gender:'男', age: 30},
{name:'范冰冰', gender:'女', age: 24},
{name:'刘亦菲', gender:'女', age: 18},
{name:'古力娜扎', gender:'女', age: 25}
]
}
})
</script>
v-else 元素必须紧跟在带 v-if 或者 v-else-if 的元素的后面,否则它将不会被识别。
}
v-show:{
另一个用于根据条件展示元素的选项是 v-show 指令。用法大致一样:
<h1 v-show="ok">Hello!</h1>
示例:
<div id="app">
<!--事件中直接写js片段-->
<button @click="show = !show">点击切换</button><br/>
<h1 v-if="show">
你好
</h1>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript">
var app = new Vue({
el:"#app",
data:{
show:true
}
})
</script>
}
v-bind:{
语法:v-bind:属性名="Vue中的变量"
例如,在这里我们可以写成:
<div v-bind:class="color"></div>
直接写成::属性名='属性值',即:<div :class="color"></div>
}
class属性的特殊用法:{
:class 一个对象,以动态地切换 class:
<div :class="{ red: true,blue:false }"></div>
- 对象中,key是已经定义的class样式的名称,如本例中的:red和blue
- 对象中,value是一个布尔值,如果为true,则这个样式会生效,如果为false,则不生效。
之前的案例可以改写成这样:
<div id="app">
<button @click="boo=!boo">点击切换背景</button>
<div :class="{red:boo, blue: !boo}">
点击按钮,背景会切换颜色哦
</div>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: "#app",
data: {
boo: true, // 一个布尔标记,判断样式是否生效
}
})
</script>
- 首先class绑定的是一个对象:{red:boo, blue: !boo}
- red和blue两个样式的值分别是boo和!boo,也就是说这两个样式的生效标记恰好相反,一个生效,另一个失效。
- boo默认为true,也就是说默认red生效,blue不生效
- 现在只需要一个按钮即可,点击时对boo取反,自然实现了样式的切换
}
计算属性:{
data:{
birthday:1529032123201 // 毫秒值
}
希望得到yyyy-MM-dd的样式:
<h1>您的生日是:{{
new Date(birthday).getFullYear() + '-'+ new Date(birthday).getMonth()+ '-' + new Date(birthday).getDay()
}}
</h1>
Vue中提供了计算属性,来替代复杂的表达式:
var vm = new Vue({
el:"#app",
data:{
birthday:1429032123201 // 毫秒值
},
computed:{
birth(){// 计算属性本质是一个方法,但是必须返回结果
const d = new Date(this.birthday);
return d.getFullYear() + "-" + d.getMonth() + "-" + d.getDay();
}
}
})
- 计算属性本质就是方法,但是一定要返回数据。然后页面渲染时,可以把这个方法当成一个变量来使用。
页面使用:
<div id="app">
<h1>您的生日是:{{birth}} </h1>
</div>
}
watch:{
watch可以让我们监控一个值的变化。从而做出相应的反应。
示例:
<div id="app">
<input type="text" v-model="message">
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el:"#app",
data:{
message:""
},
watch:{
message(newVal, oldVal){
console.log(newVal, oldVal);
}
}
})
</script>
}
深度监控:{
如果监控的是一个对象,需要进行深度监控,才能监控到对象中属性的变化,例如:
<div id="app">
姓名:<input type="text" v-model="person.name"> <br>
年龄:<input type="text" v-model="person.age"> <button @click="person.age++">+</button> <br>
<h1>
{{person.name}}今年{{person.age}}岁了。
</h1>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: "#app",
data: {
person:{
name:"Jack",
age:21
}
},
watch:{
person:{
deep: true, // 开启深度监控,可以监控到对象中属性变化
handler(val){ // 定义监控到以后的处理方法
console.log(val.name + ": " + val.age);
}
}
}
})
</script>
变化:
- 以前定义监控时,person是一个函数,现在改成了对象,并且要指定两个属性:
- deep:代表深度监控,不仅监控person变化,也监控person中属性变化
- handler:就是以前的监控处理函数
}
}
组件化: {
定义全局组件:{
通过Vue的component方法来定义一个全局组件。
<div id="app">
<!--使用定义好的全局组件-->
<counter></counter>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript">
// 定义全局组件,两个参数:1,组件名称。2,组件参数
Vue.component("counter",{
template:'<button v-on:click="count++">你点了我 {{ count }} 次,我记住了.</button>',
data(){
return {
count:0
}
}
})
var app = new Vue({
el:"#app"
})
</script>
- 组件其实也是一个Vue实例,因此它在定义时也会接收:data、methods、生命周期函数等
- 不同的是组件不会与页面的元素绑定,否则就无法复用了,因此没有el属性。
- 但是组件渲染需要html模板,所以增加了template属性,值就是HTML模板
- 全局组件定义完毕,任何vue实例都可以直接在HTML中通过组件名称来使用组件了。
- data的定义方式比较特殊,必须是一个函数
}
组件的复用:{
定义好的组件,可以任意复用多次:
<div id="app">
<!--使用定义好的全局组件-->
<counter></counter>
<counter></counter>
<counter></counter>
</div>
每个组件互不干扰,都有自己的count值。组件的data属性必须是函数!
当定义这个 <counter> 组件时,它的data 并不是像这样直接提供一个对象:
data: {
count: 0
}
取而代之的是,一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝:
data: function () {
return {
count: 0
}
}
如果 Vue 没有这条规则,点击一个按钮就会影响到其它所有实例!
}
局部注册:{
一旦全局注册,就意味着即便以后你不再使用这个组件,它依然会随着Vue的加载而加载。
因此,对于一些并不频繁使用的组件,我们会采用局部注册。
我们先在外部定义一个对象,结构与创建组件时传递的第二个参数一致:
const counter = {
template:'<button v-on:click="count++">你点了我 {{ count }} 次,我记住了.</button>',
data(){
return {
count:0
}
}
};
然后在Vue中使用它:
var app = new Vue({
el:"#app",
components:{
counter:counter // 将定义的对象注册为组件
}
})
components就是当前vue对象子组件集合。
其key就是子组件名称
其值就是组件对象的属性
效果与刚才的全局注册是类似的,不同的是,这个counter组件只能在当前的Vue实例中使用
}
}