vue详解

安装Vue

1.直接使用script引用

使用最新版本

<script src="https://cdn.jsdelivr.net/npm/vue"></script>

使用指定版本

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>

2.使用npm安装

由于 npm 安装速度慢,可以使用淘宝的镜像及其命令 cnpm

# 查看版本
$ npm -v
2.3.0
# 升级或安装 cnpm
npm install cnpm -g

安装vue

 最新稳定版
$ npm install vue 
或使用cnpm安装
cnpm install vue

命令行工具vue-cli

安装vue-cli

  • 查看vue版本: vue --version
  • 如果是旧版本则卸载: npm uninstall vue-cli -g
  • 安装新版本: npm install -g @vue/cli

创建项目

  • vue create hello_world

  • cd hello_world/

  • npm run serve

    18

目录结构

19

  • node_modules : npm 加载的项目依赖模块
  • src: 这里是我们要开发的目录,包含:
    • assets: 放置一些图片,如logo等。
    • components: 目录里面放了一个组件文件,可以不用。
    • App.vue: 项目入口文件,我们也可以直接将组件写这里,而不使用 components 目录。
    • main.js: 项目的核心文件。

main.js

import  from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
}).$mount('#app')

App.vue

<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <HelloWorld msg="Welcome to Your Vue.js App"/>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'

export default {
  name: 'app',
  components: {
    HelloWorld
  }
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

Vue.js

起步

每个 Vue 应用都需要通过实例化 Vue 来实现。语法格式如下:

var vm = new Vue({
  // 选项
})

模板语法

Vue.js 使用了基于 HTML 的模板语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据。所有 Vue.js 的模板都是合法的 HTML ,所以能被遵循规范的浏览器和 HTML 解析器解析。

插值

文本

数据绑定最常见的形式就是使用 {}(双大括号)的文本插值

<div id="app">
  <p>{{ message }}</p>
</div>

<script>
new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue.js!'
  }
})
</script>
原始Html

双大括号会将数据解释为普通文本,而非 HTML 代码。为了输出真正的 HTML,你需要使用 [v-html 指令]

<div id="app">
    <div v-html="message"></div>
</div>
    
<script>
new Vue({
  el: '#app',
  data: {
    message: '<h1>菜鸟教程</h1>'
  }
})
</script>
属性

HTML 属性中的值应使用 v-bind 指令。

<div id="app">
  <label for="r1">修改颜色</label><input type="checkbox" v-model="use" id="r1">
  <br><br>
  <div v-bind:class="{'class1': use}">
    v-bind:class 指令
  </div>
</div>
    
<script>
new Vue({
    el: '#app',
  data:{
      use: false
  }
});
</script>
表达式

Vue.js 都提供了完全的 JavaScript 表达式支持。


<div id="app">
    {{5+5}}<br>
    {{ ok ? 'YES' : 'NO' }}<br>
    {{ message.split('').reverse().join('') }}
    <div v-bind:id="'list-' + id">菜鸟教程</div>
</div>
    
<script>
new Vue({
  el: '#app',
  data: {
    ok: true,
    message: 'RUNOOB',
    id : 1
  }
})
</script>

指令

指令是带有 v- 前缀的特殊属性。


<div id="app">
    <p v-if="seen">现在你看到我了</p>
</div>
    
<script>
new Vue({
  el: '#app',
  data: {
    seen: true
  }
})
</script>
参数

参数在指令后以冒号指明。

<a v-on:click="doSomething">
修饰符

修饰符是以半角句号 . 指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。例如,.prevent 修饰符告诉 v-on 指令对于触发的事件调用 event.preventDefault()

<form v-on:submit.prevent="onSubmit"></form>

用户输入

  • 在 input 输入框中我们可以使用 v-model 指令来实现双向数据绑定。

  • v-model 指令用来在 input、select、textarea、checkbox、radio 等表单控件元素上创建双向数据绑定,根据表单上的值,自动更新绑定的元素的值。

<div id="app">
    <p>{{ message }}</p>
    <input v-model="message">
</div>
	
<script>
new Vue({
  el: '#app',
  data: {
    message: 'Runoob!'
  }
})
</script>

过滤器

Vue.js 允许你自定义过滤器,被用作一些常见的文本格式化。由"管道符"指示, 格式如下:

<!-- 在两个大括号中 -->
{{ message | capitalize }}

<!-- 在 v-bind 指令中 -->
<div v-bind:id="rawId | formatId"></div>

缩写

v-bind缩写
<!-- 完整语法 -->
<a v-bind:href="url"></a>
<!-- 缩写 -->
<a :href="url"></a>
v-on缩写
<!-- 完整语法 -->
<a v-on:click="doSomething"></a>
<!-- 缩写 -->
<a @click="doSomething"></a>

