【Vue】 基础语法

Vue3 教程
Vue3 教程 官网
Vue3 入门指南与实战案例

  1. vue create 名称
  2. cd 所在文件夹
  3. npm run serve
  4. 在浏览器中打开提供的网站
  5. 在index.html编写,每次保存网站都会更新
<!--在 head 中-->
<!--在 HTML 页面中引入 Vue 的 JS 文件-->
<script src="https://unpkg.com/vue@next"></script>
<!--在 HTML 页面中引入 Vue 路由-->
<script src="https://unpkg.com/vue-router@4"></script>
<!--在 HTML 页面中引入 axios -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://cdn.staticfile.org/axios/0.18.0/axios.min.js"></script>

错误

报错:‘xxxx‘ is declared but its value is never read.Vetur(6133)

路径

Vue文件中引用路径:

  • ./ 当前文件同级目录
  • @ 可以使用 @ 代替 /src 目录,避免易错的相对路径
//vite.config.ts
import { defineConfig } from 'vite';

export default defineConfig({
  resolve: {
    alias: {
      '@': path.resolve(__dirname, 'src') // 设置`@`指向`src`
    }
  }
})
//vue.config.js
  chainWebpack(config) {
    config.resolve.alias
      .set('@', resolve('src'))
      .set('assets', resolve('src/assets'))
      .set('utils', resolve('src/utils'));
  },

组件

Vue3 中的应用是通过使用 createApp 函数来创建的,参数是根组件(例:HelloVueApp)

Vue.createApp({...}).mount('#hello-vue')

const HelloVueApp = {...}
Vue.createApp(HelloVueApp).mount('#hello-vue')

const HelloVueApp = {...}
const app = Vue.createApp(HelloVueApp)
app.mount('#hello-vue')    //hello-vue与app不要取一样的名字,不然会错,页面全空白就是有错误

以上三种表示一个应用需要被挂载到一个 DOM 元素中,以上代码使用 mount('#hello-vue') 将 Vue 应用 HelloVueApp 挂载到 <div id="hello-vue"></div> 中。

自定义组件

//全局组件
const app = Vue.createApp({...})
app.component('my-component-name', {...})  //my-component-name 为组件名

//调用该组件
<my-component-name></my-component-name>
//局部组件
var runoobA = {...}
 
const app = Vue.createApp({
  components: {
    'runoob-a': runoobA
  }
})

//调用该组件
<runoob-a></runoob-a>

组件属性汇总

const myMixin = {}             //要混入的组件

const helloworld = {
  data() {return {count: 2}},   //data() 选项
  methods: {},                  //methods 方法属性,包含了所需方法的对象
  computed: {},                 //computed 计算属性
  watch: {},                    //watch 监听属性
  mixins: [myMixin]             //mixins 混入属性
}
vm = Vue.createApp(helloworld).mount('#hello')
vm.$watch('对象',function(...)){...}   //组件里面没写watch也能有这条
vm.$data.count = 6
//自定义组件
const app = Vue.createApp({})
// 定义一个名为 runoob的新全局组件
app.component('runoob', {             //除了可以有上面的属性外,还有:
	props: ['title'],                 //props属性:把数据传给子组件
	
	//单行用单引号                     //template属性:子组件
    template: '<h1>{{ title }}</h1>',
    //多行用反引号
    template: `
	    <button @click="count++">
	      点了 {{ count }} 次!
	    </button>`,
	
	//各种钩子函数
	// 在绑定元素的 attribute 或事件监听器被应用之前调用
	created() {},
	// 在绑定元素的父组件挂载之前调用
	beforeMount() {},
	// 绑定元素的父组件被挂载时调用
	mounted() {},
	// 在包含组件的 VNode 更新之前调用
	beforeUpdate() {},
	// 在包含组件的 VNode 及其子组件的 VNode 更新之后调用
	updated() {},
	// 在绑定元素的父组件卸载之前调用
	beforeUnmount() {},
	// 卸载绑定元素的父组件时调用
	unmounted() {}    
	   
})
 
app.mount('#hello')

钩子函数

Vue3生命周期钩子(hooks)完整指南
Vue3.x 的生命周期和钩子函数
指令定义函数提供了几个钩子函数:

  • 导入:import { onActivated, onMounted } from 'vue'
  • 钩子函数更新:
