<?xml version="1.0" encoding="utf-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><title>行者无疆</title><link>https://xinz.run/</link><description>灵魂与肉身有一样要常在路上</description><item><title>VUE3快速入门（11）——路由的嵌套与传参</title><link>https://xinz.run/post/16.html</link><description>&lt;head&gt;&lt;/head&gt;&lt;body&gt;&lt;p&gt;&lt;img style=&quot;max-width:100%;&quot; title=&quot;202402081422145633320.png&quot; alt=&quot;202402081422145633320.png&quot; src=&quot;https://xinz.run/zb_users/upload/2024/02/202402081422145633320.png&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h1 id=&quot;h1-1.20u5D4Cu5957u8DEFu7531-5&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;1. 嵌套路由&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;1. 嵌套路由&lt;/h1&gt;&lt;h2 id=&quot;h2-1.120u4EC0u4E48u662Fu5D4Cu5957u8DEFu7531-6&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;1.1 什么是嵌套路由&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;1.1 什么是嵌套路由&lt;/h2&gt;&lt;p&gt;嵌套路由是指一个路由视图中又包含一个路由视图，通常用于多级分类的SPA。比如一个新闻SPA，分为板块与列表二级。单击不同的板块出现不同的文章列表，再点击列表则出现新闻正文。本文基于上一节内容增加新闻列表和新闻详情的展示功能。&lt;/p&gt;
&lt;h2 id=&quot;h2-1.220u521Bu5EFAu663Eu793Au65B0u95FBu8BE6u60C5u7684u89C6u56FEu7EC4u4EF6-8&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;1.2 创建显示新闻详情的视图组件&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;1.2 创建显示新闻详情的视图组件&lt;/h2&gt;&lt;p&gt;在“@/views/”路径下，新增一个Content.vue组件，HTML部分如下：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;template&amp;gt;
    &amp;lt;div id=&quot;detail&quot;&amp;gt;
        &amp;lt;h2&amp;gt;新闻标题&amp;lt;/h2&amp;gt;
        &amp;lt;p&amp;gt;这是新闻的具体内容&amp;lt;/p&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;h2-1.220u5B9Au4E49u65B0u95FBu6570u636E-18&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;1.2 定义新闻数据&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;1.2 定义新闻数据&lt;/h2&gt;&lt;p&gt;修改上一节的News.vue代码的ts部分，增加新闻数据：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&amp;lt;script lang=&quot;ts&quot; name=&quot;News&quot; setup&amp;gt;
    import { ref } from &#039;vue&#039;;
    const news_data = ref([
        {
            id: 1,
            title: &#039;新闻1&#039;,
            content: &#039;新闻内容1&#039;
        },
        {
            id: 2,
            title: &#039;新闻2&#039;,
            content: &#039;新闻内容2&#039;
        },
        {
            id: 3,
            title: &#039;新闻3&#039;,
            content: &#039;新闻内容3&#039;
        },
        {
            id: 4,
            title: &#039;新闻4&#039;,
            content: &#039;新闻内容4&#039;
        }
    ]);
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;h2-1.320u65B0u589Eu5B50u8DEFu7531u5B9Au4E49-47&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;1.3 新增子路由定义&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;1.3 新增子路由定义&lt;/h2&gt;&lt;p&gt;在路由定义文件的新闻路径下增加一个子路由：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-TypeScript&quot;&gt;import Content from &#039;@/views/Content.vue&#039;//新增引入
const router = createRouter({
    history: createWebHashHistory(),
    routes: [
        //...
        {
        name: &#039;news&#039;,
        path: &#039;/news&#039;,
        component: News,
        //增加children属性，注意为数组
        children: [
            {
                name: &#039;content&#039;,
                path: &#039;content&#039;,//注意：子路由无需再用“/”
                component: Content,
            }],
        },
        //...
    ],
})
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;h2-1.420u4FEEu6539u65B0u95FBu5217u8868u89C6u56FE-71&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;1.4 修改新闻列表视图&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;1.4 修改新闻列表视图&lt;/h2&gt;&lt;p&gt;修改News.vue的HTML部分如下：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;template&amp;gt;
    &amp;lt;h1&amp;gt;新闻列表&amp;lt;/h1&amp;gt;
    &amp;lt;div id=&quot;warpper&quot;&amp;gt;
        &amp;lt;!-- 左侧新闻列表 ---&amp;gt;
        &amp;lt;div id=&quot;list&quot;&amp;gt;
            &amp;lt;ul&amp;gt;
                &amp;lt;li v-for=&quot;item in news_data&quot; :key=&quot;item.id&quot;&amp;gt;
                    &amp;lt;p&amp;gt;&amp;lt;RouterLink :to=&#039;{path: &quot;/news/content&quot;}&#039;&amp;gt;{{ item.title }}&amp;lt;/RouterLink&amp;gt;&amp;lt;/p&amp;gt;
                &amp;lt;/li&amp;gt;
            &amp;lt;/ul&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;!-- 右侧新闻内容 --&amp;gt;
        &amp;lt;div id=&quot;content&quot;&amp;gt;
            &amp;lt;RouterView&amp;gt;&amp;lt;/RouterView&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意二级路由的写法。&lt;/p&gt;
&lt;p&gt;修改完成后，可以在新闻导航内看到左侧的新闻列表，点击链接在右侧展示的新闻内容。&lt;/p&gt;
&lt;h1 id=&quot;h1-2.20u8DEFu7531u4F20u53C2-96&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2. 路由传参&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2. 路由传参&lt;/h1&gt;&lt;p&gt;上述代码中点击每个新闻链接展示的内容都一样，现在需要根据链接展示不同的新闻，该功能需要用路由传参来实现。&lt;/p&gt;
&lt;h2 id=&quot;h2-2.120Queryu4F20u53C2-98&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2.1 Query传参&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2.1 Query传参&lt;/h2&gt;&lt;p&gt;路由定义文件见前文。&lt;/p&gt;
&lt;h3 id=&quot;h3-2.1.120u76F4u63A5u5B57u7B26u4E32u62FCu63A5uFF08u4E0Du63A8u8350uFF09-100&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2.1.1 直接字符串拼接（不推荐）&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2.1.1 直接字符串拼接（不推荐）&lt;/h3&gt;&lt;p&gt;修改New.vue的RouterLink组件调用代码：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;p&amp;gt;
    &amp;lt;RouterLink :to=&#039;`/news/content?title=${ item.title }&amp;amp;content=${ item.content }`&#039;&amp;gt;{{ item.title }}&amp;lt;/RouterLink&amp;gt;