条件语句

v-if

<p v-if="seen">现在你看到我了</p>

v-else

<div id="app">
    <div v-if="Math.random() > 0.5">
      Sorry
    </div>
    <div v-else>
      Not sorry
    </div>
</div>
    
<script>
new Vue({
  el: '#app'
})
</script>

v-else-if

   <div v-if="type === 'A'">
      A
    </div>
    <div v-else-if="type === 'B'">
      B
    </div>
    <div v-else-if="type === 'C'">
      C
    </div>
    <div v-else>
      Not A/B/C
    </div>

v-show

可以使用 v-show 指令来根据条件决定是否展示元素

<h1 v-show="ok">Hello!</h1>

循环语句

v-for

<div id="app">
  <ul>
    <li v-for="n in 10">
     {{ n }}
    </li>
  </ul>
</div>

计算属性

计算属性关键词: computed。计算属性在处理一些复杂逻辑时是很有用的。

监听属性

可以通过 watch 来响应数据的变化


<div id = "app">
    <p style = "font-size:25px;">计数器: {{ counter }}</p>
    <button @click = "counter++" style = "font-size:25px;">点我</button>
</div>
<script type = "text/javascript">
var vm = new Vue({
    el: '#app',
    data: {
        counter: 1
    }
});
vm.$watch('counter', function(nval, oval) {
    alert('计数器值的变化 :' + oval + ' 变为 ' + nval + '!');
});
</script>

样式绑定v-bind

属性绑定

class 与 style 是 HTML 元素的属性,用于设置元素的样式,我们可以用 v-bind 来设置样式属性。

<style>
.active {
	width: 100px;
	height: 100px;
	background: green;
}
.text-danger {
	background: red;
}
</style>
</head>
<body>
<div id="app">
  <div class="static"
     v-bind:class="{ active: isActive, 'text-danger': hasError }">
  </div>
</div>

<script>
new Vue({
  el: '#app',
  data: {
    isActive: true,
	hasError: true
  }
})
</script>

数组绑定

<style>
.active {
	width: 100px;
	height: 100px;
	background: green;
}
.text-danger {
	background: red;
}
</style>
</head>
<body>
<div id="app">
	<div v-bind:class="[activeClass, errorClass]"></div>
</div>

<script>
new Vue({
  el: '#app',
  data: {
    activeClass: 'active',
    errorClass: 'text-danger'
  }
})
</script>

事件处理v-on


<div id="app">
   <!-- `greet` 是在下面定义的方法名 -->
  <button v-on:click="greet">Greet</button>
</div>
 
<script>
var app = new Vue({
  el: '#app',
  data: {
    name: 'Vue.js'
  },
  // 在 `methods` 对象中定义方法
  methods: {
    greet: function (event) {
      // `this` 在方法里指当前 Vue 实例
      alert('Hello ' + this.name + '!')
      // `event` 是原生 DOM 事件
      if (event) {
          alert(event.target.tagName)
      }
    }
  }
})
// 也可以用 JavaScript 直接调用方法
app.greet() // -> 'Hello Vue.js!'
</script>

表单v-model

v-model指令在表单控件元素上创建双向数据绑定。

<div id="app">
  <p>input 元素:</p>
  <input v-model="message" placeholder="编辑我……">
  <p>消息是: {{ message }}</p>
    
  <p>textarea 元素:</p>
  <p style="white-space: pre">{{ message2 }}</p>
  <textarea v-model="message2" placeholder="多行文本输入……"></textarea>
</div>
 
<script>
new Vue({
  el: '#app',
  data: {
    message: 'Runoob',
    message2: '菜鸟教程\r\nhttp://www.runoob.com'
  }
})
</script>

v-slot 插槽

v-slot取代了slotslot-scope这两个目前已被废弃但未被移除且仍在文档中的特性。v-slot指令结合了slotslot-scope的功能。

插槽作用

插槽就是子组件中的提供给父组件使用的一个占位符,用<slot></slot> 表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的<slot></slot>标签。

匿名插槽(也叫默认插槽default)

没有命名,有且只有一个

父页面:
<todo-list> 
    <template v-slot:default>
       任意内容
       <p>我是匿名插槽 </p>
    </template>
</todo-list>  
//v-slot:default写上感觉和具名写法比较统一,容易理解,也可以不用写
子组件 todoList.vue:
<slot>我是默认值</slot>
##显示##
// 任意内容
// 我是匿名插槽

具名插槽

相对匿名插槽组件slot标签带name命名的