Vue2--------------vue3
beforeCreate  -> setup()
created       -> setup()
beforeMount   -> onBeforeMount
mounted       -> onMounted
beforeUpdate  -> onBeforeUpdate
updated       -> onUpdated
beforeDestroy -> onBeforeUnmount
destroyed     -> onUnmounted
activated     -> onActivated
deactivated   -> onDeactivated
errorCaptured -> onErrorCaptured
  • 功能
    setup() :开始创建组件之前,在beforeCreatecreated之前执行。创建的是datamethod
    onBeforeMount() : 组件挂载到节点上之前执行的函数。
    onMounted() : 组件挂载完成后执行的函数。
    onBeforeUpdate(): 组件更新之前执行的函数。
    onUpdated(): 组件更新完成之后执行的函数。
    onBeforeUnmount(): 组件卸载之前执行的函数。
    onUnmounted(): 组件卸载完成后执行的函数
    onActivated(): 被包含在<keep-alive>中的组件,会多出两个生命周期钩子函数。被激活时执行。例如,使用keep-alive管理不同的tab视图,每次切换tab时,当前的tab将会触发activated钩子。使用组件会将数据保留在内存中,比如我们不想每次看到一个页面都重新加载数据,就可以使用组件解决。
    onDeactivated(): 比如从 A 组件,切换到 B 组件,A 组件消失时执行。
    onErrorCaptured(): 当捕获一个来自子孙组件的异常时激活钩子函数(以后用到再讲,不好展现)。

钩子函数的参数有:

  • el:el 指令绑定到的元素。这可用于直接操作 DOM。
  • binding:binding 是一个对象,包含以下属性:
    • instance:使用指令的组件实例。
    • value:传递给指令的值。例如,在 v-my-directive=“1 + 1” 中,该值为 2。
    • oldValue:先前的值,仅在 beforeUpdate 和 updated 中可用。值是否已更改都可用。
    • arg:参数传递给指令 (如果有)。例如在 v-my-directive:foo 中,arg 为 “foo”。
    • modifiers:包含修饰符 (如果有) 的对象。例如在 v-my-directive.foo.bar 中,修饰符对象为 {foo: true,bar: true}。
    • dir:一个对象,在注册指令时作为参数传递。
  • vnode:作为 el 参数收到的真实 DOM 元素的蓝图。
  • prevNode:上一个虚拟节点,仅在 beforeUpdate 和 updated 钩子中可用。
import { createApp } from 'vue'
const app = createApp({})
 
// 注册
app.directive('my-directive', {
  // 指令是具有一组生命周期的钩子:
  // 在绑定元素的 attribute 或事件监听器被应用之前调用
  created() {},
  // 在绑定元素的父组件挂载之前调用
  beforeMount() {},
  // 绑定元素的父组件被挂载时调用
  mounted() {},
  // 在包含组件的 VNode 更新之前调用
  beforeUpdate() {},
  // 在包含组件的 VNode 及其子组件的 VNode 更新之后调用
  updated() {},
  // 在绑定元素的父组件卸载之前调用
  beforeUnmount() {},
  // 卸载绑定元素的父组件时调用
  unmounted() {}
})
 
// 注册 (功能指令)
app.directive('my-directive', () => {
  // 这将被作为 `mounted` 和 `updated` 调用
})
 
// getter, 如果已注册,则返回指令定义
const myDirective = app.directive('my-directive')

不要在选项 property 或回调上使用箭头函数,比如 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
之类的错误。

props 属性

Props
通过 Prop 向子组件传递数据

<!-- 包含该 prop 没有值的情况在内,都意味着 `true` -->
<!-- 如果没有在 props 中把 is-published 的类型设置为 Boolean,则这里的值为空字符串,而不是“true”。 -->
<blog-post is-published></blog-post>
<div id="app">
  <site-name title="Google"></site-name>
  <site-name title="Runoob"></site-name>
  <site-name title="Taobao"></site-name>
</div>
 
<script>
const app = Vue.createApp({})
 
app.component('site-name', {         //局部组件site-name是父组件
  props: ['title'],                  //父组件的数据通过 props 把数据传给子组件
  template: `<h4>{{ title }}</h4>`   //子组件
})
 
app.mount('#app')
</script>
<!--也可以用 v-bind 动态绑定 props 的值到父组件的数据中。
	每当父组件的数据变化时,该变化也会传导给子组件-->
<div id="app">
  <site-info
    v-for="site in sites"
    :id="site.id"        <!--v-bind 的缩写-->  
    :title="site.title"
  ></site-info>
</div>
 
<script>
const Site = {
  data() {
    return {
      sites: [
        { id: 1, title: 'Google' },
        { id: 2, title: 'Runoob' },
        { id: 3, title: 'Taobao' }
      ]
    }
  }
}
 
const app = Vue.createApp(Site)
 