&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意VUE的字符串模板语法：`…${变量名1}…${变量名2}…`。&lt;br&gt;修改Content.vue的代码，取参数：&lt;br&gt;ts部分：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;import { useRoute } from &#039;vue-router&#039;//引入useRoute
import { toRefs } from &#039;vue&#039;//响应式
const route = useRoute()
const { query } = toRefs(route)//从useRoute中解构query属性，该属性保存了传递的参数。
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;html部分：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;template&amp;gt;
    &amp;lt;div id=&quot;detail&quot;&amp;gt;
        &amp;lt;!-- 从query属性获取title参数--&amp;gt;
        &amp;lt;h2&amp;gt;{{ query.title }}&amp;lt;/h2&amp;gt;
        &amp;lt;!-- 从query属性获取content参数--&amp;gt;
        &amp;lt;p&amp;gt;{{ query.content }}&amp;lt;/p&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意：由于是直接把传递的参数进行动态显示，所以在解构时需要转换为响应式类型。或者不解构，则写法为：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;h2&amp;gt;{{ route.query.title }}&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;{{ route.query.content }}&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;h3-2.1.220u901Au8FC7RouterLinku7EC4u4EF6u201Ctou201Du5C5Eu6027u7684u5BF9u8C61u5199u6CD5-132&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2.1.2 通过RouterLink组件“to”属性的对象写法&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2.1.2 通过RouterLink组件“to”属性的对象写法&lt;/h3&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;RouterLink :to=
    &quot;{
        //注意路径
        path: &#039;/news/content&#039;,
        //通过query属性传递
        query: {
            title: item.title,
            content: item.content
    }}&quot;&amp;gt;{{ item.title }}&amp;lt;/RouterLink&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;h2-2.220Paramsu4F20u53C2-144&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2.2 Params传参&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2.2 Params传参&lt;/h2&gt;&lt;p&gt;首先修改路由定义：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;children: [
    {
        name: &#039;content&#039;,//在Params传参模式下，必须定义name属性
        path: &#039;content/:title/:content&#039;,//注意此处的占位符写法
        component: Content,
    },
],
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;再修改接收的代码。ts部分：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;import { useRoute } from &#039;vue-router&#039;
import { toRefs } from &#039;vue&#039;
const route = useRoute()
const { params } = toRefs(route)//从route对象解构params属性并处理响应式
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;html部分：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;template&amp;gt;
    &amp;lt;div id=&quot;detail&quot;&amp;gt;
        &amp;lt;!-- 从query属性获取title参数--&amp;gt;
        &amp;lt;h2&amp;gt;{{ params.title }}&amp;lt;/h2&amp;gt;
        &amp;lt;!-- 从query属性获取content参数--&amp;gt;
        &amp;lt;p&amp;gt;{{ params.content }}&amp;lt;/p&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;h3-2.2.120u76F4u63A5u5B57u7B26u4E32u62FCu63A5uFF08u4E0Du63A8u8350uFF09-173&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2.2.1 直接字符串拼接（不推荐）&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2.2.1 直接字符串拼接（不推荐）&lt;/h3&gt;&lt;p&gt;修改New.vue的RouterLink组件调用代码：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;p&amp;gt;&amp;lt;RouterLink :to=&#039;`/news/content/${ item.title }/${ item.content }`&#039;&amp;gt;{{ item.title }}&amp;lt;/RouterLink&amp;gt;&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;h3-2.2.220u901Au8FC7RouterLinku7EC4u4EF6u201Ctou201Du5C5Eu6027u7684u5BF9u8C61u5199u6CD5-178&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2.2.2 通过RouterLink组件“to”属性的对象写法&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2.2.2 通过RouterLink组件“to”属性的对象写法&lt;/h3&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;RouterLink :to=&quot;{
    name: &#039;content&#039;,//这里必须用name属性
    params: {//指定params
        title: item.title,
        content: item.content
    }
}&quot;&amp;gt;{{ item.title }}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;h2-2.320Propsu4F20u53C2-189&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2.3 Props传参&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2.3 Props传参&lt;/h2&gt;&lt;p&gt;Props传参可以让参数的接收变得更加简化，相当于普通组件的参数接收。先修改路由视图组件，ts部分：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;defineProps([&#039;title&#039;, &#039;content&#039;])//定义两个属性
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;html部分：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;template&amp;gt;
    &amp;lt;div id=&quot;detail&quot;&amp;gt;
        &amp;lt;h2&amp;gt;{{ title }}&amp;lt;/h2&amp;gt;
        &amp;lt;p&amp;gt;{{ content }}&amp;lt;/p&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;显然，跟普通组件的属性定义写法一模一样。&lt;br&gt;Props传参又分为布尔值、函数式、对象式三种写法。&lt;/p&gt;
&lt;h3 id=&quot;h3-2.3.120u5E03u5C14u503Cu5199u6CD5-205&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2.3.1 布尔值写法&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2.3.1 布尔值写法&lt;/h3&gt;&lt;p&gt;布尔值写法用于将&lt;strong&gt;所有params方式传递的参数&lt;/strong&gt;传递到路由视图组件。&lt;br&gt;修改路由定义文件：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;//@/router/index.js
children: [
    {
        name: &#039;content&#039;,
        path: &#039;content/:title/:content&#039;,
        component: Content,
        props: true//启用props
    },
],
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;h3-2.3.220u51FDu6570u5F0Fu5199u6CD5-219&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2.3.2 函数式写法&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2.3.2 函数式写法&lt;/h3&gt;&lt;p&gt;函数式写法用于传递部分参数，该写法需要自己定义一个名为props的函数，该函数具有一个参数，用于传递route对象，代码如下：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;children: [
    {
        name: &#039;content&#039;,
        path: &#039;content/:title/:content&#039;,
        component: Content,
        props(r){//参数r的类型为route对象
            return r.params//将所有参数全部传过去，实际上采用布尔型写法更简便
            //或返回部分参数：
            //return r.params.content
        }
    },
],
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;由于函数式写法可以操作route对象，所以可以根据实际情况传递需要使用的一部分参数，而不是一定是所有。如果为传递所有参数，则用布尔值写法更简便。&lt;/p&gt;
&lt;h3 id=&quot;h3-2.3.320u5BF9u8C61u5F0Fu5199u6CD5-236&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2.3.3 对象式写法&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2.3.3 对象式写法&lt;/h3&gt;&lt;p&gt;直接传递对象，用处不大：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;children: [
    {
        name: &#039;content&#039;,
        path: &#039;content/:title/:content&#039;,
        component: Content,
        props: {
            title: &#039;xxx&#039;,
            content: &#039;xxx&#039;
        }
    },
],
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&quot;h1-3.20u7F16u7A0Bu5F0Fu63A7u5236-252&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;3. 编程式控制&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;3. 编程式控制&lt;/h1&gt;&lt;p&gt;如果需要高级功能，如自动跳转、自定义路由标签（将RouterLink替换为button标签）、权限检查等，就必须自己实现RouterLink的功能，常见于后端系统。&lt;br&gt;修改代码，将原本的RouterLink去掉，改为单击按钮查看新闻，同时将新闻标题用普通标签展示。&lt;br&gt;html部分:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;ul&amp;gt;
    &amp;lt;li v-for=&quot;item in news_data&quot; :key=&quot;item.id&quot;&amp;gt;
        &amp;lt;p&amp;gt;
            &amp;lt;button @click=&quot;showContent(item)&quot;&amp;gt;查看&amp;lt;/button&amp;gt;
            &amp;lt;span&amp;gt;{{ item.title }}&amp;lt;/span&amp;gt;
        &amp;lt;/p&amp;gt;
    &amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ts部分：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;import { useRouter } from &#039;vue-router&#039;;//注意此处引用的是useRouter
//ts为强类型语言，定义新闻对象类型
interface news_data_type {
        id: number;
        title: string;
        content: string;
}
//实现showContent方法，传递新闻对象类型参数
function showContent(data: news_data_type) {
    router.push(
    {
        name: &#039;content&#039;,
        params: {
            title: data.title,
            content: data.content
        }
    });
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Router对象的push方法用于传递一个对象，该对象的写法与通过RouterLink组件“to”属性的对象写法一模一样。也可以用Router对象的replace方法，只是没有历史记录。（关于push与replace的区别参看上一章）&lt;/p&gt;
&lt;h1 id=&quot;h1-4.20u603Bu7ED3-289&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;4. 总结&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;4. 总结&lt;/h1&gt;&lt;ol&gt;
&lt;li&gt;子路径在定义时，写在父级路径的“children”属性下，且子路由的path属性不需要以“/”开头；&lt;/li&gt;&lt;li&gt;使用params传参时，定义路由时&lt;strong&gt;必须定义name属性&lt;/strong&gt;，同时path属性需要添加占位符，格式为“/:参数1/:参数2…”；&lt;/li&gt;&lt;li&gt;通过RouterLink组件“to”属性的对象写法进行params传参时，&lt;strong&gt;必须使用name属性而不能用path属性&lt;/strong&gt;；&lt;/li&gt;&lt;li&gt;props传参是在params传参基础上定义的，故在调用RouterLink时，仍然&lt;strong&gt;只能使用name属性&lt;/strong&gt;；&lt;/li&gt;&lt;li&gt;useRoute()创建的对象是响应式对象，但如果解构则会变成非响应式。如果需要路由参数在界面上更新，则必须用toRef、toRefs处理；&lt;/li&gt;&lt;li&gt;如果需要高级功能，如跳转、鉴权、自定义链接标签（RouterLink实际上被转换为a便签），则需要使用编程式控制路由；&lt;/li&gt;&lt;li&gt;注意useRoute与useRouter。useRoute方法返回一个Route对象， 该对象用于对路由规则进行管理；useRouter返回的是Router对象，用于执行路由动作（如跳转、传值等），可以理解为路由器；注意两者的使用场景。&lt;/li&gt;&lt;/ol&gt;
&lt;/body&gt;</description><pubDate>Wed, 19 Mar 2025 12:17:58 +0800</pubDate></item><item><title>VUE3快速入门（10）——路由的基础使用</title><link>https://xinz.run/post/14.html</link><description>&lt;head&gt;&lt;/head&gt;&lt;body&gt;&lt;p&gt;&lt;img style=&quot;max-width:100%;&quot; title=&quot;202402081422145633320.png&quot; alt=&quot;202402081422145633320.png&quot; src=&quot;https://xinz.run/zb_users/upload/2024/02/202402081422145633320.png&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h1 id=&quot;h1-1.20u4EC0u4E48u662Fu8DEFu7531-5&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;1. 什么是路由&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;1. 什么是路由&lt;/h1&gt;&lt;p&gt;路由是指根据不同的URL加载不同的组件，其典型应用是后台页面，点击不同的菜单显示不同的页面。通过使用路由，能实现SPA页面、无刷新加载、部分页面加载的功能，是VUE最为典型的一种功能。&lt;/p&gt;
&lt;h1 id=&quot;h1-2.20u51C6u5907u5DE5u4F5C-8&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2. 准备工作&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2. 准备工作&lt;/h1&gt;&lt;h2 id=&quot;h2-2.120u642Du5EFAu5BFCu822Au533Au4E0Eu5C55u793Au533Au6846u67B6-9&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2.1 搭建导航区与展示区框架&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2.1 搭建导航区与展示区框架&lt;/h2&gt;&lt;p&gt;本文实现一个功能：导航有三个按钮，分别是“首页”、“新闻”、“关于”。点击三个按钮在展示区显示不同的页面。&lt;br&gt;App.vue代码如下：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;template&amp;gt;
    &amp;lt;!--这是导航区--&amp;gt;
      &amp;lt;nav&amp;gt;
        &amp;lt;ol&amp;gt;
          &amp;lt;li&amp;gt;&amp;lt;a href=&quot;#&quot;&amp;gt;首页&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
          &amp;lt;li&amp;gt;&amp;lt;a&amp;gt;新闻&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
          &amp;lt;li&amp;gt;&amp;lt;a&amp;gt;关于&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
        &amp;lt;/ol&amp;gt;
      &amp;lt;/nav&amp;gt;
    &amp;lt;!--这是展示区--&amp;gt;
      &amp;lt;div id=&quot;content&quot;&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;h2-2.220u521Bu5EFAu8DEFu7531u89C6u56FEu9875-26&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2.2 创建路由视图页&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2.2 创建路由视图页&lt;/h2&gt;&lt;p&gt;在源码目录下新建views目录，用于单独存放路由视图组件，目录内建立Home.vue、News.vue、About.vue，分别对应“首页”、“新闻”、“关于”的具体内容。具体代码略。&lt;/p&gt;
&lt;h2 id=&quot;h2-2.320u5B89u88C5u8DEFu7531-28&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2.3 安装路由&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2.3 安装路由&lt;/h2&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;npm install vue-router
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;上述代码将会自动安装VUE3的路由组件。&lt;/p&gt;
&lt;h1 id=&quot;h1-3.20u4F7Fu7528u8DEFu7531-34&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;3. 使用路由&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;3. 使用路由&lt;/h1&gt;&lt;h2 id=&quot;h2-3.120u5B9Au4E49u8DEFu7531uFF08Historyu6A21u5F0FuFF09-35&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;3.1 定义路由（History模式）&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;3.1 定义路由（History模式）&lt;/h2&gt;&lt;p&gt;在源码目录新建目录router，再创建index.ts文件作为路由定义文件。&lt;br&gt;首先引用路由以及需要使用的路由视图：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;import { createRouter, createWebHistory } from &#039;vue-router&#039;
//三个准备好的路由视图
import Home from &#039;@/views/Home.vue&#039;
import News from &#039;@/views/News.vue&#039;
import About from &#039;@/views/About.vue&#039;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;其次定义路由，关键是路径与路由视图的对应关系：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;const router = createRouter({
  //路由模式
  history: createWebHistory(),
  //路由映射关系
  routes: [
    {
      path: &#039;/home&#039;,//路径 
      component: Home,//加载的组件 
    },
    {
      path: &#039;/news&#039;,
      component: News,
    },
    {
      path: &#039;/about&#039;,
      component: About,
    }
  ],
})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;createRouter函数中传入对象的history属性用于指定路由模式为“WebHistory”模式，routes用于指明路径与页面的映射关系，类型为键值对数组。&lt;br&gt;&lt;strong&gt;注意：创建路由时，必须指定使用哪一种路由模式。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;记得将定义好的路由暴露出去&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;export default router
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;h2-3.220u52A0u8F7Du8DEFu7531-75&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;3.2 加载路由&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;3.2 加载路由&lt;/h2&gt;&lt;p&gt;在main.ts入口文件中，引用定义好的路由，在原始代码基础上新增如下代码：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;import router from &#039;@/router/index&#039;
app.use(router)//注意该代码放在const app = createApp(App)之后
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;h2-3.320u5904u7406u89C6u56FE-82&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;3.3 处理视图&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;3.3 处理视图&lt;/h2&gt;&lt;p&gt;首先添加引用：import { RouterLink, RouterView } from ‘vue-router’&lt;br&gt;其次将App.vue的a标签替换为RouterLink组件：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;li&amp;gt;&amp;lt;RouterLink to=&quot;/home&quot;&amp;gt;首页&amp;lt;/RouterLink&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;RouterLink to=&quot;/news&quot;&amp;gt;新闻&amp;lt;/RouterLink&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;RouterLink to=&quot;/about&quot;&amp;gt;关于&amp;lt;/RouterLink&amp;gt;&amp;lt;/li&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;最后在原本要展示内容的位置写上RouterView标签：&lt;br&gt;&amp;lt;RouterView&amp;gt;&amp;lt;/RouterView&amp;gt;&lt;/p&gt;
&lt;p&gt;最终效果：在页面上点击三个按钮，可以看到浏览器地址的路径在变化，同时页面展示区显示了三个按钮对应的页面。&lt;/p&gt;
&lt;h1 id=&quot;h1-4.20u66F4u6362u8DEFu7531u6A21u5F0FuFF08Hashu6A21u5F0FuFF09-95&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;4. 更换路由模式（Hash模式）&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;4. 更换路由模式（Hash模式）&lt;/h1&gt;&lt;p&gt;在上述示例代码中使用了History模式，现在替换为Hash模式。修改路由定义文件@/router/index.js&lt;br&gt;更改引用：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;import { createRouter, createWebHashHistory } from &#039;vue-router&#039;
//...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;更改创建路由的代码：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;const router = createRouter({
  history: createWebHashHistory(),//此处修改为了createWebHashHistory
  //...
})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;此时浏览器中出现了一个“/#/”部分。&lt;/p&gt;
&lt;h1 id=&quot;h1-5.20RouterLinku7EC4u4EF6u201Ctou201Du5C5Eu6027u7684u4E24u79CDu5199u6CD5-111&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;5. RouterLink组件“to”属性的两种写法&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;5. RouterLink组件“to”属性的两种写法&lt;/h1&gt;&lt;h2 id=&quot;h2-5.120u5B57u7B26u4E32u5199u6CD5-112&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;5.1 字符串写法&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;5.1 字符串写法&lt;/h2&gt;&lt;p&gt;见前文。&lt;/p&gt;
&lt;h2 id=&quot;h2-5.220u5BF9u8C61u5199u6CD5-114&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;5.2 对象写法&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;5.2 对象写法&lt;/h2&gt;&lt;h3 id=&quot;h3-5.2.120u5BF9u8C61u7684u8DEFu5F84u5C5Eu6027-115&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;5.2.1 对象的路径属性&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;5.2.1 对象的路径属性&lt;/h3&gt;&lt;p&gt;代码如下：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;li&amp;gt;&amp;lt;RouterLink :to=&quot;{path:&#039;/home&#039;}&quot;&amp;gt;首页&amp;lt;/RouterLink&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;RouterLink :to=&quot;{path:&#039;/news&#039;}&quot;&amp;gt;新闻&amp;lt;/RouterLink&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;RouterLink :to=&quot;{path:&#039;/about}&quot;&amp;gt;关于&amp;lt;/RouterLink&amp;gt;&amp;lt;/li&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;该写法传入了一个包含path属性的对象。&lt;/p&gt;
&lt;h3 id=&quot;h3-5.2.120u5BF9u8C61u7684u540Du5B57u5C5Eu6027uFF08u547Du540Du8DEFu7531uFF09-123&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;5.2.1 对象的名字属性（命名路由）&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;5.2.1 对象的名字属性（命名路由）&lt;/h3&gt;&lt;p&gt;修改路由定义文件，增加name属性：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;//@/router/index.ts
const router = createRouter({
  history: createWebHashHistory(),
  routes: [
    {
      name: &#039;home&#039;,
      path: &#039;/home&#039;,
      component: Home,
    }
    //...
  ],
})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;将对象写法的path属性改为name即可：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;li&amp;gt;&amp;lt;RouterLink :to=&quot;{name:&#039;home&#039;}&quot;&amp;gt;首页&amp;lt;/RouterLink&amp;gt;&amp;lt;/li&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&quot;h1-6.20u5904u7406u5386u53F2u8BB0u5F55-144&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;6. 处理历史记录&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;6. 处理历史记录&lt;/h1&gt;&lt;p&gt;RouterLink组件有两种模式，push与replace。push模式允许从浏览器后退而replace不行，&lt;strong&gt;默认为push模式&lt;/strong&gt;。修改为replace模式仅需增加replace选项即可：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;RouterLink replace :to=&quot;{name:&#039;home&#039;}&quot;&amp;gt;首页&amp;lt;/RouterLink&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&quot;h1-7.20u91CDu5B9Au5411-150&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;7. 重定向&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;7. 重定向&lt;/h1&gt;&lt;p&gt;重定向可以让某个路径转到到另一个已存在的路径：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;  routes: [
    //...
    {
      path: &#039;/&#039;,
      redirect: &#039;/home&#039;,
    }
  ],
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;上述代码将默认首页跳转到了/home路径。&lt;/p&gt;
&lt;h1 id=&quot;h1-8.20u6CE8u610Fu4E8Bu9879-163&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;8. 注意事项&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;8. 注意事项&lt;/h1&gt;&lt;ol&gt;
&lt;li&gt;在定义路由时，必须指定路由的模式；&lt;/li&gt;&lt;li&gt;定义好的路由记得在入口文件中引用；&lt;/li&gt;&lt;li&gt;路由链接必须使用专门的RouterLink组件，视图显示也必须使用专门的RouterView组件；&lt;/li&gt;&lt;li&gt;&lt;strong&gt;当视图不显示时，对应的视图组件是被卸载了而不是被隐藏了&lt;/strong&gt;；&lt;/li&gt;&lt;li&gt;history模式浏览器地址没有“#”号，但&lt;strong&gt;需要服务端处理路径问题&lt;/strong&gt;，SEO友好；而hash模式带有“#”号，服务端无需特别处理，SEO较差；最佳实践：To C用history，To B用Hash；&lt;/li&gt;&lt;li&gt;注意编码规范，为了区分一般组件和路由视图组件，最好把路由视图组件单独放在pages或views目录下。&lt;/li&gt;&lt;/ol&gt;
&lt;/body&gt;</description><pubDate>Tue, 18 Mar 2025 18:23:35 +0800</pubDate></item><item><title>关于“拓源纯净主题”引发的Undefined array key &amp;quot;pro&amp;quot; 的修复</title><link>https://xinz.run/post/15.html</link><description>&lt;head&gt;&lt;/head&gt;&lt;body&gt;&lt;p&gt;&lt;img style=&quot;max-width:100%;&quot; title=&quot;&quot; alt=&quot;null&quot; src=&quot;https://xinz.run/zb_users/upload/2024/11/202411231918389149767.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;本博客使用的是由&lt;a title=&quot;拓源&quot; href=&quot;https://www.toyean.com/&quot;&gt;拓源&lt;/a&gt; 推出的“纯净主题”。目前发现一个由于IP查询接口触发的问题，导致主题需要显示IP归属地的页面（如留言、评论页等）会出现如下错误：&lt;br&gt;&lt;img style=&quot;max-width:100%;&quot; title=&quot;&quot; alt=&quot;null&quot; src=&quot;https://xinz.run/zb_users/upload/2024/11/202411231853373066158.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;经检查，该主题的 tpure_IP函数使用了一个“&lt;a href=&quot;https://whois.pconline.com.cn/ipJson.jsp”&quot;&gt;https://whois.pconline.com.cn/ipJson.jsp”&lt;/a&gt; 接口查询IP归属地，但该接口不稳定，时常返回空，所以触发了上述问题。修改方式如下：&lt;/p&gt;
&lt;h1 id=&quot;h1-120u5B9Au4F4Du5230u51FDu6570-8&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;1 定位到函数&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;1 定位到函数&lt;/h1&gt;&lt;p&gt;在该主题的安装目录下（位置：/zblog的安装目录/zb_users/theme/tpure）,打开includes.php 在编辑器中按“Ctrl+F”搜索函数：tpure_IP。找到如下代码：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;function tpure_IP($ip)
{
     $ch = curl_init();
     $url = &#039;https://whois.pconline.com.cn/ipJson.jsp?ip=&#039;.$ip;
     curl_setopt($ch, CURLOPT_URL, $url);
     curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
     curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER, false );
     curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
     $location = curl_exec($ch);
     curl_close($ch);
     $location = mb_convert_encoding($location, &#039;utf-8&#039;,&#039;GB2312&#039;);
     $location = substr($location, strlen(&#039;({&#039;)+strpos($location, &#039;({&#039;),(strlen($location) - strpos($location, &#039;})&#039;))*(-1));
     $location = str_replace(&#039;&quot;&#039;,&quot;&quot;,str_replace(&quot;:&quot;,&quot;=&quot;,str_replace(&quot;,&quot;,&quot;&amp;amp;&quot;,$location)));
     parse_str($location,$ip_location);
     return $ip_location[&#039;pro&#039;];
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&quot;h1-220u66F4u6362u67E5u8BE2u63A5u53E3uFF0Cu5B9Eu73B0u81EAu5DF1u7684u89E3u6790u65B9u5F0F-28&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2 更换查询接口，实现自己的解析方式&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2 更换查询接口，实现自己的解析方式&lt;/h1&gt;&lt;p&gt;在function tpure_IP($ip)代码前增加函数ip_parser($ip)，完整代码如下：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;function ip_query($ip)
{
    $url = &quot;https://opendata.baidu.com/api.php?query={$ip}&amp;amp;co=&amp;amp;resource_id=6006&amp;amp;oe=utf8&quot;;//此处使用百度API
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false );
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    $location = curl_exec($ch);
    curl_close($ch);
    $ip_obj = json_decode($location, true);
    
    if(0 != count($ip_obj[&#039;data&#039;]) &amp;amp;&amp;amp; array_key_exists(&#039;location&#039;, $ip_obj[&#039;data&#039;][0]))
        return $ip_obj[&#039;data&#039;][0][&#039;location&#039;];
    else
        return &#039;未知&#039;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;注意，该代码一定要放在tpure_IP函数的前面。&lt;/strong&gt;&lt;/p&gt;
&lt;h1 id=&quot;h1-320u6CE8u91CAu539Fu6765u7684u4EE3u7801uFF0Cu8C03u7528u65B0u7684u51FDu6570-50&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;3 注释原来的代码，调用新的函数&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;3 注释原来的代码，调用新的函数&lt;/h1&gt;&lt;p&gt;将tpure_IP函数体内的代码全部用&lt;code&gt;/**/&lt;/code&gt;注释，并在最后添加ip_query的调用代码，如下：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;function tpure_IP($ip)
{
    /*
    $ch = curl_init();
     $url = &#039;https://whois.pconline.com.cn/ipJson.jsp?ip=&#039;.$ip;
     curl_setopt($ch, CURLOPT_URL, $url);
     curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
     curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER, false );
     curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
     $location = curl_exec($ch);
     curl_close($ch);
     $location = mb_convert_encoding($location, &#039;utf-8&#039;,&#039;GB2312&#039;);
     $location = substr($location, strlen(&#039;({&#039;)+strpos($location, &#039;({&#039;),(strlen($location) - strpos($location, &#039;})&#039;))*(-1));
     $location = str_replace(&#039;&quot;&#039;,&quot;&quot;,str_replace(&quot;:&quot;,&quot;=&quot;,str_replace(&quot;,&quot;,&quot;&amp;amp;&quot;,$location)));
     parse_str($location,$ip_location);
     return $ip_location[&#039;pro&#039;];
     */
     return ip_query($ip);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;相当于不再使用原本的实现，而使用自己的实现，但函数名称不变，保存即可。有动手能力的大佬也可以将API换成其他的，但是解析代码也同样要换。&lt;/p&gt;
&lt;p&gt;点击下列链接可以下载本人修改好的文件进行替换。&lt;strong&gt;请注意备份好源文件！！！&lt;/strong&gt;&lt;br&gt;&lt;a href=&quot;https://115.com/s/swh71iv3ntr?password=xinz&quot;&gt;include.php&lt;/a&gt;&lt;/p&gt;
&lt;/body&gt;</description><pubDate>Sat, 23 Nov 2024 18:49:25 +0800</pubDate></item><item><title>VUE3快速入门（9）——插槽</title><link>https://xinz.run/post/13.html</link><description>&lt;head&gt;&lt;/head&gt;&lt;body&gt;&lt;p&gt;&lt;img title=&quot;202402081422145633320.png&quot; alt=&quot;202402081422145633320.png&quot; src=&quot;https://xinz.run/zb_users/upload/2024/02/202402081422145633320.png&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;插槽可以实现组件的样式由调用者决定的功能。本文讲述了默认插槽、具名插槽以及作用域插槽的三种使用方式。&lt;/p&gt;
&lt;h1 id=&quot;h1-1-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;1. 什么是插槽&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;1. 什么是插槽&lt;/h1&gt;&lt;p&gt;插槽是指组件的部分或全部HTML样式由调用者决定，即动态的Template。例如组件的列表有可能是无序列表、有序列表或图片列表，无法在设计组件时指定，在这种情况下需要使用插槽。&lt;/p&gt;
&lt;h1 id=&quot;h1-2-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2. 默认插槽&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2. 默认插槽&lt;/h1&gt;&lt;p&gt;默认插槽类似HTML的嵌套标签。本节在上一节的基础上对员工列表组件进行改造(WorkerTableEx)，上一节组件的列表标题使用了&amp;lt;h1&amp;gt;标签，但调用者可能希望行换成其他的形式，这里使用默认插槽实现。&lt;/p&gt;
&lt;p&gt;组件代码如下：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;template&amp;gt;
    &amp;lt;slot&amp;gt;&amp;lt;/slot&amp;gt;&amp;lt;!-- 使用默认插槽形成占位符 --&amp;gt;
    &amp;lt;table id=&quot;main&quot;&amp;gt;
        &amp;lt;!-- 表格部分省略 --&amp;gt;
    &amp;lt;/table&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;则调用该组件的代码为：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;WorkerTableEx&amp;gt;&amp;lt;h2&amp;gt;部门：办公室&amp;lt;/h2&amp;gt;&amp;lt;/WorkerTableEx&amp;gt;
&amp;lt;WorkerTableEx&amp;gt;&amp;lt;p&amp;gt;部门：办公室&amp;lt;/p&amp;gt;&amp;lt;/WorkerTableEx&amp;gt;
&amp;lt;WorkerTableEx&amp;gt;&amp;lt;img src=&quot;...&quot;/&amp;gt;&amp;lt;/WorkerTableEx&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这样，表格的标题展示形式由调用者决定，它可以是头部标题、段落或者图片以及其他。&lt;/p&gt;
&lt;p&gt;通过在&amp;lt;template&amp;gt;中使用&amp;lt;slot&amp;gt;&amp;lt;/slot&amp;gt;形成占位符，当调用者在组件标签中插入HTML片段或另一个组件时，VUE将会把插入的内容放到占位符中（有几个占位符就放几个）。&lt;/p&gt;
&lt;h1 id=&quot;h1-3-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;3. 具名插槽&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;3. 具名插槽&lt;/h1&gt;&lt;p&gt;有时希望多个占位符展示的内容不一样，这种情况需要使用具名插槽。假如要求表格底部可以显示备注信息，这就需要与展示标题的插槽区分开来：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;template&amp;gt;
    &amp;lt;slot name=&quot;title&quot;&amp;gt;&amp;lt;/slot&amp;gt;&amp;lt;!-- 使用具名插槽，标题显示部分 --&amp;gt;
    &amp;lt;table id=&quot;main&quot;&amp;gt;
        &amp;lt;!-- 表格部分代码省略 --&amp;gt;
    &amp;lt;/table&amp;gt;
    &amp;lt;slot name=&quot;description&quot;&amp;gt;&amp;lt;/slot&amp;gt;&amp;lt;!-- 使用具名插槽，备注显示部分 --&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;则调用该组件的代码为：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;WorkerTableEx&amp;gt;
    &amp;lt;template v-slot:title&amp;gt;&amp;lt;!-- 使用v-slot指令 --&amp;gt;
        &amp;lt;h3&amp;gt;部门：办公室&amp;lt;/h3&amp;gt;
    &amp;lt;/template&amp;gt;

    &amp;lt;template #description&amp;gt;&amp;lt;!-- v-slot语法糖 --&amp;gt;
        &amp;lt;p&amp;gt;导出时间：2024年6月26日&amp;lt;/p&amp;gt;
    &amp;lt;/template&amp;gt;
&amp;lt;/WorkerTableEx&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;提示：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;使用v-slot指令可以指明内容放在组件的哪个插槽内，同时v-slot指令可以简写为“#”。&lt;/li&gt;&lt;li&gt;v-slot指令只能用在&amp;lt;template&amp;gt;标签和组件标签上，不能用在HTML标签上，因此使用具名插槽必须把普通HTML代码用&amp;lt;template&amp;gt;标签包裹。&lt;/li&gt;&lt;li&gt;由于使用了具名插槽，因此组件展示的内容顺序与调用者的编码顺序无关。&lt;/li&gt;&lt;/ul&gt;
&lt;h1 id=&quot;h1-4-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;4. 作用域插槽&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;4. 作用域插槽&lt;/h1&gt;&lt;p&gt;有时会有这样的需求：数据由组件生成（如请求服务器得到后端数据），但展示形式却由调用者决定，这种情况需要使用作用域插槽。作用域插槽常见于UI框架。&lt;/p&gt;
&lt;p&gt;继续改造WorkerTableEx组件，其中该组件仅提供数据（员工、部门及导出时间）以及头部、正文和注脚三个具名插槽：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;let ajax_data = ref(
    {
        workers:  [
            {id: 1234, sex: true, name: &quot;张三&quot;, tel: &quot;13600000000&quot;},
            {id: 1235, sex: false, name: &quot;李四&quot;, tel: &quot;13600000001&quot;},
            {id: 1235, sex: false, name: &quot;王五&quot;, tel: &quot;13600000002&quot;},
            {id: 1234, sex: false, name: &quot;赵六&quot;}
        ],
        department: &quot;技术部&quot;,
        exp_t: &quot;2024年6月27日20:22:37&quot;
    });//实际开发从应从服务器获取
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;组件的模板部分：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;template&amp;gt;
    &amp;lt;slot :title=&quot;ajax_data.title&quot; name=&quot;header&quot;&amp;gt;&amp;lt;/slot&amp;gt;
    &amp;lt;slot :workers=&quot;ajax_data.workers&quot; name=&quot;content&quot;&amp;gt;&amp;lt;/slot&amp;gt;
    &amp;lt;slot :exp_t=&quot;ajax_data.exp_t&quot; name=&quot;footer&quot;&amp;gt;&amp;lt;/slot&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;上述代码使用了具名作用域插槽，将ajax_data的title、workers和exp_t属性分别绑定到三个不同的具名插槽。&lt;/p&gt;
&lt;p&gt;则调用者的代码为：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;WorkerTableEx&amp;gt;

    &amp;lt;template #header=&quot;parame&quot;&amp;gt;
        &amp;lt;h3&amp;gt;部门：{{ parame.title }}&amp;lt;/h3&amp;gt;
    &amp;lt;/template&amp;gt;

    &amp;lt;template #footer=&quot;parame&quot;&amp;gt;
        &amp;lt;p&amp;gt;导出时间：{{ parame.exp_t }}&amp;lt;/p&amp;gt;
    &amp;lt;/template&amp;gt;

    &amp;lt;template #content=&quot;parame&quot;&amp;gt;
        &amp;lt;table id=&quot;main&quot;&amp;gt;
            &amp;lt;thead&amp;gt;
                &amp;lt;tr&amp;gt;
                    &amp;lt;th scope=&quot;col&quot;&amp;gt;员工号码&amp;lt;/th&amp;gt;
                    &amp;lt;th scope=&quot;col&quot;&amp;gt;姓名&amp;lt;/th&amp;gt;
                    &amp;lt;th scope=&quot;col&quot;&amp;gt;性别&amp;lt;/th&amp;gt;
                    &amp;lt;th scope=&quot;col&quot;&amp;gt;电话&amp;lt;/th&amp;gt;
                &amp;lt;/tr&amp;gt;
            &amp;lt;/thead&amp;gt;
            &amp;lt;tbody&amp;gt;
                &amp;lt;tr v-for=&quot; (item, index) in parame.workers&quot; :key=&quot;item.id&quot;&amp;gt;
                    &amp;lt;th scope=&quot;col&quot;&amp;gt;{{ item.id }}&amp;lt;/th&amp;gt;
                    &amp;lt;td scope=&quot;col&quot;&amp;gt;{{ item.name }}&amp;lt;/td&amp;gt;
                    &amp;lt;td scope=&quot;col&quot;&amp;gt;{{ item.sex ? &#039;男&#039; : &#039;女&#039; }}&amp;lt;/td&amp;gt;
                    &amp;lt;td scope=&quot;col&quot;&amp;gt;{{ item.tel }}&amp;lt;/td&amp;gt;
                &amp;lt;/tr&amp;gt;
            &amp;lt;/tbody&amp;gt;
        &amp;lt;/table&amp;gt;
    &amp;lt;/template&amp;gt;

&amp;lt;/WorkerTableEx&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;提示：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;无论组件传递了几个属性，即使分部在不同的插槽上，均会被打包成一个对象供调用者接收，调用者可以用任意名字（如上述代码中的“parame”）接收该对象。&lt;/li&gt;&lt;li&gt;由于接收的数据是对象，因此调用者可以直接解构：&lt;/li&gt;&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&amp;lt;template #header=&quot;{title}&quot;&amp;gt;
    &amp;lt;h3&amp;gt;部门：{{ title }}&amp;lt;/h3&amp;gt;
&amp;lt;/template&amp;gt;
&amp;lt;template #header=&quot;{exp_t}&quot;&amp;gt;
    &amp;lt;h3&amp;gt;部门：{{ exp_t }}&amp;lt;/h3&amp;gt;
&amp;lt;/template&amp;gt;
//...
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;需熟悉的语法糖，调用者接收数据还有如下写法：&lt;/li&gt;&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;template v-slot:header=&quot;{title}&quot;&amp;gt;
&amp;lt;!--&amp;lt;template v-slot:插槽名=&quot;用于接收数据的名称&quot;&amp;gt;--&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;需熟悉的语法糖，组件绑定数据还有如下写法：&lt;/li&gt;&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;slot v-bind=&quot;{workers: ajax_data.workers}&quot; name=&quot;content&quot;&amp;gt;&amp;lt;/slot&amp;gt;
&amp;lt;!--&amp;lt;slot v-bind=&quot;{属性名: 属性值}&quot; name=&quot;content&quot;&amp;gt;&amp;lt;/slot&amp;gt;--&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;由于语法糖的存在，使得插槽存在多种写法，需要熟悉。尤其是在阅读一些框架代码的时候。&lt;/li&gt;&lt;/ul&gt;
&lt;/body&gt;</description><pubDate>Mon, 24 Jun 2024 11:34:52 +0800</pubDate></item><item><title>VUE3快速入门（8）——属性</title><link>https://xinz.run/post/12.html</link><description>&lt;head&gt;&lt;/head&gt;&lt;body&gt;&lt;p&gt;&lt;img style=&quot;max-width:100%;&quot; title=&quot;202402081422145633320.png&quot; alt=&quot;202402081422145633320.png&quot; src=&quot;https://xinz.run/zb_users/upload/2024/02/202402081422145633320.png&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;本文讲述了组件属性的实现方法，以及如何限制属性的数据类型。&lt;/p&gt;
&lt;h1 id=&quot;h1-1.20u4EC0u4E48u662Fu7EC4u4EF6u7684u5C5Eu6027-7&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;1. 什么是组件的属性&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;1. 什么是组件的属性&lt;/h1&gt;&lt;p&gt;组件的属性是指可以由组件的调用者动态设置的参数，组件在运行时根据这些参数展现调用者需要的数据。组件的属性等同于HTML标签的属性。&lt;/p&gt;
&lt;h1 id=&quot;h1-2.20u6700u7B80u5355u7684u4E00u4E2Au5C5Eu6027-10&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2. 最简单的一个属性&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2. 最简单的一个属性&lt;/h1&gt;&lt;p&gt;本节实现一个展现员工信息的列表，第一步先传入一个“department”属性用于显示员工所属的部门。&lt;/p&gt;
&lt;h2 id=&quot;h2-2.120u5C5Eu6027u7684u5B9Au4E49-13&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2.1 属性的定义&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2.1 属性的定义&lt;/h2&gt;&lt;p&gt;定义属性：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;import { defineProps } from &quot;vue&quot;;//引入defineProps，该函数属于宏函数，实际无需引入
let props = defineProps([&quot;department&quot;]);//声明department为一个属性
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;defineProps方法传入一个&lt;strong&gt;字符串数组&lt;/strong&gt;，其内容是将要被设为属性的变量名称。该方法同时返回一个对象，该对象由传入该组件所有属性的名称和值组成。&lt;/p&gt;
&lt;p&gt;模板部分：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;template&amp;gt;
    &amp;lt;p&amp;gt;所属部门： {{ department }}&amp;lt;/p&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;h2-2.220u4F7Fu7528u7EC4u4EF6u5E76u8BBEu7F6Eu5C5Eu6027-29&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2.2 使用组件并设置属性&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2.2 使用组件并设置属性&lt;/h2&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&amp;lt;WorkerTable department=&quot;宣传科&quot;&amp;gt;&amp;lt;/WorkerTable&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&quot;h1-3.20u5F3Au5236u7C7Bu578Bu9650u5B9A-34&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;3. 强制类型限定&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;3. 强制类型限定&lt;/h1&gt;&lt;p&gt;接下来新增一个属性：data，该属性是描述员工信息的数组，用于表格展示。其中模板部分如下：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;template&amp;gt;
    &amp;lt;h1&amp;gt;所属部门:{{ department }}&amp;lt;/h1&amp;gt;
    &amp;lt;table id=&quot;main&quot;&amp;gt;
        &amp;lt;thead&amp;gt;
            &amp;lt;tr&amp;gt;
                &amp;lt;th scope=&quot;col&quot;&amp;gt;员工号码&amp;lt;/th&amp;gt;
                &amp;lt;th scope=&quot;col&quot;&amp;gt;姓名&amp;lt;/th&amp;gt;
                &amp;lt;th scope=&quot;col&quot;&amp;gt;性别&amp;lt;/th&amp;gt;
                &amp;lt;th scope=&quot;col&quot;&amp;gt;电话&amp;lt;/th&amp;gt;
            &amp;lt;/tr&amp;gt;
        &amp;lt;/thead&amp;gt;
        &amp;lt;tbody&amp;gt;
            &amp;lt;tr v-for=&quot; (item, index) in data&quot; :key=&quot;item.id&quot;&amp;gt;
                &amp;lt;th scope=&quot;col&quot;&amp;gt;{{ item.id }}&amp;lt;/th&amp;gt;
                &amp;lt;td scope=&quot;col&quot;&amp;gt;{{ item.name }}&amp;lt;/td&amp;gt;
                &amp;lt;td scope=&quot;col&quot;&amp;gt;{{ item.sex ? &#039;男&#039; : &#039;女&#039; }}&amp;lt;/td&amp;gt;
                &amp;lt;td scope=&quot;col&quot;&amp;gt;{{ item.tel }}&amp;lt;/td&amp;gt;
            &amp;lt;/tr&amp;gt;
        &amp;lt;/tbody&amp;gt;
    &amp;lt;/table&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;根据模板的展示需求，员工信息需要包括ID、姓名、性别、电话等字段，如果上级组件传入的属性数据不符合员工字段的要求，则组件会出现显示异常。为避免这样的问题，需要检查属性数据的类型，当类型不符合要求时，禁止上级组件的属性赋值。&lt;/p&gt;
&lt;h2 id=&quot;h2-3.120u5B9Au4E49u65B0u7C7Bu578B-62&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;3.1 定义新类型&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;3.1 定义新类型&lt;/h2&gt;&lt;p&gt;利用TS的接口类，定义一个员工数据类型，并导出：（建议新建一个名为WorkerTable的文件夹，该文件夹包含一个子文件夹src，用于存放组件的辅助代码，而组件的入口文件则与src同级）&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;//file：@/component/WorkerTable/src/IWorker.ts
export interface IWorker{
    // 序列号
    id: number,

    // 姓名
    name: string,

    // 性别
    sex: boolean,

    // 电话(可选)
    tel?: string
}

export type IWorkerArray = IWorker[];
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;该文件定义了一个员工类：IWorker以及它的数组类型：IWorkerArray。&lt;/p&gt;
&lt;h2 id=&quot;h2-3.220u7C7Bu578Bu68C0u67E5-84&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;3.2 类型检查&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;3.2 类型检查&lt;/h2&gt;&lt;p&gt;修改组件TS代码：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;import { type IWorkerArray } from &quot;@/components/WorkerTable/src/IWorker&quot;;
defineProps&amp;lt;{department: string, data: IWorkerArray}&amp;gt;();//通过泛型进行类型检查并声明属性
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;上述代码有两个注意点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;引入类型需要使用type关键字&lt;/li&gt;&lt;li&gt;通过泛型的方式进行类型检查时，&lt;strong&gt;所有属性&lt;/strong&gt;均需进行类型检查（要么所有，要么都不）&lt;/li&gt;&lt;/ul&gt;
&lt;h2 id=&quot;h2-3.320u5C5Eu6027u8D4Bu503C-94&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;3.3 属性赋值&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;3.3 属性赋值&lt;/h2&gt;&lt;p&gt;最后调用该组件的TS部分：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;import WorkerTable from &#039;@/components/WorkerTable/WorkeTable.vue&#039;;
import { ref } from &quot;vue&quot;;

let workers = ref([
    {id: 1234, sex: true, name: &quot;张三&quot;, tel: &quot;13600000000&quot;},
    {id: 1235, sex: false, name: &quot;李四&quot;, tel: &quot;13600000001&quot;},
    {id: 1235, sex: false, name: &quot;王五&quot;, tel: &quot;13600000002&quot;},
    {id: 1234, sex: false, name: &quot;赵六&quot;}
]);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;也可以向ref（reactive）传递泛型，在此处限定workers的类型：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;import { type IWorkerArray } from &#039;@/components/WorkerTable/src/IWorker&#039;;
import { ref } from &quot;vue&quot;;

let workers = ref&amp;lt;IWorkerArray&amp;gt;(...);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;但由于WorkerTable组件已经进行了类型检查，因此上述代码的写法似乎没必要。&lt;/p&gt;
&lt;p&gt;模板部分：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;WorkerTable department=&quot;办公室&quot; :data=&quot;workers&quot;&amp;gt;&amp;lt;/WorkerTable&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;当传入的属性不符合类型要求时，代码将无法运行，避免显示异常。&lt;/li&gt;&lt;li&gt;属性的“：”表示后面的内容作为表达式解析，如果不加“：”，则将会把“workers”作为字符串而不是变量，也可使用 v-bind指令进行属性绑定：&lt;/li&gt;&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;WorkerTable department=&quot;办公室&quot; v-bind:data=&quot;workers&quot;&amp;gt;&amp;lt;/WorkerTable&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&quot;h1-4.20u53EFu9009u5C5Eu6027u4E0Eu9ED8u8BA4u503C-127&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;4. 可选属性与默认值&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;4. 可选属性与默认值&lt;/h1&gt;&lt;p&gt;某些时候允许调用者不对属性赋值，因此需要使用可选属性。当调用者不赋值时，有时需自动给出默认值。修改组件TS代码：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;//file: @/component/WorkerTable/WorkerTable.vue
import { type IWorkerArray } from &quot;@/components/WorkerTable/src/IWorker&quot;;
import { withDefaults } from &quot;vue&quot;;

withDefaults(defineProps&amp;lt;{department?: string, data?: IWorkerArray}&amp;gt;(), {
    department: &quot;默认部门&quot;,
    data: () =&amp;gt; [{id: 0, sex: true, name: &quot;默认&quot;, tel: &quot;0000&quot;}]
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这样当调用者不对该组件进行任何属性(或仅部分)的赋值，就会显示默认数据：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;WorkerTable&amp;gt;&amp;lt;/WorkerTable&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;withDefaults的两个参数分别为defineProps声明的属性、由默认属性组成的对象。&lt;/li&gt;&lt;li&gt;在属性声明后加“？”表示可选属性，如果没有“？”则为必选属性，调用者不赋值会出错。&lt;/li&gt;&lt;li&gt;对象类型的默认值必须以函数的形式返回。&lt;/li&gt;&lt;/ul&gt;
&lt;/body&gt;</description><pubDate>Sun, 23 Jun 2024 14:20:46 +0800</pubDate></item><item><title>VUE3快速入门（7）——监视</title><link>https://xinz.run/post/11.html</link><description>&lt;head&gt;&lt;/head&gt;&lt;body&gt;&lt;p&gt;&lt;img title=&quot;202402081422145633320.png&quot; alt=&quot;202402081422145633320.png&quot; src=&quot;https://xinz.run/zb_users/upload/2024/02/202402081422145633320.png&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;本文讲述了监视基础数据类、对象数据类的方法。&lt;/p&gt;
&lt;h1 id=&quot;h1-1-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;1. 什么是监视&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;1. 什么是监视&lt;/h1&gt;&lt;p&gt;监视是指，当被监视的对象发生变化时，执行某个逻辑，类似于控件的消息事件。从被监视的数据类型分类，可分为监视ref创建的普通类型、ref创建的对象类型、reactive创建的对象类型三类；从被监视数据的完整与否又可分为监视整个对象和监视部分属性。&lt;/p&gt;
&lt;h1 id=&quot;h1-2-ref-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2. ref类型的监视&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2. ref类型的监视&lt;/h1&gt;&lt;h2 id=&quot;h2-2-1-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2.1 基础类型&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2.1 基础类型&lt;/h2&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;import { ref, watch } from &#039;vue&#039;//引入watch
let input_content = ref(0);//创建一个基础数据类型
//使用watch方法实现监视
watch(input_content, (newVal, oldVal)=&amp;gt;{
    console.log(&quot;值：&quot;, newVal, oldVal)
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;关于watch方法的参数：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;参数1： 需要时监视的变量；&lt;/li&gt;&lt;li&gt;参数2： 回调函数，其中有两个传入参数，分别为新值和的值；也可以只有一个参数，即为新值；&lt;/li&gt;&lt;li&gt;参数3： 配置对象，用于指定一些其他功能，如立即监视、深度监视等。&lt;/li&gt;&lt;/ul&gt;
&lt;h2 id=&quot;h2-2-2-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2.2 监视整个对象&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2.2 监视整个对象&lt;/h2&gt;&lt;p&gt;监视由ref定义的对象类型，其实是在监控&lt;strong&gt;对象类型的地址&lt;/strong&gt;，因此部分字段的更新不会触发监视，需要&lt;strong&gt;手动开启深度监视&lt;/strong&gt;。在这种情况下，任何一个字段的变化都会触发监视。&lt;/p&gt;
&lt;p&gt;例子：监控员工年龄变化，当到达35岁时让其卷铺盖走人。&lt;br&gt;HTML部分：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;button @click=&quot;add()&quot;&amp;gt;+1&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;JS部分：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;import { ref, watch } from &#039;vue&#039;//引入watch

let worker = ref({
    name: &quot;张三&quot;,
    age: 32
});

function add(): any
{
    worker.value.age += 1;
}

const stop = watch(worker, (newVal, oldVal)=&amp;gt;{
    console.log(&quot;值：&quot;, newVal, oldVal)
        
    if(newVal.age &amp;gt; 35)
    {
        alert(&quot;卷铺盖走人&quot;);
        stop();//停止监视
    }
}, {deep: true});//第三个参数开启深度监视
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;提示：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;上述代码中，watch返回了一个函数，调用该函数时会停止当前的监视；&lt;/li&gt;&lt;li&gt;watch的第三个参数开启了深度监视选项，这样仅变化对象成员时，也会触发监视调用；&lt;/li&gt;&lt;li&gt;控制台打印的newVal, oldVal值均相同，因为对象的地址没有发生变化。&lt;/li&gt;&lt;/ul&gt;
&lt;h2 id=&quot;h2-2-3-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2.3 监视对象的属性(部分监视)&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2.3 监视对象的属性(部分监视)&lt;/h2&gt;&lt;p&gt;很多时候，我们仅需要关注对象的某几个字段是否发生了变化，即部分监视。对象的部分属性又可能是基础类型，也可能是一个嵌套的对象。因此部分监视又分为基础数据类型和对象数据类型两种。&lt;/p&gt;
&lt;h3 id=&quot;h3-2-3-1-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2.3.1 属性为基础数据类型&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2.3.1 属性为基础数据类型&lt;/h3&gt;&lt;p&gt;需要将被监视的数据包装为getter函数&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;import { ref, watch } from &#039;vue&#039;//引入watch

let worker = ref({
    name: &quot;张三&quot;,
    age: 32
});

function add(): any
{
    worker.value.age += 1;
}

const stop = watch(()=&amp;gt;{ return worker.value.age }, (newVal, oldVal)=&amp;gt;{
    console.log(&quot;值：&quot;, newVal, oldVal)

    if(newVal &amp;gt; 35)
    {
        alert(&quot;卷铺盖走人&quot;);
        stop();//停止监视
    }
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意箭头函数也可以简写成：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;()=&amp;gt; worker.value.age
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;h3-2-3-2-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2.3.2 属性为对象类型&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2.3.2 属性为对象类型&lt;/h3&gt;&lt;p&gt;即嵌套对象，修改worker代码，增加银行存款账户的嵌套对象类属性：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;let worker = ref({
    name: &quot;张三&quot;,
    age: 32,
    accounts:
    {
        icbc: 2000,
        bc: 1200
    }
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;增加存款和清零的功能：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;button @click=&quot;icbc()&quot;&amp;gt;存入工行&amp;lt;/button&amp;gt;
&amp;lt;button @click=&quot;bc()&quot;&amp;gt;存入中行&amp;lt;/button&amp;gt;
&amp;lt;button @click=&quot;clear()&quot;&amp;gt;清零存款&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;function icbc()
{
    //改变accounts的一个属性
     worker.value.accounts.icbc += 1000;
}

function bc()
{
    //改变accounts的一个属性
    worker.value.accounts.bc += 1000;
}

function clear()
{
    //改变整个accounts
    worker.value.accounts = {bc: 0, icbc: 0};
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;仅监视存款清零：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;watch(() =&amp;gt; worker.value.accounts, (newVal, oldVal)=&amp;gt;{
    console.log(&quot;账户变动：&quot;, newVal, oldVal)
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;监视存款清零和增加存款：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;watch(() =&amp;gt; worker.value.accounts, (newVal, oldVal)=&amp;gt;{
    console.log(&quot;存款清零：&quot;, newVal, oldVal)
},{deep: true});//开启了深度监视
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;提示：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;与整个对象的监视不同，&lt;strong&gt;部分监视即使该部分是对象，也必须写成getter函数形式，在这种情况下监视的是部分对象的地址&lt;/strong&gt;；&lt;/li&gt;&lt;li&gt;监视嵌套对象的内部属性，开启深度监视即可;&lt;/li&gt;&lt;li&gt;最佳编码方式是，由ref创建的对象，只要是部分监视，则一律写成getter函数。&lt;/li&gt;&lt;/ul&gt;
&lt;h1 id=&quot;h1-3-reactive-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;3. reactive类型的监视&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;3. reactive类型的监视&lt;/h1&gt;&lt;p&gt;将worker修改为由reactive定义的响应式对象，特别注意整体修改accounts属性的写法：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;function clear()
{
    Object.assign(worker.accounts, {bc: 0, icbc: 0});
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;监视accounts属性：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;watch(worker.accounts, (newVal, oldVal)=&amp;gt;{
    console.log(&quot;账户变动：&quot;, newVal, oldVal)
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;当accounts内部或整体变化时，均能触发监视。&lt;br&gt;&lt;strong&gt;提示：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;监视由reactive创建的对象，其默认开启了深度监视。&lt;/li&gt;&lt;/ul&gt;
&lt;h1 id=&quot;h1-4-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;4. 监视多个数据&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;4. 监视多个数据&lt;/h1&gt;&lt;p&gt;监视多个数据时，只需要将它们放到一个数组中作为一个整体即可。&lt;br&gt;例如，同时监控两个账户的变化：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;watch([()=&amp;gt; worker.value.accounts.icbc, () =&amp;gt; worker.value.accounts.bc], (val) =&amp;gt; {
    console.log(&quot;同时监视两个账户&quot;, val);
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;提示：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;数组内元素的具体写法需遵守基础数据、嵌套对象数据的监视写法；&lt;/li&gt;&lt;li&gt;回调函数的传入参数也就变成了数组。&lt;/li&gt;&lt;/ul&gt;
&lt;h1 id=&quot;h1-5-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;5. 最佳实践&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;5. 最佳实践&lt;/h1&gt;&lt;p&gt;本节涉及的情况较多，但就开发而言，推荐选用最稳的情况：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;使用ref创建响应式对象（支持整体替换）；&lt;/li&gt;&lt;li&gt;在上述前提下，一律使用getter函数作为监视源（即使它是嵌套的对象），再视情况决定是否开启深度监视。&lt;/li&gt;&lt;/ul&gt;
&lt;h1 id=&quot;h1-6-watcheffect&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;6. watchEffect&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;6. watchEffect&lt;/h1&gt;&lt;p&gt;watchEffect用于自动推断要监视的变量，适合需要同时监控多个变量的场合。&lt;br&gt;例子：监控员工的年龄、存款&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;const stop = watchEffect(()=&amp;gt;{
    if(worker.value.age &amp;gt; 35)
    {
        alert(&quot;卷铺盖走人&quot;);
    }
        
    if(worker.value.accounts.icbc &amp;gt;= 10000 || worker.value.accounts.bc &amp;gt;= 10000)
    {
        //其他逻辑
    }
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;提示：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;watchEffect能自动判断需要监视的内容；&lt;/li&gt;&lt;li&gt;watchEffect会&lt;strong&gt;立即执行一次监视&lt;/strong&gt;；&lt;/li&gt;&lt;li&gt;watchEffect的返回值也是一个函数，用于停止监视。&lt;/li&gt;&lt;/ul&gt;
&lt;/body&gt;</description><pubDate>Thu, 16 May 2024 11:23:22 +0800</pubDate></item><item><title>VUE3快速入门（6）——计算属性</title><link>https://xinz.run/post/10.html</link><description>&lt;head&gt;&lt;/head&gt;&lt;body&gt;&lt;p&gt;&lt;img title=&quot;202402081422145633320.png&quot; alt=&quot;202402081422145633320.png&quot; src=&quot;https://xinz.run/zb_users/upload/2024/02/202402081422145633320.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;本节讲述了Vue3的计算属性的用法。&lt;/p&gt;
&lt;hr&gt;
&lt;h1 id=&quot;h1-1-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;1. 什么是计算属性&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;1. 什么是计算属性&lt;/h1&gt;&lt;p&gt;计算属性用于对一些需要展示到模板上的数据进行处理，虽然用函数也能实现，但&lt;strong&gt;计算属性会自动缓存，只有值发生变化时才重新计算，加快运行效率&lt;/strong&gt;。&lt;/p&gt;
&lt;h1 id=&quot;h1-2-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2. 基本使用方法&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2. 基本使用方法&lt;/h1&gt;&lt;p&gt;本节实现一个功能，将输入的电话号码隐去中间四位。&lt;/p&gt;
&lt;h2 id=&quot;h2-2-1-computed&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2.1 引用computed&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2.1 引用computed&lt;/h2&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;import { computed } from &#039;vue&#039;;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;h2-2-2-computed-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2.2 使用computed方法定义一个计算属性&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2.2 使用computed方法定义一个计算属性&lt;/h2&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;let encoded_tel = computed(() =&amp;gt; {
    let part_1 = worker.value.tel.substring(0, 3);
    let part_2 = worker.value.tel.slice(-4);
    return part_1 + &quot;****&quot; + part_2;
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;其中worker是由ref定义的响应式数据，通过输入框修改电话号码并实时显示的方法参考上一节：&lt;a title=&quot;VUE3快速入门（5）——响应式数据&quot; href=&quot;https://xinz.run/post/9.html&quot;&gt;VUE3快速入门（5）——响应式数据&lt;/a&gt;。&lt;/p&gt;
&lt;h2 id=&quot;h2-2-3-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2.3 在模板中使用&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2.3 在模板中使用&lt;/h2&gt;&lt;p&gt;将上一节的模板变量改为：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;h2&amp;gt;电话号码： {{ encoded_tel }}&amp;lt;/h2&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这样，当输入电话号码并点击“修改”后，号码将隐去中间四位。&lt;/p&gt;
&lt;h1 id=&quot;h1-3-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;3. 计算属性的读写性&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;3. 计算属性的读写性&lt;/h1&gt;&lt;p&gt;如果要通过代码修改计算属性的值，则：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;function changeComputed()
{
    encoded_tel.value = &quot;...&quot;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;h2-3-1-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;3.1 只读&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;3.1 只读&lt;/h2&gt;&lt;p&gt;第二节定义计算属性的方式属于只读属性，采用上述方法修改计算属性的值会报错。&lt;/p&gt;
&lt;h2 id=&quot;h2-3-2-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;3.2 可读可写&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;3.2 可读可写&lt;/h2&gt;&lt;p&gt;要修改计算属性的值，必须定义getter和setter：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;let encoded_tel = computed(() =&amp;gt; {
    get(){
        let part_1 = worker.value.tel.substring(0, 3);
        let part_2 = worker.value.tel.slice(-4);
        return part_1 + &quot;****&quot; + part_2;
    },
    set(val){
        //针对val的逻辑处理代码
    }
});
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&quot;h1-4-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;4. 总结&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;4. 总结&lt;/h1&gt;&lt;ol&gt;
&lt;li&gt;计算属性与函数类似，但计算属性有缓存，如多次调用其值不变，则仅计算一次；&lt;/li&gt;&lt;li&gt;计算属性如果要通过代码修改值，则必须定义getter和setter；&lt;/li&gt;&lt;li&gt;对计算属性的value字段赋值，&lt;strong&gt;仅仅触发setter的调用，实际上并没有修改任何值，还需要在setter里面编写逻辑处理代码！&lt;/strong&gt;&lt;/li&gt;&lt;/ol&gt;
&lt;/body&gt;</description><pubDate>Tue, 23 Apr 2024 13:40:46 +0800</pubDate></item><item><title>VUE3快速入门（5）——响应式数据</title><link>https://xinz.run/post/9.html</link><description>&lt;head&gt;&lt;/head&gt;&lt;body&gt;&lt;p&gt;&lt;img title=&quot;202402081422145633320.png&quot; alt=&quot;202402081422145633320.png&quot; src=&quot;https://xinz.run/zb_users/upload/2024/02/202402081422145633320.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;本节讲述了如何用ref和reactive实现基本数据类型和对象数据类型的响应式更新，同时讲述了在何种情况下会失去响应式功能以及对应的解决办法。&lt;/p&gt;
&lt;hr&gt;
&lt;h1 id=&quot;h1-1-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;1. 什么是响应式&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;1. 什么是响应式&lt;/h1&gt;&lt;p&gt;响应式是指当变量的值变化后，&amp;lt;template&amp;gt;的内容同步自动更新。Vue2的选项式API中的data默认为响应式，但Vue3的组合式API为非响应式，即无法自动更新。因此需要用ref和reactive进行处理。&lt;/p&gt;
&lt;h1 id=&quot;h1-2-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2.基本数据类型的响应式处理&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2.基本数据类型的响应式处理&lt;/h1&gt;&lt;p&gt;基本数据类型是指字符串和数字，&lt;strong&gt;这种类型只能用ref处理&lt;/strong&gt;。&lt;/p&gt;
&lt;h2 id=&quot;h2-2-1-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2.1 表单输入的响应式更新&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2.1 表单输入的响应式更新&lt;/h2&gt;&lt;p&gt;本节实现HTML标签实时显示表单内容的功能。&lt;/p&gt;
&lt;p&gt;在上一节的基础上增加一个HTML元素，用来实时显示表单的输入值：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;h2&amp;gt;input框的内容： {{ input_content }}&amp;lt;/h2&amp;gt;
&amp;lt;input v-model=&quot;input_content&quot;/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;修改&amp;lt;script&amp;gt;代码：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;import { ref } from &#039;vue&#039;
let input_content = ref(&#039;&#039;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;对比上一节代码(2.2小节)，input_content此时通过ref进行了定义。执行代码，当在input框内输入数据时，&amp;lt;h2&amp;gt;标签的内容将同步更新，此时的input_content为响应式数据。&lt;/p&gt;
&lt;h2 id=&quot;h2-2-2-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2.2 代码操作的响应式更新&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2.2 代码操作的响应式更新&lt;/h2&gt;&lt;p&gt;本节实现按钮单击实时更改HTML标签内容的功能。&lt;/p&gt;
&lt;p&gt;新增按钮并绑定事件：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;button @click=&quot;add()&quot;&amp;gt;+1&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;事件处理方法：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;function add()
{
    input_content.value += 1;//注意：必须通过“ref的实例名.value.字段”的形式更新
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;单击按钮，页面上的数字加1，即通过代码实现了页面的更新。&lt;/p&gt;
&lt;h1 id=&quot;h1-3-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;3. 对象数据类型的响应式处理&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;3. 对象数据类型的响应式处理&lt;/h1&gt;&lt;p&gt;对象数据类的响应式处理既可以用ref又可以用reactive。&lt;/p&gt;
&lt;p&gt;本节将实现通过输入框更改对象的一个字段，并实时显示的功能。&amp;lt;template&amp;gt;部分代码如下：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;h2&amp;gt;电话号码： {{ worker.tel }}&amp;lt;/h2&amp;gt;&amp;lt;!--注意此处对象实例.字段的写法，不受ref或reactive的影响--&amp;gt;
&amp;lt;input v-model=&quot;tel&quot;/&amp;gt;
&amp;lt;button @click=&quot;changeTel(tel)&quot;&amp;gt;修改电话&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;h2-3-1-ref-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;3.1 通过ref处理&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;3.1 通过ref处理&lt;/h2&gt;&lt;p&gt;定义表单绑定的变量、事件方法，并通过ref定义一个对象：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;import { ref } from &#039;vue&#039;
let worker = ref({
    name: &quot;Jesse&quot;,
    age: 12,
    mail: &quot;3898*******@qq.com&quot;,
    tel: &quot;136****615&quot;
});

let tel = &quot;&quot;;

function changeTel(content: any): any
{
    worker.value.tel = content;//同样通过“ref的实例名.value.字段”的形式更新
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;输入新的号码并点击按钮，将更新worker对象的tel字段，且在页面同步更新。&lt;/p&gt;
&lt;h2 id=&quot;h2-3-2-reactive-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;3.2 通过reactive处理&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;3.2 通过reactive处理&lt;/h2&gt;&lt;p&gt;修改代码如下：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;import { reactive } from &#039;vue&#039;
let worker = reactive({
    name: &quot;Jesse&quot;,
    age: 12,
    mail: &quot;3898*******@qq.com&quot;,
    tel: &quot;136****615&quot;
});

let tel = &quot;&quot;;

function changeTel(content: any): any
{
    worker.tel = content;//注意此处与ref的区别，不再需要.value
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&quot;h1-4-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;4. 丢失响应功能的情况&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;4. 丢失响应功能的情况&lt;/h1&gt;&lt;p&gt;当整体替换对象或解构对象时，可能会丢失响应式功能。&lt;/p&gt;
&lt;h2 id=&quot;h2-4-1-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;4.1 对象类型的字段批量更新&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;4.1 对象类型的字段批量更新&lt;/h2&gt;&lt;p&gt;很多时候希望将服务器返回的数据直接赋值给对象，从而更新多个的字段。在JS/TS里，服务器返回的数据被视为一个新的对象，如果采用直接赋值的方式会失去响应式功能。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;//之前定义的对象
let worker = reactive({
    name: &quot;Jesse&quot;,
    age: 12,
    mail: &quot;3898*******@qq.com&quot;,
    tel: &quot;136****615&quot;
});

function getPost(content: any): any
{
    let ajax_obj = JSON.parse(content);//解码JSON，转换成对象
    /*
    假设ajax_obj对象如下：
    {
        name: &quot;Alice&quot;,
        age: 14,
        mail: &quot;1234*******@qq.com&quot;,
        tel: &quot;132****777&quot;
    }
    */
    
    worker = reactive(ajax_obj)//尝试通过这样的方式更新多个字段的内容将会失去响应式功能。
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;h3-4-1-1-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;4.1.1 逐字段赋值&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;4.1.1 逐字段赋值&lt;/h3&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;function getPost(content: any): any
{
    let ajax_obj = JSON.parse(content);//解码JSON，转换成对象
    
    worker.name = ajax_obj.name;
    wroker.age = ajax_obj.age;
    //...
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这种方法适合字段较少的情况。&lt;/p&gt;
&lt;h3 id=&quot;h3-4-1-2-object-assgin&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;4.1.2 使用Object.assgin&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;4.1.2 使用Object.assgin&lt;/h3&gt;&lt;p&gt;Object.assgin的主要功能是对象合并，第一个参数是原始对象，后面的参数是要合并的多个对象。但使用Object.assgin在某些情况可能不适用。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;function getPost(content: any): any
{
    let ajax_obj = JSON.parse(content);//解码JSON，转换成对象
    
    worker = Object.assgin(worker, ajax_obj);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;h3-4-1-3-ref&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;4.1.3 使用ref&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;4.1.3 使用ref&lt;/h3&gt;&lt;p&gt;将原始对象的定义改为ref即可。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;//之前定义的对象
let worker = ref({
    name: &quot;Jesse&quot;,
    //...
});

function getPost(content: any): any
{
    let ajax_obj = JSON.parse(content);//解码JSON，转换成对象
    
    worker.value = ajax_obj;//通过value属性直接赋值
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;h3-4-1-4-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;4.1.4 嵌套定义，变为部分字段更新&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;4.1.4 嵌套定义，变为部分字段更新&lt;/h3&gt;&lt;p&gt;如果非要用reactive且不想用Object.assgin，则可以采用此方法。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;//之前定义的对象
let worker =reactive({
    data: {
        name: &quot;Jesse&quot;,
        //...
    }
});

function getPost(content: any): any
{
    let ajax_obj = JSON.parse(content);//解码JSON，转换成对象
    
    worker.data = ajax_obj;//相当于只更新data字段
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;h2-4-2-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;4.2 提取一个或多个字段的值&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;4.2 提取一个或多个字段的值&lt;/h2&gt;&lt;p&gt;有时只需要使用对象的部分字段，则经过对象的解构后，新定义的变量将失去响应功能。如：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;let worker = ref({
    name: &quot;Jesse&quot;,
    //...
});

let {name, age} = worker;//提取worker中的部分字段，这样定义会让name, age丢失响应功能
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;h3-4-2-1-torefs-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;4.2.1 使用toRefs批量处理&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;4.2.1 使用toRefs批量处理&lt;/h3&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;import { toRefs } from &#039;vue&#039;
let {name, age} = toRefs(worker);//此时name和age为响应式
//注意更新数据仍然需要使用.value
name.value = &quot;...&quot;;
age.value += 1;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;h3-4-2-2-toref-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;4.2.2 使用toRef逐个处理&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;4.2.2 使用toRef逐个处理&lt;/h3&gt;&lt;p&gt;toRef方法的参数为：toRef(源对象，字段名)&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;import { toRef } from &#039;vue&#039;
let name = toRef(worker, &#039;name&#039;);//此时name和age为响应式
let age = toRef(worker, &#039;age&#039;);//此时name和age为响应式
//注意更新数据仍然需要使用.value
name.value = &quot;...&quot;;
age.value += 1;
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&quot;h1-5-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;5. 关于对象重新赋值导致响应式失效的解释&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;5. 关于对象重新赋值导致响应式失效的解释&lt;/h1&gt;&lt;ol&gt;
&lt;li&gt;&lt;p&gt;ref 定义数据（包括对象）时，都会变成 RefImpl(Ref 引用对象) 类的实例，无论是修改还是重新赋值都会调用 setter，都会经过 reactive 方法处理为响应式对象。&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;但是 reactive 定义数据（必须是对象），是直接调用 reactive 方法处理成响应式对象。如果重新赋值，就会丢失原来响应式对象的引用地址，变成一个新的引用地址，这个新的引用地址指向的对象是没有经过 reactive 方法处理的，所以是一个普通对象，而不是响应式对象。解构同理。&lt;/p&gt;
&lt;/li&gt;&lt;/ol&gt;
&lt;h1 id=&quot;h1-6-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;6. 总结&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;6. 总结&lt;/h1&gt;&lt;ul&gt;
&lt;li&gt;组合式API必须通过ref和reactive定义数据才能实现响应式功能；&lt;/li&gt;&lt;li&gt;模板中使用对象的某个字段，直接通过“{{实例名.字段名}}”实现，不受ref或reactive的影响；&lt;/li&gt;&lt;li&gt;ref能处理任何数据，但reactive只能定义对象类型；&lt;/li&gt;&lt;li&gt;ref的更新必须通过.value字段，reactive直接赋值；&lt;/li&gt;&lt;li&gt;特别注意，当需要用后端返回的对象去替换（无论返回的对象字段内容有几个跟源对象不一致）源对象时，如果整体直接赋值可能将丢掉响应式功能；&lt;/li&gt;&lt;li&gt;特别注意，如果解构对象还需要保持响应式，则需要用toRefs或toRef处理。&lt;/li&gt;&lt;/ul&gt;
&lt;/body&gt;</description><pubDate>Mon, 15 Apr 2024 11:21:47 +0800</pubDate></item><item><title>VUE3快速入门（4）——Setup语法糖与数据绑定</title><link>https://xinz.run/post/8.html</link><description>&lt;head&gt;&lt;/head&gt;&lt;body&gt;&lt;p&gt;&lt;img title=&quot;202402081422145633320.png&quot; alt=&quot;202402081422145633320.png&quot; src=&quot;https://xinz.run/zb_users/upload/2024/02/202402081422145633320.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;本文讲述了如何使用Setup语法糖简化代码，以及如何获取表单数据。在本系列后续的文章中，均使用setup语法糖写法。&lt;/p&gt;
&lt;hr&gt;
&lt;h1 id=&quot;h1-1-setup-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;1. Setup语法糖&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;1. Setup语法糖&lt;/h1&gt;&lt;p&gt;使用Setup导出数据或者方法必须使用return，当代码过多时就变得复杂。使用Setup语法糖无需显式声明要导出的内容，也不必再写setup方法名。&lt;/p&gt;
&lt;h2 id=&quot;h2-1-1-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;1.1 声明组件导出&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;1.1 声明组件导出&lt;/h2&gt;&lt;p&gt;首先将&amp;lt;script&amp;gt;代码中的setup方法部分全部移除，仅留下组件导出声明：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&amp;lt;script lang=&quot;ts&quot;&amp;gt;
export default {
    name: &quot;MyComp&quot;,
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;h2-1-2-setup-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;1.2 创建setup语法糖&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;1.2 创建setup语法糖&lt;/h2&gt;&lt;p&gt;其次，新增一个&amp;lt;script&amp;gt;片段，如下：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&amp;lt;script lang=&quot;ts&quot; setup&amp;gt;
    
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;lang属性对应的语言必须与上一个&amp;lt;script&amp;gt;的代码语言一致，不得JS、TS混用；&lt;/li&gt;&lt;li&gt;setup语法糖所在的&amp;lt;script&amp;gt;必须增加一个setup属性&lt;/li&gt;&lt;/ol&gt;
&lt;h2 id=&quot;h2-1-3-setup-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;1.3 在setup语法糖标签内写代码&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;1.3 在setup语法糖标签内写代码&lt;/h2&gt;&lt;p&gt;最后将原本setup方法里面的内容除了return外全部放入后一个&amp;lt;script&amp;gt;标签内，完整代码如下：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&amp;lt;script lang=&quot;ts&quot; setup&amp;gt;
    let author = &quot;Jesse&quot;;
    let mail = &quot;3898xxxx@qq.com&quot;;
    let tel = &quot;136****615&quot;;
    
    function add(a: number, b: number): number{
        return a + b;
    }

    function show(content: any): any
    {
        alert(content);
    }
    
    //无需return {author, mail, ...}
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这样，凡是在setup语法糖内定义的数据和方法全部自动导出，不用再return。&lt;/p&gt;
&lt;h1 id=&quot;h1-2-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2. 数据绑定&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2. 数据绑定&lt;/h1&gt;&lt;p&gt;数据绑定是指获取表单中填写的值。&lt;/p&gt;
&lt;h2 id=&quot;h2-2-1-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2.1 创建一个表单&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2.1 创建一个表单&lt;/h2&gt;&lt;p&gt;在合适位置增加一个表单标签： &amp;lt;input name=””/&amp;gt;&lt;/p&gt;
&lt;h2 id=&quot;h2-2-2-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2.2 创建变量并绑定表单的值&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2.2 创建变量并绑定表单的值&lt;/h2&gt;&lt;p&gt;创建一个变量，用于接收表单的值：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;let input_content = &quot;&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在表单标签内使用v-model指令将表单值与该变量绑定：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;input name=&quot;&quot; v-model=&quot;input_content&quot;/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;h2-2-3-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2.3 测试&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2.3 测试&lt;/h2&gt;&lt;p&gt;修改button的click事件，单击时弹出表单的值：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;button @click=&quot;show(input_content)&quot;&amp;gt;单击&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;其中show方法代码：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;function show(content: any): any
{
    alert(content);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&quot;h1-3-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;3. 总结&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;3. 总结&lt;/h1&gt;&lt;ol&gt;
&lt;li&gt;使用setup语法糖就无需再显式声明导出的内容，但要求两个&amp;lt;script&amp;gt;片段语言类型一致；&lt;/li&gt;&lt;li&gt;v-model指令用于将表单值与变量绑定；&lt;/li&gt;&lt;li&gt;v-model指令仅能用于表单相关的标签。&lt;/li&gt;&lt;/ol&gt;
&lt;/body&gt;</description><pubDate>Sat, 13 Apr 2024 08:51:56 +0800</pubDate></item><item><title>VUE3快速入门（3）——方法与事件</title><link>https://xinz.run/post/7.html</link><description>&lt;head&gt;&lt;/head&gt;&lt;body&gt;&lt;p&gt;&lt;img title=&quot;202402081422145633320.png&quot; alt=&quot;202402081422145633320.png&quot; src=&quot;https://xinz.run/zb_users/upload/2024/02/202402081422145633320.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;本文讲述了如何在自定义组件中定义并调用方法，以及绑定DOM事件响应的方法。&lt;/p&gt;
&lt;hr&gt;
&lt;h1 id=&quot;h1-1-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;1. 自定义方法&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;1. 自定义方法&lt;/h1&gt;&lt;h2 id=&quot;h2-1-1-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;1.1 定义一个方法&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;1.1 定义一个方法&lt;/h2&gt;&lt;p&gt;在&amp;lt;script&amp;gt;标签内的setup方法内增加一个add方法，该方法传入两个参数，用于求和：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;function add(a: number, b: number): number{
    return a + b;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;同时，将add方法暴露（返回）：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;return {author, mail, tel, add};//author, mail, tel是上一节定义的变量
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;h2-1-2-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;1.2 调用方法&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;1.2 调用方法&lt;/h2&gt;&lt;p&gt;在&amp;lt;template&amp;gt;标签内，适当位置增加一个标签，用于调用方法：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;h2&amp;gt;调用add方法： {{add(1,1)}}&amp;lt;/h2&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;h2-1-3-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;1.3 查看结果&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;1.3 查看结果&lt;/h2&gt;&lt;p&gt;编译、构建成功后，浏览器新出现“调用add方法： 2”的字样，说明求和方法被成功调用。&lt;/p&gt;
&lt;h1 id=&quot;h1-2-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2. 绑定事件&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2. 绑定事件&lt;/h1&gt;&lt;p&gt;前端开发少不了处理DOM事件，如单击、获得焦点等。本节将讲述如何绑定常见的web标签事件。&lt;/p&gt;
&lt;h2 id=&quot;h2-2-1-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2.1 绑定一个事件&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2.1 绑定一个事件&lt;/h2&gt;&lt;p&gt;在&amp;lt;template&amp;gt;标签内，适当位置增加一个按钮，绑定click方法：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;button @click=&quot;show(tel)&quot;&amp;gt;点我&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;单击会调用test函数，并传入tel的值，该值在上一节已经定义：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;let author = &quot;Jesse&quot;;
let mail = &quot;3898xxxx@qq.com&quot;;
let tel = &quot;136****615&quot;;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;h2-2-2-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2.2 完善事件处理方法&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2.2 完善事件处理方法&lt;/h2&gt;&lt;p&gt;在&amp;lt;script&amp;gt;标签内setup方法内，再增加show方法，该方法具有一个传输参数：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;function show(content: any): any
{
    alert(content);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;同时记得暴露该方法：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;return {author, mail, tel, add, show};//author, mail, tel是上一节定义的变量
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;h2-2-3-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;2.3 执行&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2.3 执行&lt;/h2&gt;&lt;p&gt;编译、构建成功后，浏览器会出现一个按钮，点击按钮，将弹出对话框，其内容是tel变量的内容。&lt;/p&gt;
&lt;h1 id=&quot;h1-3-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;3. 总结&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;3. 总结&lt;/h1&gt;&lt;ol&gt;
&lt;li&gt;方法与变量一样需要写在methods属性内。&lt;/li&gt;&lt;li&gt;&lt;a class=&quot;at-link&quot; title=&quot;@click&quot; href=&quot;https://github.com/click&quot;&gt;@click&lt;/a&gt;=”&amp;lt;方法名&amp;gt;”其实是v-on:click=”&amp;lt;方法名&amp;gt;”的简写。&lt;/li&gt;&lt;li&gt;除了click外，还有submit、scroll的其他的DOM事件均可采用此方法进行事件处理。&lt;/li&gt;&lt;/ol&gt;
&lt;h1 id=&quot;h1-4-&quot;&gt;&lt;a class=&quot;reference-link&quot; name=&quot;4. 拓展学习与思考&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;4. 拓展学习与思考&lt;/h1&gt;&lt;ol&gt;
&lt;li&gt;除了v-on指令外，学习v-if、v-show、v-for的用法。&lt;/li&gt;&lt;li&gt;尝试处理submit、onfocus等其他常见DOM事件。&lt;/li&gt;&lt;/ol&gt;
&lt;/body&gt;</description><pubDate>Thu, 08 Feb 2024 21:44:14 +0800</pubDate></item></channel></rss>