//父页面
<todo-list> 
    <template v-slot:todo>
       任意内容
       <p>我是匿名插槽 </p>
    </template>
</todo-list> 
// todo
data() {
   return {
    dynamicSlotName:"todo" 
   }
 },
子组件
<slot name="todo">我是默认值</slot>
##显示##
// 任意内容
// 我是匿名插槽

动态命名

v-slot:{dynamicSlotName}``//替换标签上 v-slot:todo

具名插槽缩写

#todo 替换标签上 v-slot:todo

作用域插槽

子组件内数据可以被父页面拿到(解决了数据只能从父页面传递给子组件)

父页面:
<todo-list>
 <template v-slot:todo="slotProps" >
   {{slotProps.user.firstName}}
 </template> 
</todo-list> 
//slotProps 可以随意命名
//slotProps 接取的是子组件标签slot上属性数据的集合所有v-bind:user="user"
子组件:
<slot name="todo" :user="user" :test="test">
    {{ user.lastName }}
 </slot> 
data() {
    return {
      user:{
        lastName:"Zhang",
        firstName:"yue"
      },
      test:[1,2,3,4]
    }
  },
// {{ user.lastName }}是默认数据  v-slot:todo 当父页面没有(="slotProps")
// 时显示 Zhang
 
 
## 显示 ##
// yue

解构插槽Prop

父页面 (子组件不变 显示一样)

// 相当于
function (slotProps) {
 // 插槽内容
}
(slotProps)=>参数可以用slot标签上现有的值({user,test})替换
<todo-list>
 <template v-slot:todo="{user,test}
" >
   {{user.firstName}}
 </template> 
</todo-list> 
## 显示 ##
## // yue

参数值替换名字(可以后看)

<todo-list>
 <template v-slot:todo="{user:person,test}
" >
   {{person.firstName}}
 </template> 
</todo-list> 
 
// v-slot:[dynamicSlotName]="{user:person,test}
## 显示 ##
## // yue

组件Component

Vue.component(tagName, options)

tagName 为组件名,options 为配置选项。

调用组件方式:

<div id="app">
    <runoob></runoob>
</div>
 
<script>
// 注册
Vue.component('runoob', {
  template: '<h1>自定义组件!</h1>'
})
// 创建根实例
new Vue({
  el: '#app'
})
</script>

import

引入js文件

在用的那一页,引入文件
import tools from './tools.js'

相应的js文件里面,必须是暴露出来的
function add(a,b){
	return a+b;
}
function isFunction(fn){
	return typeof fn === 'function'
}
export default {a: 1, add, isFunction}

引入组件

import name1 from './name1'
import name2 from './name2'
    components:{
         name1,
         name2,
    },

export

  • export 导出模块,以便在其他模块import
  • export 和export default 的区别在于:export 可以导出多个命名模块,export default 只能导出一个默认模块,这个模块可以匿名

切记,一个js文件中,只能有一个export default; 但是,一个js文件中,可以有多个export。

export 实例:

//demo1.js导出
export const str = 'hello world'
 
export function f(a){
    return a+1
}

//demo2.js导入
import { str, f } from 'demo1'

export default实例:

//demo1.js导出
export default {
    a: 'hello',
    b: 'world'      
}

//demo2.js导入
//引入的时候可以给这个模块取任意名字,例如 "obj",且不需要用大括号括起来。
import obj from 'demo1'

属性前面加冒号

加上冒号会首先将这个属性当作变量或者表达式解析,没加冒号就直接是当字符串解析。

例如:
<tab :line-width="2" active-color="#fc378c">
  <tab-item :selected="demo2 === item" 
            v-for="item in list2" 
            @click="demo2 = item"></tab-item>
</tab>

还有一种类class前面加冒号是:class是v-bind:class的简写

数据操作

data

类型:Object | Function

限制:组件的定义只接受 function

data和computed区别

  • data属性的值,不会随赋值变量的改动而改动。如果要改变这个属性的值,则需要直接给data属性赋值,视图上对这个属性的显示才会变。

  • computed属性,属于持续变化跟踪。在computed属性定义的时候,这个computed属性就与给它赋值的变量绑定了。改变这个赋值变量,computed属性值会随之改变。

  • data 只是对于你想要展示的数据的定义,但是,如果该数据需要进行复杂的处理(例如将其变为翻转字符串等),就需要计算属性的帮忙。

<span>{{reversedMessage}}</span>
data() {
  message: '',
},
computed: {
  reversedMessage() {
    return this.message.split('').reverse().join('');
  },
},

computed

类型:{ [key: string]: Function | { get: Function, set: Function } }