app.component('site-info', {
  props: ['id','title'],
  template: `<h4>{{ id }} - {{ title }}</h4>`
})
 
app.mount('#app')
</script>
//可以为 props 中的值提供一个带有验证需求的对象,而不是一个字符串数组。例如:
Vue.component('my-component', {
  props: {
    // 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
    propA: Number,
    // 多个可能的类型
    propB: [String, Number],
    // 必填的字符串
    propC: {
      type: String,
      required: true
    },
    // 带有默认值的数字
    propD: {
      type: Number,
      default: 100
    },
    // 带有默认值的对象
    propE: {
      type: Object,
      // 对象或数组默认值必须从一个工厂函数获取
      default: function () {
        return { message: 'hello' }
      }
    },
    // 自定义验证函数
    propF: {
      validator: function (value) {
        // 这个值必须匹配下列字符串中的一个
        return ['success', 'warning', 'danger'].indexOf(value) !== -1
      }
    }
  }
})

type 可以是下面原生构造器:
String
Number
Boolean
Array
Object
Date
Function
Symbol
type 也可以是一个自定义构造器,使用 instanceof 检测。

computed 计算属性

  • 可以使用 methods 来替代 computed,效果上两个都是一样的,
  • 但是 computed 是基于它的依赖缓存,只有相关依赖发生改变时才会重新取值。
  • 而使用 methods ,在重新渲染的时候,函数总会重新调用执行。
  • 可以说使用 computed 性能会更好,但是如果你不希望缓存,你可以使用 methods 属性。

computed 属性默认只有 getter ,不过在需要时你也可以提供一个 setter :

//例子
  computed: {
    site: {
      // getter
      get: function () {
        return this.name + ' ' + this.url
      },
      // setter
      set: function (newValue) {
        var names = newValue.split(' ')
        this.name = names[0]
        this.url = names[names.length - 1]
      }
    }
  }

mixins 混入属性

  • 混入 (mixins)定义了一部分可复用的方法或者计算属性。混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被混入该组件本身的选项。
  • 全局混入:一旦使用全局混入对象,将会影响到 每个单独创建的 Vue 实例 (包括第三方模板)。使用恰当时,可以为自定义对象注入处理逻辑。
  • 选项合并:当组件和混入对象含有同名选项时,这些选项将以恰当的方式混合。
    • 数据对象在内部会进行浅合并 (一层属性深度),在和组件的数据发生冲突时以组件数据优先。
    • 同名钩子函数将合并为一个数组,因此都将被调用。另外,mixin 对象的钩子将在组件自身钩子之前调用。
    • 两个对象键名冲突时,取组件对象的键值对。例如 methods、components 和 directives,将被合并为同一个对象。
// 定义混入对象
const myMixin = {
  created() {
    this.hello()
  },
  methods: {
    hello() {
      console.log('欢迎来到混入实例-RUNOOB!')
    }
  }
}
 
// 定义一个应用,使用混入
const app = Vue.createApp({
  mixins: [myMixin]
})
 
app.mount('#app') // => "欢迎来到混入实例-RUNOOB!"
//选项合并
<script type = "text/javascript">
const myMixin = {
  data() {
    return {
      message: 'hello',
      foo: 'runoob'
    }
  }
}
 
const app = Vue.createApp({
  mixins: [myMixin],
  data() {
    return {
      message: 'goodbye',
      bar: 'def'
    }
  },
  created() {
    document.write(JSON.stringify(this.$data)) 
  }
})

//输出结果为:
{"message":"goodbye","foo":"runoob","bar":"def"}
const myMixin = {
  created() {
    console.log('mixin 对象的钩子被调用')
  }
}

const app = Vue.createApp({
  mixins: [myMixin],
  created() {
    console.log('组件钩子被调用')
  }
})

// => "mixin 对象的钩子被调用"
// => "组件钩子被调用"
//
const myMixin = {
  methods: {
    foo() {
      console.log('foo')
    },
    conflicting() {
      console.log('from mixin')
    }
  }
}
 
const app = Vue.createApp({
  mixins: [myMixin],
  methods: {
    bar() {
      console.log('bar')
    },
    conflicting() {
      console.log('from self')
    }
  }
})
 
const vm = app.mount('#app')
 
vm.foo() // => "foo"
vm.bar() // => "bar"
vm.conflicting() // => "from self"
//全局混入
const app = Vue.createApp({
  myOption: 'hello!'
})
 
// 为自定义的选项 'myOption' 注入一个处理器。
app.mixin({
  created() {
    const myOption = this.$options.myOption
    if (myOption) {
      document.write(myOption)
    }
  }
})
 
app.mount('#app') // => "hello!"

watch 监听属性

Vue3 监听属性

指令

<!-- 在 index.html 的 body 中 -->
<div id="hello-vue"> 
  <p>123456</p> 

  <!-- 对应组件实例中 message 属性的值-->
  <p>{{ message }}</p>
  
  <!-- 可使用JavaScript表达式 -->
  <p>{{5+5}}</p>
  <!--  这是语句,不是表达式:-->
  <!-- <p>{{var a = 1}}</p> -->
  <!-- 流控制也不会生效,请使用三元表达式 -->
  <!-- <p>{{ if (true) { return message } }}</p> -->
  
  <!-- 指令:带有 v- 前缀的特殊属性-->
  <!-- v-once:执行一次性地插值,当数据改变时,插值处的内容不会更新 -->
  <p><span v-once>不会改变: {{ message }}</span> </p>
  <!-- v-html:输出 html 代码 ,这里的hhhhhh不会输出-->
  <p><span v-html="rawHtml">hhhhhhhhh</span></p>
  <!-- v-model:如:用户输入,在 input 输入框中我们可以使用v-model 指令来实现双向数据绑定: -->
  <input v-model="message">
  <!--  v-show: 来根据条件展示元素 -->
  <h1 v-show="ok">Hello!</h1>

  <!-- v-bind:双大括号不能在HTML attribute中使用,所以使用 v-bind 指令
	   v-bind 绑定 HTML 特性到一个表达式-->
  <p><div v-bind:id="'list-'">菜鸟教程</div></p>
  <p><a v-bind:href="url">菜鸟教程</a></p> 
  <p><a :href="url">缩写格式</a></p> 

  <!-- v-on:监听  -->
  <button v-on:click="">完整格式</button>
  <button @click="">缩写格式</button>

  <!-- v-if: 多个元素,可以包裹在 <template> 元素上-->
  <p v-if="seen">现在你看到我了</p>
  <template v-if="seen">
    <h1>网站</h1>
    <p>Google</p>
    <p>Runoob</p>
    <p>Taobao</p>
  </template>
  <!-- v-else:如 随机生成一个数字,判断是否大于 0.5 -->
  <div v-if="Math.random() > 0.5">随机数大于 0.5</div>
  <div v-else>随机数小于等于 0.5</div>
  <!-- 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-for: 需要以 site in sites 形式的特殊语法, 
        sites 是源数据数组并且 site 是数组元素迭代的别名。
        v-for 可以绑定数据到数组来渲染一个列表 -->
  <li v-for="site in sites">{{ site.text }}</li>
  <li v-for="(site, index) in sites">{{ index }}--{{ site.text }}</li>
  <template v-for="site in sites">
    <li>{{ site.text }}</li>
    <li>--------------</li>
  </template>
  <li v-for="value in object">{{ value }}</li>
  <li v-for="(value, key, index) in object">
    {{ index }}. {{ key }} : {{ value }}
  </li>
  <li v-for="n in 10">{{ n }}</li>
  <li v-for="n in evenNumbers">{{ n }}</li>
</div>


<script>
  const HelloVueApp = {
  	//`data` 选项是一个函数。Vue 在创建新组件实例的过程中调用此函数。
  	//它应该返回一个对象,然后 Vue 会通过响应性系统将其包裹起来,
  	//并以 $data 的形式存储在组件实例中。
    data() {
      return {
        message: 'Hello V!!',
        rawHtml: '<span style="color: red">这里会显示红色!</span>',
        seen: true,  /* 改为false,信息就无法显示 */
        url: 'https://www.runoob.com',
        type: "C",
        ok: true,
        sites: [
          { text: 'Google' },
          { text: 'Runoob' },
          { text: 'Taobao' }
        ],
        object: {
          name: '菜鸟教程',
          url: 'http://www.runoob.com',
          slogan: '123456'
        },
        numbers: [ 1, 2, 3, 4, 5 ]
      }
    },
    computed: {
      evenNumbers() {
          return this.numbers.filter(number => number % 2 === 0)
      }
    }
  }
  
  Vue.createApp(HelloVueApp).mount('#hello-vue')
</script> 

v-on 指令

Vue指令之v-on

  • v-on 指令监听 DOM 事件
  • v-on 指令可以缩写为 @ 符号
  • v-on 指令是事件绑定指令,当用户需要点击,按下键盘,滚动鼠标等操作时,想要添加一些自己的逻辑处理时,就可以为特定的元素绑定一些特定的事件。
  • 如果是点击事件就写click,如果是鼠标移入事件就写monseenter,如果是鼠标双击事件就写 dblclick v-on:click