计算属性:主要是对原数据进行改造输出。改造输出:包括格式化数据(价格,日期),大小写转换,排序,添加符号

<template>
      <p>Computed reversed message: "{{ reversedMessage }}"</p>
</template>
export default {

  name: 'Home',
  data: function () {
    return {
      ......
    }
  },
  computed: {
    // 计算属性的 getter
    reversedMessage: function () {
      // console.log('1')
      return this.msg.split('').reverse().join('')
    }
  }
......

computed并不是一个方法,而是依赖于属性的,就是一个属性的封装,属性的值不变化,那么不会调用computed

methods

类型:{ [key: string]: Function }

方法属性:用于绑定html中的事件对应的方法

methods:{
    add (num) {
        this.count += num;
    }
}

computed和method区别

我们可以把同一函数定义为一个方法而不是计算属性,两种方式最后的结果一样的,不同的是,计算属性是基于他们的依赖进行缓存的,只有相关依赖的值发生改变才会重新求值;而方法只要被触发就会再次执行该函数。如果你不希望有缓存,请用方法来代替。

类型是否被缓存备注
computed只要依赖值有变化就会立马执行
method需要绑定事件
<template>
    <p>{{msg}}</p>
    <button v-on:click="reverseMessage">逆转消息</button>
</template>
export default {

  name: 'Home',
  data: function () {
    return {
      ......
      msg: 'this msg for vue.js!!!',
      ......
    }
  },
  methods: {
    reverseMessage: function () {
      this.msg = this.msg.split('').reverse().join('')
      return this.msg
    }
 ......

watch

类型:{ [key: string]: string | Function | Object | Array }

watch与computed区别

在很多情况下,computed 会比 watch 使用起来更加方便,但是当需要在数据变化时执行异步或者开销比较大的情况下,用 watch 会更加合适。

类型目的备注
computed依赖变动实时更新数据更新数据
watch观察某一特定的值,执行特定的函数观察数据
<template>
  <div>
    <el-input v-model="demo"></el-input>
    {{value}}
  </div>
</template>
<script>
  export default {
    name: 'index',
    data() {
      return {
        demo: '',
        value: ''
      };
    },
    watch: {
      demo(val) {
        this.value = this.demo;
      }
    }
  };
</script>

上面这个就浅显易懂了,通过watch来直接监测demo,如果demo的值变化,value的值也会跟着一起变化。

props

类型:Array | Object

子组件中的data数据,不是通过父组件传递的是子组件私有的,是可读可写的。

子组件中的所有 props中的数据,都是通过父组件传递给子组件的,是只读的。

props 可以是数组或对象,用于接收来自父组件的数据

<!--父组件-->
<template>
  <div>
      <hello-world2 :good = "good"></hello-world2> //向子组件传值
  </div>
</template>

<script>
  import helloWorld2 from "./HelloWorld2"  //引用子组件页面

  export default {
    name: "HelloWorld3",
    data() {
      return {
        good: "我是从hello word3传递过来的"
      }
    },
    components: {
      'hello-world2': helloWorld2   //注册子组件
    },
  }
</script>
<!--子组件-->
<template>
    <div>{{good}}</div>
</template>

<script>
  export default {
    props: ['good'], //通过props获取父组件传递过来的值
    data: function () {
      return {}
    },
    methods: {}
  }
</script>

总结:父组件通过v-bind向子组件传值,子组件通过props来获取父组件传递过来的值,被引用的就是子组件

Vue 文件基本结构

<template>
  <div class="container">
   </div>
</template>

<script type="text/ecmascript-6">
export default {
    data(){
        return{
        // 数据
        };
    },
    components:{
      // 组件注册
    },
    beforeCreate(){
      // 在实例初始化之后,数据观测(data observer) 和 event/watcher 事件配置之前被调用。
    },
    create(){
      // 实例已经创建完成之后被调用。在这一步,实例已完成以下的配置:数据观测(data observer),属性和方法的运算, watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。
    },
    beforeMount(){
      // 在挂载开始之前被调用:相关的 render 函数首次被调用。
    },
    mounted(){
      // el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。
    },
    beforeUpdate(){
      // 数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。 你可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程。
    },
    updated(){
      // 由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。
      // 当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态,因为这可能会导致更新无限循环
    },
    beforeDestroy(){
      // 实例销毁之前调用。在这一步,实例仍然完全可用。 
    },
    destroyed(){
      // Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。 该钩子在服务器端渲染期间不被调用。
    },
    computed:{
      // 计算属性
    },
    watch:{
      // 数据监听
    },
    methods:{
      // 方法定义
    }
}
</script>
<style>
  // css 样式
</style>

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×