<div id="hello">
      <!-- v-on 指令可以缩写为 @ 符号 -->
      <button @click="counter += 1">增加 1</button>
      <p>这个按钮被点击了 {{ counter }} 次。</p>
      <!-- 接收一个定义的方法来调用 -->
      <!-- `greet` 是在下面定义的方法名 -->
      <button @click="greet">点我</button>
      <!-- 用内联 JavaScript 语句 -->
      <button @click="say('hi')">Say hi</button>
      <!-- 事件处理程序中可以有多个方法,这些方法由逗号运算符分隔 -->
      <button @click="one($event), two($event)">点我</button>
    </div>
    
    <script>
    const helloworld = {
      data() {
        return {
          counter: 0,  
          name: 'Runoob'        
        }          
      },
      methods: {
        greet(event) {
          // `methods` 内部的 `this` 指向当前活动实例
          alert('Hello ' + this.name + '!')
          // `event` 是原生 DOM event
          if (event) {
            alert(event.target.tagName)
          }
        },
        say(message) {
          alert(message)
        },
        one(event) {
          alert("第一个事件处理器逻辑...")
        },
        two(event) {
          alert("第二个事件处理器逻辑...")
        }
      }
    }    
    Vue.createApp(helloworld).mount('#hello')
    </script>
  • 事件修饰符
    v-on 提供了事件修饰符来处理 DOM 事件细节
    .stop - 阻止冒泡
    .prevent - 阻止默认事件
    .capture - 阻止捕获
    .self - 只监听触发该元素的事件
    .once - 只触发一次
    .left - 左键事件
    .right - 右键事件
    .middle - 中间滚轮事件
  • 按键修饰符
    Vue 允许为 v-on 在监听键盘事件时添加按键修饰符
    全部的按键别名:
    .enter
    .tab
    .delete (捕获 “删除” 和 “退格” 键)
    .esc
    .space
    .up
    .down
    .left
    .right
    系统修饰键:
    .ctrl
    .alt
    .shift
    .meta
    鼠标按钮修饰符:
    .left
    .right
    .middle
  • .exact 修饰符
    .exact 修饰符允许你控制由精确的系统修饰符组合触发的事件。
实例
<!-- 即使 Alt 或 Shift 被一同按下时也会触发 -->
<button @click.ctrl="onClick">A</button>
<!-- 有且只有 Ctrl 被按下的时候才触发 -->
<button @click.ctrl.exact="onCtrlClick">A</button>
<!-- 没有任何系统修饰符被按下的时候才触发 -->
<button @click.exact="onClick">A</button>

v-bind 指令

  • 在需要动态绑定的属性前面加上v-bind就会自动去vue实例里面去找当前的属性去进行设置
  • 表示绑定这个属性,绑定之后,对应的值要去vue的数据里面找,当然也可以等于一个常数,这样就不用去data里找了。
  • v-bind:可以省略成:

v-model 指令

v-model 相当于 v-on 和 v-bind

//例如:可以使用v-model 指令来实现双向数据绑定
<input v-model="test">
//本质上是
<input 
  :value="test" 
  @input="test => $event.target.value"
>
//v-on:在 input 发生时,会触发 test = $event.target.value 事件 
//v-bind:给属性 value 绑定 test 实例
  • v-model 会根据控件类型自动选取正确的方法来更新元素。
  • v-model 会忽略所有表单元素的 value、checked、selected 属性的初始值,使用的是 data 选项中声明初始值。
  • v-model 在内部为不同的输入元素使用不同的属性并抛出不同的事件:
    • select :使用 value 属性和 change 事件。
    • texttextarea :使用 value 属性和 input 事件;
    • checkboxradio :使用 checked 属性和 change 事件;
  <input v-model="message" placeholder="编辑我……">
  <p>input 表单消息是: {{ message }}</p>
    
  <textarea v-model="message2" placeholder="多行文本输入……"></textarea>
  <p>textarea 表单消息是:</p>
  <p style="white-space: pre">{{ message2 }}</p>

//
  data() {
    return {
      message: '',
      message2: '菜鸟教程\r\nhttps://www.runoob.com'
    }
  }

在文本区域 textarea 插值是不起作用,需要使用 v-model 来代替:
<!-- 错误 -->
<textarea>{{ text }}</textarea>

<!-- 正确 -->
<textarea v-model="text"></textarea>

复选框如果是一个为逻辑值,如果是多个则绑定到同一个数组:

<input type="checkbox" id="checkbox" v-model="checked">

<input type="checkbox" id="runoob" value="Runoob" v-model="checkedNames">
  <label for="runoob">Runoob</label>
  <input type="checkbox" id="google" value="Google" v-model="checkedNames">
  <label for="google">Google</label>
  <input type="checkbox" id="taobao" value="Taobao" v-model="checkedNames">
  <label for="taobao">taobao</label>

//
data() {
    return {
      checked : false,
      checkedNames: []
    }
  }

单选按钮的双向数据绑定

<input type="radio" id="runoob" value="Runoob" v-model="picked">

//
data() {
    return {
      picked : 'Runoob'
    }
  }

下拉列表的双向数据绑定

<select v-model="selected" name="site">
    <option value="">选择一个网站</option>
    <option value="www.runoob.com">Runoob</option>
    <option value="www.google.com">Google</option>
  </select>

//
data() {
    return {
      selected: '' 
    }
  }

多选时会绑定到一个数组

<select v-model="selected" name="fruit" multiple>
    <option value="www.runoob.com">Runoob</option>
    <option value="www.google.com">Google</option>
    <option value="www.taobao.com">Taobao</option>
  </select>

//
selected: '' 

v-for 循环输出选项

<select v-model="selected">
    <option v-for="option in options" :value="option.value">
      {{ option.text }}
    </option>
  </select>

//
selected: 'www.runoob.com',
      options: [
        { text: 'Runoob', value: 'www.runoob.com' },
        { text: 'Google', value: 'www.google.com' },
        { text: 'Taobao', value: 'www.taobao.com' }
      ]

值绑定
对于单选按钮,复选框及选择框的选项,v-model 绑定的值通常是静态字符串 (对于复选框也可以是布尔值):
但是有时我们可能想把值绑定到当前活动实例的一个动态属性上,这时可以用 v-bind 实现,此外,使用 v-bind 可以将输入值绑定到非字符串。

//复选框 (Checkbox):
<input type="checkbox" v-model="toggle" true-value="yes" false-value="no" />
...
// 选中时
vm.toggle === 'yes'
// 取消选中 
vm.toggle === 'no'

//单选框 (Radio):
<input type="radio" v-model="pick" v-bind:value="a" />
// 当选中时
vm.pick === vm.a

//选择框选项 (Select):
<select v-model="selected">
  <!-- 内联对象字面量 -->
  <option :value="{ number: 123 }">123</option>
</select>
// 当被选中时
typeof vm.selected // => 'object'
vm.selected.number // => 123

修饰符
.lazy
在默认情况下, v-model 在 input 事件中同步输入框的值与数据,但你可以添加一个修饰符 lazy ,从而转变为在 change 事件中同步:

<!-- 在 "change" 而不是 "input" 事件中更新 -->
<input v-model.lazy="msg" >

.number
如果想自动将用户的输入值转为 Number 类型(如果原值的转换结果为 NaN 则返回原值),可以添加一个修饰符 number 给 v-model 来处理输入值:

<input v-model.number="age" type="number">

这通常很有用,因为在 type=“number” 时 HTML 中输入的值也总是会返回字符串类型。

.trim
如果要自动过滤用户输入的首尾空格,可以添加 trim 修饰符到 v-model 上过滤输入:

<input v-model.trim="msg">

自定义指令

默认设置的核心指令( v-model 和 v-show )

<!--注册一个全局指令 v-focus, 该指令的功能是在页面加载时,元素获得焦点:-->

<div id="app">
    <p>页面载入时,input 元素自动获取焦点:</p>
    <input v-focus>
</div>
 
<script>
// 注册一个全局自定义指令 `v-focus`
const app = Vue.createApp({})
app.directive('focus', {
  // 当被绑定的元素挂载到 DOM 中时……
  mounted(el) {
    // 聚焦元素
    el.focus()
  }
})

//可以在实例使用 directives 选项来注册局部指令,这样指令只能在这个实例中使用
const app = {
   data() {
      return {   }
   },
   directives: {
      focus: {
         // 指令的定义
         mounted(el) {
            el.focus()
         }
      }
   }
}

app.mount('#app')
</script>

样式绑定

class

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

  • :class 指令也可以与普通的 class 属性共存。
  • 在带有单个根元素的自定义组件上使用 class 属性时,这些 class 将被添加到该元素中。此元素上的现有 class 将不会被覆盖
  • 如果你的组件有多个根元素,你需要定义哪些部分将接收这个类。可以使用 $attrs 组件属性执行此操作
<!DOCTYPE html>
<html lang="">
  <head>
    <meta charset="utf-8">
    <script src="https://unpkg.com/vue@next"></script>
    
    <style>
      .static {
        width: 100px;
        height: 100px;
      }
      .active {
        background: green;
      }
      .text-danger {
        background: red;
      }
    </style>
  </head>

  <body>
    <div id="hello">
      <!-- 为 v-bind:class 设置一个对象,从而动态的切换 class -->
      <div class="static" :class="{ 'active': isActive }"></div>
      <!-- 在对象中传入更多属性用来动态切换多个 class -->
      <div class="static" :class="{ 'active' : isActive, 'text-danger' : hasError }"></div>
      <!-- 直接绑定数据里的一个对象 -->
      <div class="static" :class="classObject"></div>
      <!-- 绑定一个返回对象的计算属性 -->
      <div class="static" :class="classObject2"></div>
      <!-- 可以把一个数组传给 v-bind:class -->
      <div class="static" :class="[activeClass, errorClass]"></div>
      <!-- 三元表达式来切换列表中的 class -->
      <div class="static" :class="[isActive ? activeClass : '', errorClass]"></div>
    </div>
    
    <script>
    const helloworld = {
      data() {
        return {
          isActive: true,
          hasError: false,
          classObject: {
          'active': false,
          'text-danger': true
          },
          error: null,
          activeClass: 'active',
          errorClass: 'text-danger'
        }
      },
      computed: {
        classObject2() {
          return {
            active: this.isActive && !this.error,
            'text-danger': this.error && this.error.type === 'fatal'
          }
        }
      }
    }
     
    Vue.createApp(helloworld).mount('#hello')
    </script>
  </body>
</html>

style

    <div id="hello">
      <!-- 在 v-bind:style 直接设置样式,可以简写为 :style: -->
      <div :style="{ color: activeColor, fontSize: fontSize + 'px' }">111</div>
      <!-- 直接绑定到一个样式对象,让模板更清晰: -->
      <div :style="styleObject">222</div>
      <!-- v-bind:style 可以使用数组将多个样式对象应用到一个元素上: -->
      <div :style="[baseStyles, overridingStyles]">333</div>
      <!-- 可以为 style 绑定中的 property 提供一个包含多个值的数组,常用于提供多个带前缀的值,
           这样写只会渲染数组中最后一个被浏览器支持的值。在本例中,如果浏览器支持不带浏览器前缀的 flexbox,那么就只会渲染 display: flex。 -->
      <div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>
    </div>
    
    <script>
    const helloworld = {
      data() {
        return {
          activeColor: 'red',
			    fontSize: 30,
          styleObject: {
            color: "red",
            fontSize: "30px"
          },
          baseStyles: {
            color: 'green',
            fontSize: '30px'
          },
	        overridingStyles: {
            'font-weight': 'bold'
          }
        }
      }
    }
     
    Vue.createApp(helloworld).mount('#hello')
    </script>

router 路由

    <script src="https://unpkg.com/vue@next"></script>
    <script src="https://unpkg.com/vue-router@4"></script>

<router-link> 组件用于设置一个导航链接,切换不同 HTML 内容。不用 a 标签 可以在不重新加载页面的情况下更改 URL
<router-view> 将显示与 url 对应的组件

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>
<script src="https://unpkg.com/vue@next"></script>
<script src="https://unpkg.com/vue-router@4"></script>
</head>
<body>
<div id="app">
  <p>
    <!--使用 router-link 组件进行导航 -->
    <!--通过传递 `to` 来指定链接 -->
    <!--`<router-link>` 将呈现一个带有正确 `href` 属性的 `<a>` 标签-->
    <router-link to="/">Go to Home</router-link>
    <router-link to="/about">Go to About</router-link>
  </p>
  <!-- 路由出口 -->
  <!-- 路由匹配到的组件将渲染在这里 -->
  <router-view></router-view>
</div>

<script>
// 1. 定义路由组件.
// 也可以从其他文件导入
const Home = { template: '<div>Home</div>' }
const About = { template: '<div>About</div>' }
 
// 2. 定义一些路由
// 每个路由都需要映射到一个组件。
// 我们后面再讨论嵌套路由。
const routes = [
  { path: '/', component: Home },
  { path: '/about', component: About },
]
 
// 3. 创建路由实例并传递 `routes` 配置
// 你可以在这里输入更多的配置,但我们在这里
// 暂时保持简单
const router = VueRouter.createRouter({
  // 4. 内部提供了 history 模式的实现。为了简单起见,我们在这里使用 hash 模式。
  history: VueRouter.createWebHashHistory(),
  routes, // `routes: routes` 的缩写
})
 
// 5. 创建并挂载根实例
const app = Vue.createApp({})
//确保 _use_ 路由实例使
//整个应用支持路由。
app.use(router)
 
app.mount('#app')
 
// 现在,应用已经启动了!
</script>
</body>
</html>

to 属性为目标地址, 即要显示的内容,当被点击后,内部会立刻把 to 的值传到 router.push(),所以这个值可以是一个字符串或者是描述目标位置的对象。

<!-- 字符串 -->
<router-link to="home">Home</router-link>
<!-- 渲染结果 -->
<a href="home">Home</a>

<!-- 使用 v-bind 的 JS 表达式 -->
<router-link v-bind:to="'home'">Home</router-link>

<!-- 不写 v-bind 也可以,就像绑定别的属性一样 -->
<router-link :to="'home'">Home</router-link>

<!-- 同上 -->
<router-link :to="{ path: 'home' }">Home</router-link>

<!-- 命名的路由 -->
<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>

<!-- 带查询参数,下面的结果为 /register?plan=private -->
<router-link :to="{ path: 'register', query: { plan: 'private' }}">Register</router-link>

replace
设置 replace 属性的话,当点击时,会调用 router.replace() 而不是 router.push(),导航后不会留下 history 记录。

<router-link :to="{ path: '/abc'}" replace></router-link>

append
设置 append 属性后,则在当前 (相对) 路径前添加其路径。例如,我们从 /a 导航到一个相对路径 b,如果没有配置 append,则路径为 /b,如果配了,则为 /a/b

<router-link :to="{ path: 'relative/path'}" append></router-link>

tag
有时候想要 渲染成某种标签,例如

  • 。 于是我们使用 tag prop 类指定何种标签,同样它还是会监听点击,触发导航。
  • <router-link to="/foo" tag="li">foo</router-link>
    <!-- 渲染结果 -->
    <li>foo</li>
    

    active-class
    设置 链接激活时使用的 CSS 类名。可以通过以下代码来替代。

    <style>
       ._active{
          background-color : red;
       }
    </style>
    <p>
       <router-link v-bind:to = "{ path: '/route1'}" active-class = "_active">Router Link 1</router-link>
       <router-link v-bind:to = "{ path: '/route2'}" tag = "span">Router Link 2</router-link>
    </p>
    

    注意这里 class 使用 active-class=“_active”。

    exact-active-class
    配置当链接被精确匹配的时候应该激活的 class。可以通过以下代码来替代。

    <p>
       <router-link v-bind:to = "{ path: '/route1'}" exact-active-class = "_active">Router Link 1</router-link>
       <router-link v-bind:to = "{ path: '/route2'}" tag = "span">Router Link 2</router-link>
    </p>
    

    event
    声明可以用来触发导航的事件。可以是一个字符串或是一个包含字符串的数组。

    <router-link v-bind:to = "{ path: '/route1'}" event = "mouseover">Router Link 1</router-link>
    

    以上代码设置了 event 为 mouseover ,及在鼠标移动到 Router Link 1 上时导航的 HTML 内容会发生改变。

    响应式系统

    vue3 reactive函数
    vue3 中 reactive 注意点(系列四)
    vue3
    同:将数据变成响应式数据
    异:ref用于基本数据类型,reactive是用于复杂数据类型,如对象和数组

    reactive

    import { reactive, ref } from 'vue';
    参数:必须是 json 对象或数组
    本质:就是将传入的数据包装成一个Proxy对象
    基本类型(数字、字符串、布尔值)在 reactive 中无法被创建成 proxy 对象,也就无法实现监听,无法实现响应式
    (proxy 见 es6)

    ref

    引用实例
    ref()
    ref([])
    平时我们在定义变量的时候,都是这样给他们进行类型声明的:

    // 单类型
    const msg: string = 'Hello World!';
    
    // 多类型
    const phoneNumber: number | string = 13800138000;
    

    但是在使用 ref 时,不能这样子声明,会报错,正确的声明方式应该是使用 <> 来包裹类型定义,紧跟在 ref API 之后:

    // 单类型
    const msg = ref<string>('Hello World!');
    
    // 多类型
    const phoneNumber = ref<number | string>(13800138000);
    

    Ajax(axios)

    Vue3 Ajax(axios)
    get 方法读取 JSON 数据,response.data 读取 JSON 数据
    get 方法传递参数格式
    post 方法读取 PHP 数据
    post 方法传递参数格式

    未完待续
    watch
    axios
    自定义事件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值